chef 17.4.25-universal-mingw32 → 17.6.18-universal-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +2 -2
- data/chef.gemspec +2 -0
- data/lib/chef/application/base.rb +11 -1
- data/lib/chef/client.rb +1 -2
- data/lib/chef/compliance/input.rb +115 -0
- data/lib/chef/compliance/input_collection.rb +139 -0
- data/lib/chef/compliance/profile.rb +122 -0
- data/lib/chef/compliance/profile_collection.rb +109 -0
- data/lib/chef/compliance/reporter/automate.rb +1 -1
- data/lib/chef/compliance/runner.rb +48 -6
- data/lib/chef/compliance/waiver.rb +115 -0
- data/lib/chef/compliance/waiver_collection.rb +143 -0
- data/lib/chef/dsl/compliance.rb +38 -0
- data/lib/chef/dsl/reader_helpers.rb +51 -0
- data/lib/chef/dsl/recipe.rb +4 -2
- data/lib/chef/dsl/secret.rb +2 -4
- data/lib/chef/dsl/universal.rb +2 -0
- data/lib/chef/event_dispatch/base.rb +44 -2
- data/lib/chef/formatters/doc.rb +60 -13
- data/lib/chef/formatters/minimal.rb +6 -5
- data/lib/chef/http/basic_client.rb +15 -7
- data/lib/chef/http.rb +12 -8
- data/lib/chef/provider/file.rb +2 -0
- data/lib/chef/provider/link.rb +2 -2
- data/lib/chef/provider/registry_key.rb +3 -2
- data/lib/chef/provider/remote_file/http.rb +1 -1
- data/lib/chef/provider/template.rb +1 -1
- data/lib/chef/resource/archive_file.rb +17 -14
- data/lib/chef/resource/chef_client_scheduled_task.rb +45 -2
- data/lib/chef/resource/chocolatey_config.rb +13 -13
- data/lib/chef/resource/execute.rb +2 -2
- data/lib/chef/resource/file/verification/json.rb +50 -0
- data/lib/chef/resource/file/verification/yaml.rb +52 -0
- data/lib/chef/resource/inspec_input.rb +127 -0
- data/lib/chef/resource/inspec_waiver.rb +184 -0
- data/lib/chef/resource/mount.rb +1 -1
- data/lib/chef/resource/openssl_x509_certificate.rb +1 -1
- data/lib/chef/resource/powershell_package_source.rb +234 -70
- data/lib/chef/resource/registry_key.rb +36 -48
- data/lib/chef/resource/remote_file.rb +98 -2
- data/lib/chef/resource/timezone.rb +2 -2
- data/lib/chef/resource/user_ulimit.rb +1 -0
- data/lib/chef/resource/windows_printer.rb +1 -1
- data/lib/chef/resource/windows_uac.rb +3 -1
- data/lib/chef/resource/windows_user_privilege.rb +1 -1
- data/lib/chef/resource.rb +1 -1
- data/lib/chef/resources.rb +2 -0
- data/lib/chef/run_context/cookbook_compiler.rb +112 -28
- data/lib/chef/run_context.rb +31 -1
- data/lib/chef/secret_fetcher/akeyless_vault.rb +57 -0
- data/lib/chef/secret_fetcher/aws_secrets_manager.rb +1 -1
- data/lib/chef/secret_fetcher/azure_key_vault.rb +1 -1
- data/lib/chef/secret_fetcher/base.rb +1 -1
- data/lib/chef/secret_fetcher/hashi_vault.rb +100 -0
- data/lib/chef/secret_fetcher.rb +8 -2
- data/lib/chef/version.rb +1 -1
- data/lib/chef/win32/version.rb +2 -1
- data/spec/data/archive_file/test_archive.tar.gz +0 -0
- data/spec/functional/resource/archive_file_spec.rb +87 -0
- data/spec/functional/resource/group_spec.rb +5 -1
- data/spec/functional/resource/link_spec.rb +8 -0
- data/spec/functional/resource/powershell_package_source_spec.rb +5 -6
- data/spec/integration/compliance/compliance_spec.rb +60 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/support/platform_helpers.rb +4 -0
- data/spec/support/ruby_installer.rb +51 -0
- data/spec/unit/compliance/input_spec.rb +104 -0
- data/spec/unit/compliance/profile_spec.rb +120 -0
- data/spec/unit/compliance/waiver_spec.rb +104 -0
- data/spec/unit/formatters/doc_spec.rb +1 -1
- data/spec/unit/http/basic_client_spec.rb +30 -0
- data/spec/unit/http_spec.rb +8 -2
- data/spec/unit/provider/link_spec.rb +13 -7
- data/spec/unit/provider/remote_file/http_spec.rb +10 -0
- data/spec/unit/provider/template_spec.rb +2 -2
- data/spec/unit/resource/archive_file_spec.rb +414 -3
- data/spec/unit/resource/chef_client_scheduled_task_spec.rb +69 -0
- data/spec/unit/resource/file/verification/json_spec.rb +72 -0
- data/spec/unit/resource/file/verification/yaml_spec.rb +67 -0
- data/spec/unit/resource/inspec_input_spec.rb +300 -0
- data/spec/unit/resource/inspec_waiver_spec.rb +312 -0
- data/spec/unit/resource/mount_spec.rb +10 -0
- data/spec/unit/resource/powershell_package_source_spec.rb +63 -62
- data/spec/unit/resource/user_ulimit_spec.rb +14 -1
- data/spec/unit/secret_fetcher/akeyless_vault_spec.rb +37 -0
- data/spec/unit/secret_fetcher/hashi_vault_spec.rb +80 -0
- data/tasks/rspec.rb +2 -1
- metadata +60 -6
@@ -0,0 +1,184 @@
|
|
1
|
+
#
|
2
|
+
# Copyright:: Copyright (c) Chef Software Inc.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
require_relative "../resource"
|
18
|
+
|
19
|
+
class Chef
|
20
|
+
class Resource
|
21
|
+
class InspecWaiver < Chef::Resource
|
22
|
+
provides :inspec_waiver
|
23
|
+
unified_mode true
|
24
|
+
|
25
|
+
description "Use the **inspec_waiver** resource to add a waiver to the Compliance Phase."
|
26
|
+
introduced "17.5"
|
27
|
+
examples <<~DOC
|
28
|
+
**Activate the default waiver in the openssh cookbook's compliance segment**:
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
inspec_waiver 'openssh' do
|
32
|
+
action :add
|
33
|
+
end
|
34
|
+
```
|
35
|
+
|
36
|
+
**Activate all waivers in the openssh cookbook's compliance segment**:
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
inspec_waiver 'openssh::.*' do
|
40
|
+
action :add
|
41
|
+
end
|
42
|
+
```
|
43
|
+
|
44
|
+
**Add an InSpec waiver to the Compliance Phase**:
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
inspec_waiver 'Add waiver entry for control' do
|
48
|
+
control 'my_inspec_control_01'
|
49
|
+
run_test false
|
50
|
+
justification "The subject of this control is not managed by #{ChefUtils::Dist::Infra::PRODUCT} on the systems in policy group \#{node['policy_group']}"
|
51
|
+
expiration '2022-01-01'
|
52
|
+
action :add
|
53
|
+
end
|
54
|
+
```
|
55
|
+
|
56
|
+
**Add an InSpec waiver to the Compliance Phase using the 'name' property to identify the control**:
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
inspec_waiver 'my_inspec_control_01' do
|
60
|
+
justification "The subject of this control is not managed by #{ChefUtils::Dist::Infra::PRODUCT} on the systems in policy group \#{node['policy_group']}"
|
61
|
+
action :add
|
62
|
+
end
|
63
|
+
```
|
64
|
+
|
65
|
+
**Add an InSpec waiver to the Compliance Phase using an arbitrary YAML, JSON, or TOML file**:
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
# files ending in .yml or .yaml that exist are parsed as YAML
|
69
|
+
inspec_waiver "/path/to/my/waiver.yml"
|
70
|
+
|
71
|
+
inspec_waiver "my-waiver-name" do
|
72
|
+
source "/path/to/my/waiver.yml"
|
73
|
+
end
|
74
|
+
|
75
|
+
# files ending in .json that exist are parsed as JSON
|
76
|
+
inspec_waiver "/path/to/my/waiver.json"
|
77
|
+
|
78
|
+
inspec_waiver "my-waiver-name" do
|
79
|
+
source "/path/to/my/waiver.json"
|
80
|
+
end
|
81
|
+
|
82
|
+
# files ending in .toml that exist are parsed as TOML
|
83
|
+
inspec_waiver "/path/to/my/waiver.toml"
|
84
|
+
|
85
|
+
inspec_waiver "my-waiver-name" do
|
86
|
+
source "/path/to/my/waiver.toml"
|
87
|
+
end
|
88
|
+
```
|
89
|
+
|
90
|
+
**Add an InSpec waiver to the Compliance Phase using a hash**:
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
my_hash = { "ssh-01" => {
|
94
|
+
"expiration_date" => "2033-07-31",
|
95
|
+
"run" => false,
|
96
|
+
"justification" => "because"
|
97
|
+
} }
|
98
|
+
|
99
|
+
inspec_waiver "my-waiver-name" do
|
100
|
+
source my_hash
|
101
|
+
end
|
102
|
+
```
|
103
|
+
|
104
|
+
Note that the **inspec_waiver** resource does not update and will not fire notifications (similar to the log resource). This is done to preserve the ability to use
|
105
|
+
the resource while not causing the updated resource count to be larger than zero. Since the resource does not update the state of the managed node, this behavior
|
106
|
+
is still consistent with the configuration management model. Instead, you should use events to observe configuration changes for the compliance phase. It is
|
107
|
+
possible to use the `notify_group` resource to chain notifications of the two resources, but notifications are the wrong model to use, and you should use pure ruby
|
108
|
+
conditionals instead. Compliance configuration should be independent of other resources and should only be conditional based on state/attributes, not other resources.
|
109
|
+
DOC
|
110
|
+
|
111
|
+
property :control, String,
|
112
|
+
name_property: true,
|
113
|
+
description: "The name of the control being waived"
|
114
|
+
|
115
|
+
property :expiration, String,
|
116
|
+
description: "The expiration date of the waiver - provided in YYYY-MM-DD format",
|
117
|
+
callbacks: {
|
118
|
+
"Expiration date should be a valid calendar date and match the following format: YYYY-MM-DD" => proc { |e|
|
119
|
+
re = Regexp.new('\d{4}-\d{2}-\d{2}$').freeze
|
120
|
+
if re.match?(e)
|
121
|
+
Date.valid_date?(*e.split("-").map(&:to_i))
|
122
|
+
else
|
123
|
+
e.nil?
|
124
|
+
end
|
125
|
+
},
|
126
|
+
}
|
127
|
+
|
128
|
+
property :run_test, [true, false],
|
129
|
+
description: "If present and true, the control will run and be reported, but failures in it won’t make the overall run fail. If absent or false, the control will not be run."
|
130
|
+
|
131
|
+
property :justification, String,
|
132
|
+
description: "Can be any text you want and might include a reason for the waiver as well as who signed off on the waiver."
|
133
|
+
|
134
|
+
property :source, [ Hash, String ]
|
135
|
+
|
136
|
+
action :add, description: "Add a waiver to the compliance phase" do
|
137
|
+
if run_context.waiver_collection.valid?(new_resource.control)
|
138
|
+
include_waiver(new_resource.control)
|
139
|
+
else
|
140
|
+
include_waiver(waiver_hash)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
action_class do
|
145
|
+
# If the source is nil and the control / name_property contains a file separator and is a string of a
|
146
|
+
# file that exists, then use that as the file (similar to the package provider automatic source property). Otherwise
|
147
|
+
# just return the source.
|
148
|
+
#
|
149
|
+
# @api private
|
150
|
+
def source
|
151
|
+
@source ||= build_source
|
152
|
+
end
|
153
|
+
|
154
|
+
def build_source
|
155
|
+
return new_resource.source unless new_resource.source.nil?
|
156
|
+
return nil unless new_resource.control.count(::File::SEPARATOR) > 0 || (::File::ALT_SEPARATOR && new_resource.control.count(::File::ALT_SEPARATOR) > 0 )
|
157
|
+
return nil unless ::File.exist?(new_resource.control)
|
158
|
+
|
159
|
+
new_resource.control
|
160
|
+
end
|
161
|
+
|
162
|
+
def waiver_hash
|
163
|
+
case source
|
164
|
+
when Hash
|
165
|
+
source
|
166
|
+
when String
|
167
|
+
parse_file(source)
|
168
|
+
when nil
|
169
|
+
if new_resource.justification.nil? || new_resource.justification == ""
|
170
|
+
raise Chef::Exceptions::ValidationFailed, "Entries for an InSpec waiver must have a justification given, this parameter must have a value."
|
171
|
+
end
|
172
|
+
|
173
|
+
control_hash = {}
|
174
|
+
control_hash["expiration_date"] = new_resource.expiration.to_s unless new_resource.expiration.nil?
|
175
|
+
control_hash["run"] = new_resource.run_test unless new_resource.run_test.nil?
|
176
|
+
control_hash["justification"] = new_resource.justification.to_s
|
177
|
+
|
178
|
+
{ new_resource.control => control_hash }
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
data/lib/chef/resource/mount.rb
CHANGED
@@ -42,7 +42,7 @@ class Chef
|
|
42
42
|
sensitive: true
|
43
43
|
|
44
44
|
property :mount_point, String, name_property: true,
|
45
|
-
coerce: proc { |arg| arg.chomp("/") }, # Removed "/" from the end of str, because it was causing idempotency issue.
|
45
|
+
coerce: proc { |arg| (arg == "/" || arg.match?(":/$")) ? arg : arg.chomp("/") }, # Removed "/" from the end of str, because it was causing idempotency issue.
|
46
46
|
description: "The directory (or path) in which the device is to be mounted. Defaults to the name of the resource block if not provided."
|
47
47
|
|
48
48
|
property :device, String, identity: true,
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# Author:: Tor Magnus Rakvåg (tm@intility.no)
|
2
|
+
# Author:: John McCrae (john.mccrae@progress.com)
|
2
3
|
# Copyright:: 2018, Intility AS
|
3
4
|
# License:: Apache License, Version 2.0
|
4
5
|
#
|
@@ -24,29 +25,110 @@ class Chef
|
|
24
25
|
|
25
26
|
provides :powershell_package_source
|
26
27
|
|
27
|
-
description "Use the **powershell_package_source** resource to register a PowerShell package
|
28
|
+
description "Use the **powershell_package_source** resource to register a PowerShell package source and a Powershell package provider. There are 2 distinct objects we care about here. The first is a Package Source like a PowerShell Repository or a Nuget Source. The second object is a provider that PowerShell uses to get to that source with, like PowerShellGet, Nuget, Chocolatey, etc. "
|
28
29
|
introduced "14.3"
|
30
|
+
examples <<~DOC
|
31
|
+
**Add a new PSRepository that is not trusted and which requires credentials to connect to**:
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
powershell_package_source 'PowerShellModules' do
|
35
|
+
source_name "PowerShellModules"
|
36
|
+
source_location "https://pkgs.dev.azure.com/some-org/some-project/_packaging/some_feed/nuget/v2"
|
37
|
+
publish_location "https://pkgs.dev.azure.com/some-org/some-project/_packaging/some_feed/nuget/v2"
|
38
|
+
trusted false
|
39
|
+
user "someuser@somelocation.io"
|
40
|
+
password "my_password"
|
41
|
+
provider_name "PSRepository"
|
42
|
+
action :register
|
43
|
+
end
|
44
|
+
```
|
45
|
+
|
46
|
+
**Add a new Package Source that uses Chocolatey as the Package Provider**:
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
powershell_package_source 'PowerShellModules' do
|
50
|
+
source_name "PowerShellModules"
|
51
|
+
source_location "https://pkgs.dev.azure.com/some-org/some-project/_packaging/some_feed/nuget/v2"
|
52
|
+
publish_location "https://pkgs.dev.azure.com/some-org/some-project/_packaging/some_feed/nuget/v2"
|
53
|
+
trusted true
|
54
|
+
provider_name "chocolatey"
|
55
|
+
action :register
|
56
|
+
end
|
57
|
+
```
|
58
|
+
|
59
|
+
**Add a new PowerShell Script source that is trusted**:
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
powershell_package_source 'MyDodgyScript' do
|
63
|
+
source_name "MyDodgyScript"
|
64
|
+
script_source_location "https://pkgs.dev.azure.com/some-org/some-project/_packaging/some_feed/nuget/v2"
|
65
|
+
script_publish_location "https://pkgs.dev.azure.com/some-org/some-project/_packaging/some_feed/nuget/v2"
|
66
|
+
trusted true
|
67
|
+
action :register
|
68
|
+
end
|
69
|
+
```
|
70
|
+
|
71
|
+
**Update my existing PSRepository to make it Trusted after all**:
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
powershell_package_source 'MyPSModule' do
|
75
|
+
source_name "MyPSModule"
|
76
|
+
trusted true
|
77
|
+
action :set
|
78
|
+
end
|
79
|
+
```
|
80
|
+
|
81
|
+
**Update a Nuget package source with a new name and make it trusted**:
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
powershell_package_source 'PowerShellModules -> GoldFishBowl' do
|
85
|
+
source_name "PowerShellModules"
|
86
|
+
new_name "GoldFishBowl"
|
87
|
+
provider_name "Nuget"
|
88
|
+
trusted true
|
89
|
+
action :set
|
90
|
+
end
|
91
|
+
```
|
92
|
+
|
93
|
+
**Update a Nuget package source with a new name when the source is secured with a username and password**:
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
powershell_package_source 'PowerShellModules -> GoldFishBowl' do
|
97
|
+
source_name "PowerShellModules"
|
98
|
+
new_name "GoldFishBowl"
|
99
|
+
trusted true
|
100
|
+
user "user@domain.io"
|
101
|
+
password "some_secret_password"
|
102
|
+
action :set
|
103
|
+
end
|
104
|
+
```
|
105
|
+
|
106
|
+
**Unregister a package source**:
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
powershell_package_source 'PowerShellModules' do
|
110
|
+
source_name "PowerShellModules"
|
111
|
+
action :unregister
|
112
|
+
end
|
113
|
+
```
|
114
|
+
DOC
|
29
115
|
|
30
116
|
property :source_name, String,
|
31
|
-
description: "
|
117
|
+
description: "A label that names your package source.",
|
32
118
|
name_property: true
|
33
119
|
|
34
|
-
property :
|
35
|
-
|
36
|
-
|
120
|
+
property :new_name, String,
|
121
|
+
introduced: "17.6",
|
122
|
+
description: "Used to change the name of a standard package source."
|
37
123
|
|
38
|
-
property :
|
39
|
-
|
40
|
-
|
124
|
+
property :source_location, String,
|
125
|
+
introduced: "17.6",
|
126
|
+
description: "The URL to the location to retrieve modules from."
|
41
127
|
|
42
|
-
|
43
|
-
equal_to: %w{ Programs msi NuGet msu PowerShellGet psl chocolatey },
|
44
|
-
validation_message: "The following providers are supported: 'Programs', 'msi', 'NuGet', 'msu', 'PowerShellGet', 'psl' or 'chocolatey'",
|
45
|
-
description: "The package management provider for the source.",
|
46
|
-
default: "NuGet"
|
128
|
+
alias :url :source_location
|
47
129
|
|
48
130
|
property :publish_location, String,
|
49
|
-
description: "The URL where modules will be published to
|
131
|
+
description: "The URL where modules will be published to. Only valid if the provider is `PowerShellGet`."
|
50
132
|
|
51
133
|
property :script_source_location, String,
|
52
134
|
description: "The URL where scripts are located for this source. Only valid if the provider is `PowerShellGet`."
|
@@ -54,6 +136,24 @@ class Chef
|
|
54
136
|
property :script_publish_location, String,
|
55
137
|
description: "The location where scripts will be published to for this source. Only valid if the provider is `PowerShellGet`."
|
56
138
|
|
139
|
+
property :trusted, [TrueClass, FalseClass],
|
140
|
+
description: "Whether or not to trust packages from this source. Used when creating a NON-PSRepository Package Source",
|
141
|
+
default: false
|
142
|
+
|
143
|
+
property :user, String,
|
144
|
+
introduced: "17.6",
|
145
|
+
description: "A username that, as part of a credential object, is used to register a repository or other package source with."
|
146
|
+
|
147
|
+
property :password, String,
|
148
|
+
introduced: "17.6",
|
149
|
+
description: "A password that, as part of a credential object, is used to register a repository or other package source with."
|
150
|
+
|
151
|
+
property :provider_name, String,
|
152
|
+
equal_to: %w{ Programs msi NuGet msu PowerShellGet psl chocolatey winget },
|
153
|
+
validation_message: "The following providers are supported: 'Programs', 'msi', 'NuGet', 'msu', 'PowerShellGet', 'psl', 'chocolatey' or 'winget'",
|
154
|
+
description: "The package management provider for the package source. The default is PowerShellGet and this option need only be set otherwise in specific use cases.",
|
155
|
+
default: "NuGet"
|
156
|
+
|
57
157
|
load_current_value do
|
58
158
|
cmd = load_resource_state_script(source_name)
|
59
159
|
repo = powershell_exec!(cmd)
|
@@ -62,7 +162,9 @@ class Chef
|
|
62
162
|
else
|
63
163
|
status = repo.result
|
64
164
|
end
|
65
|
-
|
165
|
+
source_name status["source_name"]
|
166
|
+
new_name status["new_name"]
|
167
|
+
source_location status["source_location"]
|
66
168
|
trusted status["trusted"]
|
67
169
|
provider_name status["provider_name"]
|
68
170
|
publish_location status["publish_location"]
|
@@ -70,97 +172,159 @@ class Chef
|
|
70
172
|
script_publish_location status["script_publish_location"]
|
71
173
|
end
|
72
174
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
175
|
+
# Notes:
|
176
|
+
# There are 2 objects we care about with this code. 1) The Package Provider which can be Nuget, PowerShellGet, Chocolatey, et al. 2) The PackageSource where the files we want access to live. The Package Provider gets us access to the Package Source.
|
177
|
+
# Per the Microsoft docs you can only have one provider for one source. Enter the PSRepository. It is a sub-type of Package Source.
|
178
|
+
# If you register a new PSRepository you get both a PSRepository object AND a Package Source object which are distinct. If you call "Get-PSRepository -Name 'PSGallery'" from powershell, notice that the Packageprovider is Nuget
|
179
|
+
# now go execute "Get-PackageSource -Name 'PSGallery'" and notice that the PackageProvider is PowerShellGet. If you set a new PSRepository without specifying a PackageProvider ("Register-PSRepository -Name 'foo' -source...") the command will create both
|
180
|
+
# a PackageSource and a PSRepository with different providers.
|
181
|
+
|
182
|
+
# Unregistering a PackageSource (unregister-packagesource -name 'foo') where that source is also a PSRepository also causes that object to delete as well. This makes sense as PSRepository is a sub-type of packagesource.
|
183
|
+
# All PSRepositories are PackageSources, and all PackageSources with Provider PowerShellGet are PSRepositories. They are 2 different views of the same object.
|
184
|
+
|
185
|
+
action :register, description: "Registers a PowerShell package source." do
|
186
|
+
package_details = get_package_source_details
|
187
|
+
output = package_details.result
|
188
|
+
if output == "PSRepository" || output == "PackageSource"
|
189
|
+
action_set
|
190
|
+
elsif new_resource.provider_name.downcase.strip == "powershellget"
|
191
|
+
converge_by("register source: #{new_resource.source_name}") do
|
192
|
+
register_cmd = build_ps_repository_command("Register", new_resource)
|
193
|
+
res = powershell_exec(register_cmd)
|
194
|
+
raise "Failed to register #{new_resource.source_name}: #{res.errors}" if res.error?
|
88
195
|
end
|
89
196
|
else
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
197
|
+
converge_by("register source: #{new_resource.source_name}") do
|
198
|
+
register_cmd = build_package_source_command("Register", new_resource)
|
199
|
+
res = powershell_exec(register_cmd)
|
200
|
+
raise "Failed to register #{new_resource.source_name}: #{res.errors}" if res.error?
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
action :set, description: "Updates an existing PSRepository or Package Source" do
|
206
|
+
package_details = get_package_source_details
|
207
|
+
output = package_details.result
|
208
|
+
if output == "PSRepository"
|
209
|
+
converge_if_changed :source_location, :trusted, :publish_location, :script_source_location, :script_publish_location, :source_name do
|
210
|
+
set_cmd = build_ps_repository_command("Set", new_resource)
|
211
|
+
res = powershell_exec(set_cmd)
|
212
|
+
raise "Failed to Update #{new_resource.source_name}: #{res.errors}" if res.error?
|
213
|
+
end
|
214
|
+
elsif output == "PackageSource"
|
215
|
+
converge_if_changed :source_location, :trusted, :new_name, :provider_name do
|
216
|
+
set_cmd = build_package_source_command("Set", new_resource)
|
217
|
+
res = powershell_exec(set_cmd)
|
218
|
+
raise "Failed to Update #{new_resource.source_name}: #{res.errors}" if res.error?
|
102
219
|
end
|
103
220
|
end
|
104
221
|
end
|
105
222
|
|
106
223
|
action :unregister, description: "Unregisters the PowerShell package source." do
|
107
|
-
|
108
|
-
|
224
|
+
package_details = get_package_source_details
|
225
|
+
output = package_details.result
|
226
|
+
if output == "PackageSource" || output == "PSRepository"
|
227
|
+
unregister_cmd = "Unregister-PackageSource -Name '#{new_resource.source_name}'"
|
109
228
|
converge_by("unregister source: #{new_resource.source_name}") do
|
110
|
-
res = powershell_exec(unregister_cmd)
|
229
|
+
res = powershell_exec!(unregister_cmd)
|
111
230
|
raise "Failed to unregister #{new_resource.source_name}: #{res.errors}" if res.error?
|
112
231
|
end
|
232
|
+
else
|
233
|
+
logger.warn("*****************************************")
|
234
|
+
logger.warn("Failed to unregister #{new_resource.source_name}: Package Source does not exist")
|
235
|
+
logger.warn("*****************************************")
|
113
236
|
end
|
114
237
|
end
|
115
238
|
|
116
239
|
action_class do
|
117
|
-
def package_source_exists?
|
118
|
-
cmd = powershell_exec!("(Get-PackageSource -Name '#{new_resource.source_name}' -ErrorAction SilentlyContinue).Name")
|
119
|
-
!cmd.result.empty? && cmd.result.to_s.downcase.strip == new_resource.source_name.downcase
|
120
|
-
end
|
121
240
|
|
122
|
-
def
|
123
|
-
|
241
|
+
def get_package_source_details
|
242
|
+
powershell_exec! <<~EOH
|
243
|
+
$package_details = Get-PackageSource -Name '#{new_resource.source_name}' -ErrorAction SilentlyContinue
|
244
|
+
if ($package_details.ProviderName -match "PowerShellGet"){
|
245
|
+
return "PSRepository"
|
246
|
+
}
|
247
|
+
elseif ($package_details.ProviderName ) {
|
248
|
+
return "PackageSource"
|
249
|
+
}
|
250
|
+
elseif ($null -eq $package_details)
|
251
|
+
{
|
252
|
+
return "Unregistered"
|
253
|
+
}
|
254
|
+
EOH
|
124
255
|
end
|
125
256
|
|
126
257
|
def build_ps_repository_command(cmdlet_type, new_resource)
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
258
|
+
if new_resource.trusted == true
|
259
|
+
install_policy = "Trusted"
|
260
|
+
else
|
261
|
+
install_policy = "Untrusted"
|
262
|
+
end
|
263
|
+
if new_resource.user && new_resource.password
|
264
|
+
cmd = "$user = '#{new_resource.user}';"
|
265
|
+
cmd << "[securestring]$secure_password = Convertto-SecureString -String '#{new_resource.password}' -AsPlainText -Force;"
|
266
|
+
cmd << "$Credentials = New-Object System.Management.Automation.PSCredential -Argumentlist ($user, $secure_password);"
|
267
|
+
cmd << "#{cmdlet_type}-PSRepository -Name '#{new_resource.source_name}'"
|
268
|
+
cmd << " -SourceLocation '#{new_resource.source_location}'" if new_resource.source_location
|
269
|
+
cmd << " -InstallationPolicy '#{install_policy}'"
|
270
|
+
cmd << " -PublishLocation '#{new_resource.publish_location}'" if new_resource.publish_location
|
271
|
+
cmd << " -ScriptSourceLocation '#{new_resource.script_source_location}'" if new_resource.script_source_location
|
272
|
+
cmd << " -ScriptPublishLocation '#{new_resource.script_publish_location}'" if new_resource.script_publish_location
|
273
|
+
cmd << " -Credential $Credentials"
|
274
|
+
cmd << " | Out-Null"
|
275
|
+
else
|
276
|
+
cmd = "#{cmdlet_type}-PSRepository -Name '#{new_resource.source_name}'"
|
277
|
+
cmd << " -SourceLocation '#{new_resource.source_location}'" if new_resource.source_location
|
278
|
+
cmd << " -InstallationPolicy '#{install_policy}'"
|
279
|
+
cmd << " -PublishLocation '#{new_resource.publish_location}'" if new_resource.publish_location
|
280
|
+
cmd << " -ScriptSourceLocation '#{new_resource.script_source_location}'" if new_resource.script_source_location
|
281
|
+
cmd << " -ScriptPublishLocation '#{new_resource.script_publish_location}'" if new_resource.script_publish_location
|
282
|
+
cmd << " | Out-Null"
|
283
|
+
end
|
134
284
|
cmd
|
135
285
|
end
|
136
286
|
|
137
287
|
def build_package_source_command(cmdlet_type, new_resource)
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
288
|
+
if new_resource.user && new_resource.password
|
289
|
+
cmd = "$user = '#{new_resource.user}';"
|
290
|
+
cmd << "[securestring]$secure_password = Convertto-SecureString -String '#{new_resource.password}' -AsPlainText -Force;"
|
291
|
+
cmd << "$Credentials = New-Object System.Management.Automation.PSCredential -Argumentlist ($user, $secure_password);"
|
292
|
+
cmd << "#{cmdlet_type}-PackageSource -Name '#{new_resource.source_name}'"
|
293
|
+
cmd << " -Location '#{new_resource.source_location}'" if new_resource.source_location
|
294
|
+
cmd << " -Trusted" if new_resource.trusted
|
295
|
+
cmd << " -ProviderName '#{new_resource.provider_name}'" if new_resource.provider_name
|
296
|
+
cmd << " -Credential $credentials"
|
297
|
+
cmd << " | Out-Null"
|
298
|
+
cmd
|
299
|
+
else
|
300
|
+
cmd = "#{cmdlet_type}-PackageSource -Name '#{new_resource.source_name}'"
|
301
|
+
cmd << " -NewName '#{new_resource.new_name}'" if new_resource.new_name
|
302
|
+
cmd << " -Location '#{new_resource.source_location}'" if new_resource.source_location
|
303
|
+
cmd << " -Trusted" if new_resource.trusted
|
304
|
+
cmd << " -ProviderName '#{new_resource.provider_name}'" if new_resource.provider_name
|
305
|
+
cmd << " | Out-Null"
|
306
|
+
cmd
|
307
|
+
end
|
144
308
|
end
|
145
309
|
end
|
146
310
|
end
|
147
311
|
|
148
312
|
private
|
149
313
|
|
150
|
-
def load_resource_state_script(
|
314
|
+
def load_resource_state_script(source_name)
|
151
315
|
<<-EOH
|
152
316
|
$PSDefaultParameterValues = @{
|
153
317
|
"*:WarningAction" = "SilentlyContinue"
|
154
318
|
}
|
155
|
-
if(Get-PackageSource -Name '#{
|
156
|
-
if ((Get-PackageSource -Name '#{
|
157
|
-
(Get-PSRepository -Name '#{
|
319
|
+
if(Get-PackageSource -Name '#{source_name}' -ErrorAction SilentlyContinue) {
|
320
|
+
if ((Get-PackageSource -Name '#{source_name}').ProviderName -eq 'PowerShellGet') {
|
321
|
+
(Get-PSRepository -Name '#{source_name}') | Select @{n='source_name';e={$_.Name}}, @{n='source_location';e={$_.SourceLocation}},
|
158
322
|
@{n='trusted';e={$_.Trusted}}, @{n='provider_name';e={$_.PackageManagementProvider}}, @{n='publish_location';e={$_.PublishLocation}},
|
159
323
|
@{n='script_source_location';e={$_.ScriptSourceLocation}}, @{n='script_publish_location';e={$_.ScriptPublishLocation}}
|
160
324
|
}
|
161
325
|
else {
|
162
|
-
(Get-PackageSource -Name '#{
|
163
|
-
@{n='provider_name';e={$_.ProviderName}}, @{n='trusted';e={$_.IsTrusted}}
|
326
|
+
(Get-PackageSource -Name '#{source_name}') | Select @{n='source_name';e={$_.Name}}, @{n='new_name';e={$_.Name}}, @{n='source_location';e={$_.Location}},
|
327
|
+
@{n='provider_name';e={$_.ProviderName}}, @{n='trusted';e={$_.IsTrusted}}, @{n='publish_location';e={$_.PublishLocation}}
|
164
328
|
}
|
165
329
|
}
|
166
330
|
EOH
|