removed chef vendor

This commit is contained in:
William Mantly 2020-04-11 22:44:33 -04:00
parent 94b21f7d4c
commit d39c423da0
33 changed files with 219 additions and 826 deletions

2
.gitignore vendored
View File

@ -80,3 +80,5 @@ bin/*
Berksfile.lock
.zero-knife.rb
Policyfile.lock.json
ops/cookbooks/vendor

View File

@ -7,44 +7,47 @@
The server requires:
* NodeJS 8.x
* open ssh server(any modern version will do)
* inbound Internet access
* OpenResty
* redis
* lua rocks
This has been tested on ubuntu 16.04, but should work on any modern Linux distro. It used the Linux users for its user management, so this will **ONLY** work on Linux, no macOS, BSD or Windows.
This has been tested on ubuntu 16.04, but should work on any modern Linux
distro. It used the Linux users for its user management, so this will
**ONLY** work on Linux, no macOS, BSD or Windows.
The steps below are for a new ubuntu server, they should be mostly the same for other distros, but the paths and availability of packages may vary. A dedicated server is highly recommended (since it will make ever user a system user), a VPS like Digital Ocean will do just fine.
* Install other
These packages are needed for the PAM node package
```bash
apt install libpam0g-dev build-essential
```
* Install open ssh server
```bash
apt install ssh
```
The steps below are for a new ubuntu server, they should be mostly the same for
other distros, but the paths and availability of packages may vary. A dedicated
server is highly recommended (since it will make ever user a system user), a VPS
like Digital Ocean will do just fine.
* Install openresty
[OpenResty® Linux Packages](https://openresty.org/en/linux-packages.html)
* These packages are needed for the PAM node package
```bash
apt install libpam0g-dev build-essential
```
* Install redis
```bash
apt install redis-server
```
* install lua plugin
```bash
apt install luarocks
sudo luarocks install lua-resty-auto-ssl
```
* openresty config
Set up fail back SSL certs
```bash
mkdir /etc/ssl/
@ -56,8 +59,7 @@ openssl req -new -newkey rsa:2048 -days 3650 -nodes -x509 -subj '/CN=sni-suppo
```
change the `/etc/openresty/nginx.conf to have this config`
Change the `/etc/openresty/nginx.conf to have this config`
```
#user nobody;
@ -138,15 +140,9 @@ http {
```
add the SSL config file `/etc/openresty/autossl.conf`, contents from here https://github.com/theta42/t42-common/blob/master/templates/openresty/autossl.conf.erb
add the SSL config file `/etc/openresty/autossl.conf`, contents from here
https://github.com/theta42/t42-common/blob/master/templates/openresty/autossl.conf.erb
Add the proxy config `/etc/openresty/sites-enabled/000-proxy` contents from here https://github.com/theta42/t42-common/blob/master/templates/openresty/010-proxy.conf.erb
## ref
https://blog.trackets.com/2014/05/17/ssh-tunnel-local-and-remote-port-forwarding-explained-with-examples.html
https://github.com/GUI/lua-resty-auto-ssl
Add the proxy config `/etc/openresty/sites-enabled/000-proxy` contents from here
https://github.com/theta42/t42-common/blob/master/templates/openresty/010-proxy.conf.erb

12
Vagrantfile vendored
View File

@ -34,7 +34,7 @@ Vagrant.configure("2") do |config|
# Every Vagrant development environment requires a box. You can search for
# boxes at https://vagrantcloud.com/search.
config.vm.box = "ubuntu/xenial64"
config.vm.box = "ubuntu/bionic64"
config.vm.synced_folder '.', '/vagrant' # The vagrant dir just stopped automounting
# Create a forwarded port mapping which allows access to a specific port
@ -65,14 +65,14 @@ Vagrant.configure("2") do |config|
# Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the
# documentation for more information about their specific syntax and use.
config.vm.provision "shell", inline: <<~SHELL
if ! apt list ruby2.5 | grep installed; then
apt-get update
if ! apt list ruby2.6-dev | grep installed; then
apt-add-repository ppa:brightbox/ruby-ng -y
apt-get update
sudo apt-get install -y build-essential resolvconf ruby2.5 ruby2.5-dev gem
sudo apt-get install -y build-essential resolvconf ruby2.6 ruby2.6-dev gem
fi
if ! which berks >/dev/null; then
gem install ruby-shadow berkshelf --no-ri --no-rdoc
gem install ruby-shadow berkshelf --no-document
# ln -s /opt/chef/embedded/bin/berks /usr/local/bin/berks
fi
@ -111,7 +111,7 @@ Vagrant.configure("2") do |config|
'nodejs': {
'working-dir': 'nodejs',
'port': '3000',
'install_version': 8,
'install_version': 13,
'exec_file': 'bin/www',
'service': true,
},

View File

View File

@ -2,6 +2,16 @@
This file is used to list changes made in each version of the ark cookbook.
## 5.0.0 (2020-01-02)
- Require Chef Infra Client 14+ and remove the need for the build_essential dependency - [@tas50](https://github.com/tas50)
- Use Ruby classes in resource properties - [@tas50](https://github.com/tas50)
- Simplify the platform check logic - [@tas50](https://github.com/tas50)
- Remove the .foocritic file - [@tas50](https://github.com/tas50)
- Remove long_description and recipe metadata - [@tas50](https://github.com/tas50)
- Expand testing - [@tas50](https://github.com/tas50)
- Remove Ubuntu 14.04 testing - [@tas50](https://github.com/tas50)
## 4.0.0 (2018-07-25)
- Support append_env_path property on Windows, which increases the minimum required Chef release to Chef 13.4

View File

@ -25,7 +25,7 @@ The `ark` resource will:
By default, the ark will not run again if the `:path` is not empty. Ark provides many actions to accommodate different use cases, such as `:dump`, `:cherry_pick`, `:put`, and `:install_with_make`.
At this time ark only handles files available from URLs using the [remote_file](http://docs.chef.io/resource_remote_file.html) provider. It does handle local files using the `file://` protocol.
For remote files ark supports URLs using the [remote_file](http://docs.chef.io/resource_remote_file.html) resource. Local files are accessed with the `file://` syntax.
## Requirements
@ -36,7 +36,7 @@ At this time ark only handles files available from URLs using the [remote_file](
- Fedora
- FreeBSD
- SmartOS
- Mac OS X
- macOS
- openSUSE / SUSE Linux Enterprises
- Windows
@ -44,11 +44,10 @@ Should work on common Unix/Linux systems with typical userland utilities like ta
### Chef
- Chef 13.4+
- Chef 14+
### Cookbooks
- build-essential
- seven_zip
## Attributes

View File

@ -25,9 +25,7 @@ module Ark
end
def sevenzip_command
if resource.strip_components <= 0
return sevenzip_command_builder(resource.path, 'x')
end
return sevenzip_command_builder(resource.path, 'x') if resource.strip_components <= 0
tmpdir = make_temp_directory.tr('/', '\\')
cmd = sevenzip_command_builder(tmpdir, 'x')

File diff suppressed because one or more lines are too long

View File

@ -18,6 +18,6 @@
# limitations under the License.
#
package node['ark']['package_dependencies'] unless %w(windows mac_os_x).include?(node['platform_family'])
package node['ark']['package_dependencies'] unless platform_family?('windows', 'mac_os_x')
include_recipe 'seven_zip' if node['platform_family'] == 'windows'
include_recipe 'seven_zip' if platform_family?('windows')

View File

@ -83,7 +83,7 @@ action :install do
action :nothing
end
if node['platform_family'] == 'windows'
if platform_family?('windows')
# usually on windows there is no central directory with executables where the applications are linked
# so ignore has_binaries for now

View File

@ -2,7 +2,19 @@
This file is used to list changes made in the last 3 major versions of the postgresql cookbook.
## Unreleased
## v7.1.8 (2020-02-22)
- Fix incorrect ubuntu platform family value in `postgresql_server_install`
- Re-add unit tests that were skipped
## v7.1.7 (2020-02-21)
- Correctly configure postgres-common on Ubuntu hosts (fixes #596)
## v7.1.6 (2020-02-20)
- Remove unnecessary nil default in resource properties
- Migrate to GitHub Actions for testing
## v7.1.5 (2019-11-18)

View File

@ -213,6 +213,7 @@ module PostgresqlCookbook
"/usr/pgsql-#{new_resource.version}/bin/initdb"
end
cmd << " --locale '#{new_resource.initdb_locale}'" if new_resource.initdb_locale
cmd << " -E '#{new_resource.initdb_encoding}'" if new_resource.initdb_encoding
cmd << " -D '#{data_dir(new_resource.version)}'"
end

View File

@ -1 +1 @@
{"name":"postgresql","version":"7.1.5","description":"Installs and configures postgresql for clients or servers","long_description":"","maintainer":"Sous Chefs","maintainer_email":"help@sous-chefs.org","license":"Apache-2.0","platforms":{"ubuntu":">= 0.0.0","debian":">= 0.0.0","fedora":">= 0.0.0","amazon":">= 0.0.0","redhat":">= 0.0.0","centos":">= 0.0.0","scientific":">= 0.0.0","oracle":">= 0.0.0"},"dependencies":{},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{},"source_url":"https://github.com/sous-chefs/postgresql","issues_url":"https://github.com/sous-chefs/postgresql/issues","chef_version":[[">= 13.8"]],"ohai_version":[]}
{"name":"postgresql","version":"7.1.8","description":"Installs and configures postgresql for clients or servers","long_description":"","maintainer":"Sous Chefs","maintainer_email":"help@sous-chefs.org","license":"Apache-2.0","platforms":{"ubuntu":">= 0.0.0","debian":">= 0.0.0","fedora":">= 0.0.0","amazon":">= 0.0.0","redhat":">= 0.0.0","centos":">= 0.0.0","scientific":">= 0.0.0","oracle":">= 0.0.0"},"dependencies":{},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{},"source_url":"https://github.com/sous-chefs/postgresql","issues_url":"https://github.com/sous-chefs/postgresql/issues","chef_version":[[">= 13.8"]],"ohai_version":[]}

View File

@ -4,7 +4,7 @@ maintainer 'Sous Chefs'
maintainer_email 'help@sous-chefs.org'
license 'Apache-2.0'
description 'Installs and configures postgresql for clients or servers'
version '7.1.5'
version '7.1.8'
source_url 'https://github.com/sous-chefs/postgresql'
issues_url 'https://github.com/sous-chefs/postgresql/issues'
chef_version '>= 13.8'

View File

@ -23,7 +23,7 @@ property :owner, String
# Connection prefernces
property :user, String, default: 'postgres'
property :database, String, name_property: true
property :host, [String, nil], default: nil
property :host, String
property :port, Integer, default: 5432
action :create do

View File

@ -21,11 +21,11 @@ property :source, String, default: 'pg_ident.conf.erb'
property :cookbook, String, default: 'postgresql'
property :system_user, String, required: true
property :pg_user, String, required: true
property :comment, [String, nil], default: nil
property :comment, String
action :create do
ident_resource = new_resource
with_run_context :root do # ~FC037
with_run_context :root do
edit_resource(:template, "#{conf_dir}/pg_ident.conf") do |new_resource|
source new_resource.source
cookbook new_resource.cookbook

View File

@ -1,4 +1,3 @@
# frozen_string_literal: true
#
# Cookbook:: postgresql
# Resource:: server_install
@ -26,6 +25,7 @@ property :external_pid_file, String, default: lazy { "/var/run/postgresql/#{vers
property :password, [String, nil], default: 'generate' # Set to nil if we do not want to set a password
property :port, Integer, default: 5432
property :initdb_locale, String
property :initdb_encoding, String
# Connection preferences
property :user, String, default: 'postgres'
@ -41,6 +41,23 @@ action :install do
setup_repo new_resource.setup_repo
end
# First install the postgresql-common package
if platform_family?('debian')
package 'postgresql-common'
initdb_options = ''
initdb_options << "--locale #{new_resource.initdb_locale}" if new_resource.initdb_locale
initdb_options << " -E #{new_resource.initdb_encoding}" if new_resource.initdb_encoding
template '/etc/postgresql-common/createcluster.conf' do
source 'createcluster.conf.erb'
cookbook 'postgresql'
variables(
initdb_options: initdb_options
)
end
end
package server_pkg_name
end

View File

@ -19,7 +19,7 @@
"recipes": {
},
"version": "0.7.0",
"version": "0.7.1",
"source_url": "",
"issues_url": "",
"privacy": false,

View File

@ -4,7 +4,7 @@ maintainer_email 'you@example.com'
license 'All Rights Reserved'
description 'Installs/Configures t42-common'
long_description 'Installs/Configures t42-common'
version '0.7.0'
version '0.7.1'
chef_version '>= 13.0'
depends 'nodejs'

View File

@ -13,6 +13,11 @@ version_map = {
'version' => '12.9.1',
'url' => 'https://nodejs.org/dist/v12.9.1/node-v12.9.1-linux-x64.tar.gz',
'checksum' => '5488e9d9e860eb344726aabdc8f90d09e36602da38da3d16a7ee852fd9fbd91f'
},
13 => {
'version' => '13.12.0',
'url' => 'https://nodejs.org/dist/v13.12.0/node-v13.12.0-linux-x64.tar.gz',
'checksum' => '3e66b14bbeb9ea1ba129fae7c65374844f4ddaf1e48e2bc19b3b2570e158e362'
}
}

View File

@ -36,6 +36,11 @@ if node['web']['do_ssl']
command "openssl req -new -newkey rsa:2048 -days 3650 -nodes -x509 -subj '/CN=sni-support-required-for-valid-ssl' -keyout /etc/ssl/resty-auto-ssl-fallback.key -out /etc/ssl/resty-auto-ssl-fallback.crt"
end
# execute 'dhparam.pem 4096' do
# command "openssl dhparam -out /etc/nginx/dhparam.pem 4096"
# end
template '/etc/openresty/autossl.conf' do
source 'openresty/autossl.conf.erb'
end

View File

@ -1,77 +1,93 @@
map $http_upgrade $connection_upgrade {
default Upgrade;
'' close;
}
server {
listen 80;
listen 443 ssl;
include autossl.conf;
set_real_ip_from 192.168.1.0/24;
real_ip_header X-Real-IP;
real_ip_recursive on;
location / {
set $target '';
set $target_scheme 'http';
set $target_port '';
access_by_lua '
local host = ngx.var.host
local uri = ngx.var.uri
local scheme = ngx.var.scheme
set $target '';
set $target_scheme 'http';
set $target_port '';
set $header_host $host;
if not host then
ngx.log(ngx.ERR, "no host header found")
return ngx.exit(499)
end
access_by_lua '
local host = ngx.var.host
local uri = ngx.var.uri
local scheme = ngx.var.scheme
local redis = require "resty.redis"
local red = redis:new()
if not host then
ngx.log(ngx.ERR, "no host header found")
return ngx.exit(499)
end
red:set_timeout(1000) -- 1 second
local redis = require "resty.redis"
local red = redis:new()
local ok, err = red:connect("127.0.0.1", 6379)
if not ok then
ngx.log(ngx.ERR, "failed to connect to redis: ", err)
return ngx.exit(598)
end
red:set_timeout(1000) -- 1 second
local res, err = red:hgetall("proxy_host_"..host)
local res = red:array_to_hash(res)
local ok, err = red:connect("127.0.0.1", 6379)
if not ok then
ngx.log(ngx.ERR, "failed to connect to redis: ", err)
return ngx.exit(598)
end
if not res["ip"] then
ngx.log(ngx.ERR, "no host found for key ", host)
return ngx.exit(406)
end
local res, err = red:hgetall("proxy_host_"..host)
local res = red:array_to_hash(res)
if scheme == "http" then
if res["forcessl"] == "true" then
return ngx.redirect("https://"..host..uri, 301)
end
end
if not res["ip"] then
ngx.log(ngx.ERR, "no host found for key ", host)
return ngx.exit(406)
end
if res["targetssl"] == "true" then
ngx.var.target_scheme = "https"
end
if scheme == "http" then
if res["forcessl"] == "true" then
return ngx.redirect("https://"..host..uri, 301)
end
end
ngx.var.target = res["ip"]
ngx.var.target_port = res["targetPort"]
';
if res["targetssl"] == "true" then
ngx.var.target_scheme = "https"
end
if res["host-pass-though"] == "false" then
ngx.var.header_host = res["ip"]
end
ngx.var.target = res["ip"]
ngx.var.target_port = res["targetPort"]
';
resolver 10.0.3.1; #8.8.4.4; # use Google's open DNS server
proxy_set_header Host $target;
proxy_set_header X-Forwarded-Proto $target_scheme;
proxy_set_header Upgrade-Insecure-Requests 0;
proxy_set_header User-Agent $http_user_agent;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Accept-Encoding "";
proxy_set_header Accept-Language $http_accept_language;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Referer $target_scheme://$target;
resolver 192.168.1.1 ipv6=off; #8.8.4.4; # use Google's open DNS server
proxy_pass $target_scheme://$target:$target_port;
proxy_ssl_session_reuse on;
proxy_pass_request_headers on;
proxy_intercept_errors on;
proxy_http_version 1.1;
proxy_pass_request_headers on;
proxy_pass $target_scheme://$target:$target_port;
sub_filter $target $host;
sub_filter_once off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_ssl_session_reuse on;
proxy_intercept_errors off;
proxy_set_header Host $header_host;
add_header X-Target-Host $target;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $target_scheme;
proxy_set_header Referer $target_scheme://$header_host;
proxy_set_header Accept-Language $http_accept_language;
proxy_set_header User-Agent $http_user_agent;
sub_filter $target $host;
sub_filter_once off;
}
}

View File

@ -1,17 +1,19 @@
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
listen 443 ssl http2;
listen 4443 ssl;
ssl_certificate_by_lua_block {
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
ssl_certificate_by_lua_block {
auto_ssl:ssl_certificate()
}
}
location /.well-known/acme-challenge/ {
location /.well-known/acme-challenge/ {
content_by_lua_block {
auto_ssl:challenge_server()
auto_ssl:challenge_server()
}
}
ssl_certificate /etc/ssl/resty-auto-ssl-fallback.crt;
ssl_certificate_key /etc/ssl/resty-auto-ssl-fallback.key;
}
ssl_certificate /etc/ssl/resty-auto-ssl-fallback.crt;
ssl_certificate_key /etc/ssl/resty-auto-ssl-fallback.key;

View File

@ -1,8 +1,5 @@
server {
listen 80;
<% if node['web']['do_ssl'] %>
listen 443 ssl;
<% end %>
server_name <%= node['app']['domain'] %>;
<% if node['web']['do_ssl'] %>

View File

@ -2,6 +2,25 @@
This file is used to list changes made in each version of the windows cookbook.
## 7.0.0 (2020-03-26)
### Breaking Changes
- This cookbook now requires Chef Infra Client 14.7 and later as it no longer includes the `windows_share` and `windows_certificate` resources that are now built into Chef Infra Client.
### Other Changes
- Remove list of actions in the dns resource - [@tas50](https://github.com/tas50)
- Don't set the guard_interpreter in powershell_script - [@tas50](https://github.com/tas50)
- Add windows_schannel resource (#619) - [@Xorima](https://github.com/Xorima)
- Remove desired_state: true from resources - [@tas50](https://github.com/tas50)
- The host_name property in the dns resource doesn't need to be a name property - [@tas50](https://github.com/tas50)
- Remove unnecessary include of the powershell mixin - [@tas50](https://github.com/tas50)
## Unreleased
- Added windows_schannel to configure schannel (tls settings for dotnet apps and powershell)
## 6.0.1 (2019-10-01)
- Update README.md for Windows cookbook suggesting core dns resources (#616) - [@NAshwini](https://github.com/NAshwini)

View File

@ -16,75 +16,13 @@ Provides a set of Windows-specific resources to aid in the creation of cookbooks
### Chef
- Chef 14+
- Chef 14.7+
## Resources
### Deprecated Resources Note
As of Chef 14.7+ the windows_share and windows_certificate resources are now included in the Chef Client. Also the windows_zipfile resource is replaced by the new archive_file resource in Chef 15.0.293+. If you are running Chef 14.7+ the resources in Chef client will take precedence over the resources in this cookbook. In November 2019 we will release a new major version of this cookbook that removes these resources.
### windows_certificate
`Note`: This resource is now included in Chef 14.7 and later. There is no need to depend on the Windows cookbook for this resource.
Installs a certificate into the Windows certificate store from a file, and grants read-only access to the private key for designated accounts. Due to current limitations in WinRM, installing certificated remotely may not work if the operation requires a user profile. Operations on the local machine store should still work.
#### Actions
- `:create` - creates or updates a certificate.
- `:delete` - deletes a certificate.
- `:acl_add` - adds read-only entries to a certificate's private key ACL.
- `:verify` - logs whether or not a certificate is valid
#### Properties
- `source` - name attribute. The source file (for create and acl_add), thumbprint (for delete and acl_add) or subject (for delete).
- `pfx_password` - the password to access the source if it is a pfx file.
- `private_key_acl` - array of 'domain\account' entries to be granted read-only access to the certificate's private key. This is not idempotent.
- `store_name` - the certificate store to manipulate. One of:
- MY (Personal)
- CA (Intermediate Certification Authorities)
- ROOT (Trusted Root Certification Authorities)
- TRUSTEDPUBLISHER (Trusted Publishers)
- CLIENTAUTHISSUER (Client Authentication Issuers)
- REMOTE DESKTOP (Remote Desktop)
- TRUSTEDDEVICES (Trusted Devices)
- WEBHOSTING (Web Hosting)
- AUTHROOT (Third-Party Root Certification Authorities)
- TRUSTEDPEOPLE (Trusted People)
- SMARTCARDROOT (Smart Card Trusted Roots)
- TRUST (Enterprise Trust)
- DISALLOWED (Untrusted Certificates)
- `user_store` - if false (default) then use the local machine store; if true then use the current user's store.
#### Examples
```ruby
# Add PFX cert to local machine personal store and grant accounts read-only access to private key
windows_certificate "c:/test/mycert.pfx" do
pfx_password "password"
private_key_acl ["acme\fred", "pc\jane"]
end
```
```ruby
# Add cert to trusted intermediate store
windows_certificate "c:/test/mycert.cer" do
store_name "CA"
end
```
```ruby
# Remove all certificates matching the subject
windows_certificate "me.acme.com" do
action :delete
end
```
### windows_certificate_binding
Binds a certificate to an HTTP port in order to enable TLS communication.
Binds a certificate to an HTTP port to enable TLS communication.
#### Actions
@ -215,52 +153,19 @@ windows_http_acl 'http://+:50051/' do
end
```
### windows_share
### windows_schannel
`Note`: This resource is now included in Chef 14.7 and later. There is no need to depend on the Windows cookbook for this resource.
Creates, modifies and removes Windows shares. All properties are idempotent.
`Note`: This resource uses PowerShell cmdlets introduced in Windows 2012/8.
Used to configure the schannel security settings in windows, this is used by dotnet apps and PowerShell to be able to speak to tls 1.2 endpoints
#### Actions
- `:create`: creates/modifies a share
- `:delete`: deletes a share
- `configure`: Configures the setting
#### Properties
property | type | default | description
------------------------ | ---------- | ------------- | -----------------------------------------------------------------------------------------------------------------------------------------------------------
`share_name` | String | resource name | the share to assign to the share
`path` | String | | The path of the location of the folder to share. Required when creating. If the share already exists on a different path then it is deleted and re-created.
`description` | String | | description to be applied to the share
`full_users` | Array | [] | users which should have "Full control" permissions
`change_users` | Array | [] | Users are granted modify permission to access the share.
`read_users` | Array | [] | users which should have "Read" permissions
`temporary` | True/False | false | The lifetime of the new SMB share. A temporary share does not persist beyond the next restart of the computer
`scope_name` | String | '*' | The scope name of the share.
`ca_timeout` | Integer | 0 | The continuous availability time-out for the share.
`continuously_available` | True/False | false | Indicates that the share is continuously available.
`concurrent_user_limit` | Integer | 0 (unlimited) | The maximum number of concurrently connected users the share can accommodate
`encrypt_data` | True/False | false | Indicates that the share is encrypted.
#### Examples
```ruby
windows_share "foo" do
action :create
path "C:\\foo"
full_users ["DOMAIN_A\\some_user", "DOMAIN_B\\some_other_user"]
read_users ["DOMAIN_C\\Domain users"]
end
```
```ruby
windows_share "foo" do
action :delete
end
```
`use_strong_crypto` | True, False | true | Enables or disables the setting
### windows_user_privilege
@ -349,7 +254,7 @@ SeTakeOwnershipPrivilege Take ownership of files or other objects
`Note`: This resource has been deprecated as Chef Infra Client 15.0 shipped with a new archive_file resource, which natively handles multiple archive formats. Please update any cookbooks using this resource to instead use the `archive_file` resource: https://docs.chef.io/resource_archive_file.html
Most version of Windows do not ship with native cli utility for managing compressed files. This resource provides a pure-ruby implementation for managing zip files. Be sure to use the `not_if` or `only_if` meta parameters to guard the resource for idempotence or action will be taken every Chef run.
Most versions of Windows do not ship with native cli utility for managing compressed files. This resource provides a pure-ruby implementation for managing zip files. Be sure to use the `not_if` or `only_if` meta parameters to guard the resource for idempotence or action will be taken every Chef run.
#### Actions
@ -440,11 +345,11 @@ end
### Windows::VersionHelper
Helper that allows you to get information of the windows version running on your node. It leverages windows ohai from kernel.os_info, easy to mock and to use even on linux.
Helper that allows you to get information on the windows version running on your node. It leverages windows ohai from kernel.os_info, easy to mock and to use even on Linux.
#### core_version?
Determines whether given node is running on a windows Core.
Determines whether the given node is running on a Windows Core.
```ruby
if ::Windows::VersionHelper.core_version? node
@ -454,7 +359,7 @@ end
#### workstation_version?
Determines whether given node is a windows workstation version (XP, Vista, 7, 8, 8.1, 10)
Determines whether the given node is a windows workstation version (XP, Vista, 7, 8, 8.1, 10)
```ruby
if ::Windows::VersionHelper.workstation_version? node
@ -464,7 +369,7 @@ end
#### server_version?
Determines whether given node is a windows server version (Server 2003, Server 2008, Server 2012, Server 2016)
Determines whether the given node is a windows server version (Server 2003, Server 2008, Server 2012, Server 2016)
```ruby
if ::Windows::VersionHelper.server_version? node

View File

@ -1 +1 @@
{"name":"windows","version":"6.0.1","description":"Provides a set of useful Windows-specific primitives.","long_description":"","maintainer":"Chef Software, Inc.","maintainer_email":"cookbooks@chef.io","license":"Apache-2.0","platforms":{"windows":">= 0.0.0"},"dependencies":{},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{},"source_url":"https://github.com/chef-cookbooks/windows","issues_url":"https://github.com/chef-cookbooks/windows/issues","chef_version":[[">= 14"]],"ohai_version":[]}
{"name":"windows","version":"7.0.0","description":"Provides a set of useful Windows-specific primitives.","long_description":"","maintainer":"Chef Software, Inc.","maintainer_email":"cookbooks@chef.io","license":"Apache-2.0","platforms":{"windows":">= 0.0.0"},"dependencies":{},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{},"source_url":"https://github.com/chef-cookbooks/windows","issues_url":"https://github.com/chef-cookbooks/windows/issues","chef_version":[[">= 14.7"]],"ohai_version":[]}

View File

@ -3,8 +3,8 @@ maintainer 'Chef Software, Inc.'
maintainer_email 'cookbooks@chef.io'
license 'Apache-2.0'
description 'Provides a set of useful Windows-specific primitives.'
version '6.0.1'
version '7.0.0'
supports 'windows'
source_url 'https://github.com/chef-cookbooks/windows'
issues_url 'https://github.com/chef-cookbooks/windows/issues'
chef_version '>= 14'
chef_version '>= 14.7'

View File

@ -1,301 +0,0 @@
#
# Author:: Richard Lavey (richard.lavey@calastone.com)
# Cookbook:: windows
# Resource:: certificate
#
# Copyright:: 2015-2017, Calastone Ltd.
# Copyright:: 2018-2019, Chef Software, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
require 'chef/util/path_helper'
chef_version_for_provides '< 14.7' if respond_to?(:chef_version_for_provides)
resource_name :windows_certificate
property :source, String, name_property: true
property :pfx_password, String
property :private_key_acl, Array
property :store_name, String, default: 'MY', equal_to: ['TRUSTEDPUBLISHER', 'TrustedPublisher', 'CLIENTAUTHISSUER', 'REMOTE DESKTOP', 'ROOT', 'TRUSTEDDEVICES', 'WEBHOSTING', 'CA', 'AUTHROOT', 'TRUSTEDPEOPLE', 'MY', 'SMARTCARDROOT', 'TRUST', 'DISALLOWED']
property :user_store, [TrueClass, FalseClass], default: false
property :cert_path, String
property :sensitive, [ TrueClass, FalseClass ], default: lazy { |r| r.pfx_password ? true : false }
action :create do
load_gem
# Extension of the certificate
ext = ::File.extname(new_resource.source)
cert_obj = fetch_cert_object(ext) # Fetch OpenSSL::X509::Certificate object
thumbprint = OpenSSL::Digest::SHA1.new(cert_obj.to_der).to_s # Fetch its thumbprint
# Need to check if return value is Boolean:true
# If not then the given certificate should be added in certstore
if verify_cert(thumbprint) == true
Chef::Log.debug('Certificate is already present')
else
converge_by("Adding certificate #{new_resource.source} into Store #{new_resource.store_name}") do
if ext == '.pfx'
add_pfx_cert
else
add_cert(cert_obj)
end
end
end
end
# acl_add is a modify-if-exists operation : not idempotent
action :acl_add do
if ::File.exist?(new_resource.source)
hash = '$cert.GetCertHashString()'
code_script = cert_script(false)
guard_script = cert_script(false)
else
# make sure we have no spaces in the hash string
hash = "\"#{new_resource.source.gsub(/\s/, '')}\""
code_script = ''
guard_script = ''
end
code_script << acl_script(hash)
guard_script << cert_exists_script(hash)
powershell_script "setting the acls on #{new_resource.source} in #{cert_location}\\#{new_resource.store_name}" do
guard_interpreter :powershell_script
convert_boolean_return true
code code_script
only_if guard_script
sensitive if new_resource.sensitive
end
end
action :delete do
load_gem
cert_obj = fetch_cert
if cert_obj
converge_by("Deleting certificate #{new_resource.source} from Store #{new_resource.store_name}") do
delete_cert
end
else
Chef::Log.debug('Certificate not found')
end
end
action :fetch do
load_gem
cert_obj = fetch_cert
if cert_obj
show_or_store_cert(cert_obj)
else
Chef::Log.debug('Certificate not found')
end
end
action :verify do
load_gem
out = verify_cert
if !!out == out
out = out ? 'Certificate is valid' : 'Certificate not valid'
end
Chef::Log.info(out.to_s)
end
action_class do
require 'openssl'
# load the gem and rescue a gem install if it fails to load
def load_gem
gem 'win32-certstore', '>= 0.2.4'
require 'win32-certstore' # until this is in core chef
rescue LoadError
Chef::Log.debug('Did not find win32-certstore >= 0.2.4 gem installed. Installing now')
chef_gem 'win32-certstore' do
compile_time true
action :upgrade
end
require 'win32-certstore'
end
def add_cert(cert_obj)
store = ::Win32::Certstore.open(new_resource.store_name)
store.add(cert_obj)
end
def add_pfx_cert
store = ::Win32::Certstore.open(new_resource.store_name)
store.add_pfx(new_resource.source, new_resource.pfx_password)
end
def delete_cert
store = ::Win32::Certstore.open(new_resource.store_name)
store.delete(new_resource.source)
end
def fetch_cert
store = ::Win32::Certstore.open(new_resource.store_name)
store.get(new_resource.source)
end
# Checks whether a certificate with the given thumbprint
# is already present and valid in certificate store
# If the certificate is not present, verify_cert returns a String: "Certificate not found"
# But if it is present but expired, it returns a Boolean: false
# Otherwise, it returns a Boolean: true
def verify_cert(thumbprint = new_resource.source)
store = ::Win32::Certstore.open(new_resource.store_name)
store.valid?(thumbprint)
end
def show_or_store_cert(cert_obj)
if new_resource.cert_path
export_cert(cert_obj, new_resource.cert_path)
if ::File.size(new_resource.cert_path) > 0
Chef::Log.info("Certificate export in #{new_resource.cert_path}")
else
::File.delete(new_resource.cert_path)
end
else
Chef::Log.info(cert_obj.display)
end
end
def export_cert(cert_obj, cert_path)
out_file = ::File.new(cert_path, 'w+')
case ::File.extname(cert_path)
when '.pem'
out_file.puts(cert_obj.to_pem)
when '.der'
out_file.puts(cert_obj.to_der)
when '.cer'
cert_out = powershell_out("openssl x509 -text -inform DER -in #{cert_obj.to_pem} -outform CER").stdout
out_file.puts(cert_out)
when '.crt'
cert_out = powershell_out("openssl x509 -text -inform DER -in #{cert_obj.to_pem} -outform CRT").stdout
out_file.puts(cert_out)
when '.pfx'
cert_out = powershell_out("openssl pkcs12 -export -nokeys -in #{cert_obj.to_pem} -outform PFX").stdout
out_file.puts(cert_out)
when '.p7b'
cert_out = powershell_out("openssl pkcs7 -export -nokeys -in #{cert_obj.to_pem} -outform P7B").stdout
out_file.puts(cert_out)
else
Chef::Log.info('Supported certificate format .pem, .der, .cer, .crt, .pfx and .p7b')
end
out_file.close
end
def cert_location
@location ||= new_resource.user_store ? 'CurrentUser' : 'LocalMachine'
end
def cert_script(persist)
cert_script = '$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2'
file = Chef::Util::PathHelper.cleanpath(new_resource.source)
cert_script << " \"#{file}\""
if ::File.extname(file.downcase) == '.pfx'
cert_script << ", \"#{new_resource.pfx_password}\""
if persist && new_resource.user_store
cert_script << ', ([System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::PersistKeySet)'
elsif persist
cert_script << ', ([System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::PersistKeySet -bor [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::MachineKeyset)'
end
end
cert_script << "\n"
end
def cert_exists_script(hash)
<<-EOH
$hash = #{hash}
Test-Path "Cert:\\#{cert_location}\\#{new_resource.store_name}\\$hash"
EOH
end
def within_store_script
inner_script = yield '$store'
<<-EOH
$store = New-Object System.Security.Cryptography.X509Certificates.X509Store "#{new_resource.store_name}", ([System.Security.Cryptography.X509Certificates.StoreLocation]::#{cert_location})
$store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite)
#{inner_script}
$store.Close()
EOH
end
def acl_script(hash)
return '' if new_resource.private_key_acl.nil? || new_resource.private_key_acl.empty?
# this PS came from http://blogs.technet.com/b/operationsguy/archive/2010/11/29/provide-access-to-private-keys-commandline-vs-powershell.aspx
# and from https://msdn.microsoft.com/en-us/library/windows/desktop/bb204778(v=vs.85).aspx
set_acl_script = <<-EOH
$hash = #{hash}
$storeCert = Get-ChildItem "cert:\\#{cert_location}\\#{new_resource.store_name}\\$hash"
if ($storeCert -eq $null) { throw 'no key exists.' }
$keyname = $storeCert.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName
if ($keyname -eq $null) { throw 'no private key exists.' }
if ($storeCert.PrivateKey.CspKeyContainerInfo.MachineKeyStore)
{
$fullpath = "$Env:ProgramData\\Microsoft\\Crypto\\RSA\\MachineKeys\\$keyname"
}
else
{
$currentUser = New-Object System.Security.Principal.NTAccount($Env:UserDomain, $Env:UserName)
$userSID = $currentUser.Translate([System.Security.Principal.SecurityIdentifier]).Value
$fullpath = "$Env:ProgramData\\Microsoft\\Crypto\\RSA\\$userSID\\$keyname"
}
EOH
new_resource.private_key_acl.each do |name|
set_acl_script << "$uname='#{name}'; icacls $fullpath /grant $uname`:RX\n"
end
set_acl_script
end
# Method returns an OpenSSL::X509::Certificate object
#
# Based on its extension, the certificate contents are used to initialize
# PKCS12 (PFX), PKCS7 (P7B) objects which contains OpenSSL::X509::Certificate.
#
# @note Other then PEM, all the certificates are usually in binary format, and hence
# their contents are loaded by using File.binread
#
# @param ext [String] Extension of the certificate
#
# @return [OpenSSL::X509::Certificate] Object containing certificate's attributes
#
# @raise [OpenSSL::PKCS12::PKCS12Error] When incorrect password is provided for PFX certificate
#
def fetch_cert_object(ext)
contents = if binary_cert?
::File.binread(new_resource.source)
else
::File.read(new_resource.source)
end
case ext
when '.pfx'
OpenSSL::PKCS12.new(contents, new_resource.pfx_password).certificate
when '.p7b'
OpenSSL::PKCS7.new(contents).certificates.first
else
OpenSSL::X509::Certificate.new(contents)
end
end
# @return [Boolean] Whether the certificate file is binary encoded or not
#
def binary_cert?
powershell_out!("file -b --mime-encoding #{new_resource.source}").stdout.strip == 'binary'
end
end

View File

@ -19,7 +19,6 @@
# limitations under the License.
#
include Chef::Mixin::PowershellOut
include Windows::Helper
property :cert_name, String, name_property: true
@ -28,7 +27,7 @@ property :address, String, default: '0.0.0.0'
property :port, Integer, default: 443
property :app_id, String, default: '{4dc3e181-e14b-4a21-b022-59fc669b0914}'
property :store_name, String, default: 'MY', equal_to: ['TRUSTEDPUBLISHER', 'CLIENTAUTHISSUER', 'REMOTE DESKTOP', 'ROOT', 'TRUSTEDDEVICES', 'WEBHOSTING', 'CA', 'AUTHROOT', 'TRUSTEDPEOPLE', 'MY', 'SMARTCARDROOT', 'TRUST']
property :exists, [true, false], desired_state: true
property :exists, [true, false]
load_current_value do |desired|
mode = desired.address.match(/(\d+\.){3}\d+|\[.+\]/).nil? ? 'hostnameport' : 'ipport'

View File

@ -18,10 +18,9 @@
# limitations under the License.
#
actions :create, :delete
default_action :create
attribute :host_name, kind_of: String, name_property: true, required: true
attribute :host_name, kind_of: String, required: true
attribute :record_type, kind_of: String, default: 'A', regex: /^(?:A|CNAME)$/
attribute :dns_server, kind_of: String, default: '.'
attribute :target, kind_of: [Array, String], required: true

View File

@ -23,7 +23,7 @@ include Windows::Helper
property :url, String, name_property: true
property :user, String
property :sddl, String
property :exists, [true, false], desired_state: true
property :exists, [true, false]
# See https://msdn.microsoft.com/en-us/library/windows/desktop/cc307236%28v=vs.85%29.aspx for netsh info

View File

@ -1,288 +0,0 @@
#
# Author:: Sölvi Páll Ásgeirsson (<solvip@gmail.com>)
# Author:: Richard Lavey (richard.lavey@calastone.com)
# Author:: Tim Smith (tsmith@chef.io)
# Cookbook:: windows
# Resource:: share
#
# Copyright:: 2014-2017, Sölvi Páll Ásgeirsson.
# Copyright:: 2018, Chef Software, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
chef_version_for_provides '< 14.7' if respond_to?(:chef_version_for_provides)
resource_name :windows_share
require 'chef/json_compat'
require 'chef/util/path_helper'
# Specifies a name for the SMB share. The name may be composed of any valid file name characters, but must be less than 80 characters long. The names pipe and mailslot are reserved for use by the computer.
property :share_name, String, name_property: true
# Specifies the path of the location of the folder to share. The path must be fully qualified. Relative paths or paths that contain wildcard characters are not permitted.
property :path, String
# Specifies an optional description of the SMB share. A description of the share is displayed by running the Get-SmbShare cmdlet. The description may not contain more than 256 characters.
property :description, String, default: ''
# Specifies which accounts are granted full permission to access the share. Use a comma-separated list to specify multiple accounts. An account may not be specified more than once in the FullAccess, ChangeAccess, or ReadAccess parameter lists, but may be specified once in the FullAccess, ChangeAccess, or ReadAccess parameter list and once in the NoAccess parameter list.
property :full_users, Array, default: [], coerce: proc { |u| u.sort }
# Specifies which users are granted modify permission to access the share
property :change_users, Array, default: [], coerce: proc { |u| u.sort }
# Specifies which users are granted read permission to access the share. Multiple users can be specified by supplying a comma-separated list.
property :read_users, Array, default: [], coerce: proc { |u| u.sort }
# Specifies the lifetime of the new SMB share. A temporary share does not persist beyond the next restart of the computer. By default, new SMB shares are persistent, and non-temporary.
property :temporary, [true, false], default: false
# Specifies the scope name of the share.
property :scope_name, String, default: '*'
# Specifies the continuous availability time-out for the share.
property :ca_timeout, Integer, default: 0
# Indicates that the share is continuously available.
property :continuously_available, [true, false], default: false
# Specifies the caching mode of the offline files for the SMB share.
# property :caching_mode, String, equal_to: %w(None Manual Documents Programs BranchCache)
# Specifies the maximum number of concurrently connected users that the new SMB share may accommodate. If this parameter is set to zero (0), then the number of users is unlimited.
property :concurrent_user_limit, Integer, default: 0
# Indicates that the share is encrypted.
property :encrypt_data, [true, false], default: false
# Specifies which files and folders in the SMB share are visible to users. AccessBased: SMB does not the display the files and folders for a share to a user unless that user has rights to access the files and folders. By default, access-based enumeration is disabled for new SMB shares. Unrestricted: SMB displays files and folders to a user even when the user does not have permission to access the items.
# property :folder_enumeration_mode, String, equal_to: %(AccessBased Unrestricted)
include Chef::Mixin::PowershellOut
load_current_value do |desired|
# this command selects individual objects because EncryptData & CachingMode have underlying
# types that get converted to their Integer values by ConvertTo-Json & we need to make sure
# those get written out as strings
share_state_cmd = "Get-SmbShare -Name '#{desired.share_name}' | Select-Object Name,Path, Description, Temporary, CATimeout, ContinuouslyAvailable, ConcurrentUserLimit, EncryptData | ConvertTo-Json"
Chef::Log.debug("Running '#{share_state_cmd}' to determine share state'")
ps_results = powershell_out(share_state_cmd)
# detect a failure without raising and then set current_resource to nil
if ps_results.error?
Chef::Log.debug("Error fetching share state: #{ps_results.stderr}")
current_value_does_not_exist!
end
Chef::Log.debug("The Get-SmbShare results were #{ps_results.stdout}")
results = Chef::JSONCompat.from_json(ps_results.stdout)
path results['Path']
description results['Description']
temporary results['Temporary']
ca_timeout results['CATimeout']
continuously_available results['ContinuouslyAvailable']
# caching_mode results['CachingMode']
concurrent_user_limit results['ConcurrentUserLimit']
encrypt_data results['EncryptData']
# folder_enumeration_mode results['FolderEnumerationMode']
perm_state_cmd = %(Get-SmbShareAccess -Name "#{desired.share_name}" | Select-Object AccountName,AccessControlType,AccessRight | ConvertTo-Json)
Chef::Log.debug("Running '#{perm_state_cmd}' to determine share permissions state'")
ps_perm_results = powershell_out(perm_state_cmd)
# we raise here instead of warning like above because we'd only get here if the above Get-SmbShare
# command was successful and that continuing would leave us with 1/2 known state
raise "Could not determine #{desired.share_name} share permissions by running '#{perm_state_cmd}'" if ps_perm_results.error?
Chef::Log.debug("The Get-SmbShareAccess results were #{ps_perm_results.stdout}")
f_users, c_users, r_users = parse_permissions(ps_perm_results.stdout)
full_users f_users
change_users c_users
read_users r_users
end
def after_created
raise 'The windows_share resource relies on PowerShell cmdlets not present in Windows releases prior to 8/2012. Cannot continue!' if node['platform_version'].to_f < 6.3
end
# given the string output of Get-SmbShareAccess parse out
# arrays of full access users, change users, and read only users
def parse_permissions(results_string)
json_results = Chef::JSONCompat.from_json(results_string)
json_results = [json_results] unless json_results.is_a?(Array) # single result is not an array
f_users = []
c_users = []
r_users = []
json_results.each do |perm|
next unless perm['AccessControlType'] == 0 # allow
case perm['AccessRight']
when 0 then f_users << stripped_account(perm['AccountName']) # 0 full control
when 1 then c_users << stripped_account(perm['AccountName']) # 1 == change
when 2 then r_users << stripped_account(perm['AccountName']) # 2 == read
end
end
[f_users, c_users, r_users]
end
# local names are returned from Get-SmbShareAccess in the full format MACHINE\\NAME
# but users of this resource would simply say NAME so we need to strip the values for comparison
def stripped_account(name)
name.slice!("#{node['hostname']}\\")
name
end
action :create do
# we do this here instead of requiring the property because :delete doesn't need path set
raise 'No path property set' unless new_resource.path
converge_if_changed do
# you can't actually change the path so you have to delete the old share first
if different_path?
Chef::Log.debug('The path has changed so we will delete and recreate share')
delete_share
create_share
elsif current_resource.nil?
# powershell cmdlet for create is different than updates
Chef::Log.debug('The current resource is nil so we will create a new share')
create_share
else
Chef::Log.debug('The current resource was not nil so we will update an existing share')
update_share
end
# creating the share does not set permissions so we need to update
update_permissions
end
end
action :delete do
if current_resource.nil?
Chef::Log.debug("#{new_resource.share_name} does not exist - nothing to do")
else
converge_by("delete #{new_resource.share_name}") do
delete_share
end
end
end
action_class do
def different_path?
return false if current_resource.nil? # going from nil to something isn't different for our concerns
return false if current_resource.path == Chef::Util::PathHelper.cleanpath(new_resource.path)
true
end
def delete_share
delete_command = "Remove-SmbShare -Name '#{new_resource.share_name}' -Force"
Chef::Log.debug("Running '#{delete_command}' to remove the share")
powershell_out!(delete_command)
end
def update_share
update_command = "Set-SmbShare -Name '#{new_resource.share_name}' -Description '#{new_resource.description}' -Force"
Chef::Log.debug("Running '#{update_command}' to update the share")
powershell_out!(update_command)
end
def create_share
raise "#{new_resource.path} is missing or not a directory. Shares cannot be created if the path doesn't first exist." unless ::File.directory? new_resource.path
share_cmd = "New-SmbShare -Name '#{new_resource.share_name}' -Path '#{Chef::Util::PathHelper.cleanpath(new_resource.path)}' -Description '#{new_resource.description}' -ConcurrentUserLimit #{new_resource.concurrent_user_limit} -CATimeout #{new_resource.ca_timeout} -EncryptData:#{bool_string(new_resource.encrypt_data)} -ContinuouslyAvailable:#{bool_string(new_resource.continuously_available)}"
share_cmd << " -ScopeName #{new_resource.scope_name}" unless new_resource.scope_name == '*' # passing * causes the command to fail
share_cmd << " -Temporary:#{bool_string(new_resource.temporary)}" if new_resource.temporary # only set true
Chef::Log.debug("Running '#{share_cmd}' to create the share")
powershell_out!(share_cmd)
# New-SmbShare adds the "Everyone" user with read access no matter what so we need to remove it
# before we add our permissions
revoke_user_permissions(['Everyone'])
end
# determine what users in the current state don't exist in the desired state
# users/groups will have their permissions updated with the same command that
# sets it, but removes must be performed with Revoke-SmbShareAccess
def users_to_revoke
@users_to_revoke ||= begin
# if the resource doesn't exist then nothing needs to be revoked
if current_resource.nil?
[]
else # if it exists then calculate the current to new resource diffs
(current_resource.full_users + current_resource.change_users + current_resource.read_users) - (new_resource.full_users + new_resource.change_users + new_resource.read_users)
end
end
end
# update existing permissions on a share
def update_permissions
# revoke any users that had something, but now has nothing
revoke_user_permissions(users_to_revoke) unless users_to_revoke.empty?
# set permissions for each of the permission types
%w(full read change).each do |perm_type|
# set permissions for a brand new share OR
# update permissions if the current state and desired state differ
next unless permissions_need_update?(perm_type)
grant_command = "Grant-SmbShareAccess -Name '#{new_resource.share_name}' -AccountName \"#{new_resource.send("#{perm_type}_users").join('","')}\" -Force -AccessRight #{perm_type}"
Chef::Log.debug("Running '#{grant_command}' to update the share permissions")
powershell_out!(grant_command)
end
end
# determine if permissions need to be updated.
# Brand new share with no permissions defined: no
# Brand new share with permissions defined: yes
# Existing share with differing permissions: yes
#
# @param [String] type the permissions type (Full, Read, or Change)
def permissions_need_update?(type)
property_name = "#{type}_users"
# brand new share, but nothing to set
return false if current_resource.nil? && new_resource.send(property_name).empty?
# brand new share with new permissions to set
return true if current_resource.nil? && !new_resource.send(property_name).empty?
# there's a difference between the current and desired state
return true unless (new_resource.send(property_name) - current_resource.send(property_name)).empty?
# anything else
false
end
# revoke user permissions from a share
# @param [Array] users
def revoke_user_permissions(users)
revoke_command = "Revoke-SmbShareAccess -Name '#{new_resource.share_name}' -AccountName \"#{users.join('","')}\" -Force"
Chef::Log.debug("Running '#{revoke_command}' to revoke share permissions")
powershell_out!(revoke_command)
end
# convert True/False into "$True" & "$False"
def bool_string(bool)
# bool ? 1 : 0
bool ? '$true' : '$false'
end
end