chef 18.1.0 → 18.2.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +0 -3
  3. data/chef-universal-mingw-ucrt.gemspec +2 -2
  4. data/chef.gemspec +1 -1
  5. data/lib/chef/application/base.rb +18 -2
  6. data/lib/chef/client.rb +23 -6
  7. data/lib/chef/http/authenticator.rb +117 -34
  8. data/lib/chef/platform/query_helpers.rb +4 -2
  9. data/lib/chef/resource/apt_repository.rb +20 -2
  10. data/lib/chef/resource/bash.rb +13 -0
  11. data/lib/chef/resource/dsc_script.rb +1 -1
  12. data/lib/chef/resource/launchd.rb +2 -2
  13. data/lib/chef/resource/macos_userdefaults.rb +9 -5
  14. data/lib/chef/resource/rhsm_register.rb +1 -1
  15. data/lib/chef/resource/selinux_fcontext.rb +1 -1
  16. data/lib/chef/resource/selinux_login.rb +129 -0
  17. data/lib/chef/resource/selinux_permissive.rb +1 -1
  18. data/lib/chef/resource/selinux_port.rb +1 -1
  19. data/lib/chef/resource/selinux_state.rb +1 -1
  20. data/lib/chef/resource/selinux_user.rb +137 -0
  21. data/lib/chef/resource/service.rb +1 -1
  22. data/lib/chef/resource/user.rb +2 -2
  23. data/lib/chef/resource/windows_user_privilege.rb +14 -10
  24. data/lib/chef/resources.rb +2 -0
  25. data/lib/chef/version.rb +1 -1
  26. data/spec/data/trusted_certs/intermediate.pem +38 -27
  27. data/spec/data/trusted_certs/opscode.pem +33 -54
  28. data/spec/functional/resource/macos_userdefaults_spec.rb +4 -4
  29. data/spec/integration/client/client_spec.rb +22 -16
  30. data/spec/spec_helper.rb +3 -3
  31. data/spec/unit/client_spec.rb +26 -2
  32. data/spec/unit/compliance/runner_spec.rb +8 -0
  33. data/spec/unit/http/authenticator_spec.rb +64 -11
  34. data/spec/unit/provider/apt_repository_spec.rb +26 -5
  35. data/spec/unit/resource/macos_user_defaults_spec.rb +4 -4
  36. data/spec/unit/resource/selinux_login_spec.rb +73 -0
  37. data/spec/unit/resource/selinux_user_spec.rb +92 -0
  38. metadata +17 -16
  39. data/lib/chef/powershell.rb +0 -81
  40. data/spec/data/chef_guid +0 -1
  41. data/spec/data/nodes/mcwfhpowell.json +0 -3
@@ -20,7 +20,7 @@ class Chef
20
20
 
21
21
  provides :selinux_permissive
22
22
 
23
- description "Use **selinux_permissive** resource to allows some types to misbehave without stopping them. Not as good as specific policies, but better than disabling SELinux entirely."
23
+ description "Use the **selinux_permissive** resource to allow some domains to misbehave without stopping them. This is not as good as setting specific policies, but better than disabling SELinux entirely."
24
24
  introduced "18.0"
25
25
  examples <<~DOC
26
26
  **Disable enforcement on Apache**:
@@ -21,7 +21,7 @@ class Chef
21
21
 
22
22
  provides :selinux_port
23
23
 
24
- description "Use **selinux_port** resource to allows assigning a network port to a certain SELinux context, e.g. for running a webserver on a non-standard port."
24
+ description "Use the **selinux_port** resource to assign a network port to a specific SELinux context. For example, running a web server on a non-standard port."
25
25
  introduced "18.0"
26
26
  examples <<~DOC
27
27
  **Allow nginx/apache to bind to port 5678 by giving it the http_port_t context**:
@@ -56,7 +56,7 @@ class Chef
56
56
 
57
57
  property :persistent, [true, false],
58
58
  default: true,
59
- description: "Persist status update to the selinux configuration file."
59
+ description: "Set the status update in the SELinux configuration file."
60
60
 
61
61
  property :policy, String,
62
62
  default: lazy { default_policy_platform },
@@ -0,0 +1,137 @@
1
+ #
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ # See the License for the specific language governing permissions and
12
+ # limitations under the License.
13
+
14
+ require_relative "../resource"
15
+ require_relative "selinux/common_helpers"
16
+
17
+ class Chef
18
+ class Resource
19
+ class SelinuxUser < Chef::Resource
20
+ unified_mode true
21
+
22
+ provides :selinux_user
23
+
24
+ description "Use the **selinux_user** resource to add, update, or remove SELinux users."
25
+ introduced "18.1"
26
+ examples <<~DOC
27
+ **Manage test_u SELinux user with a level and range of s0 and roles sysadm_r and staff_r**:
28
+
29
+ ```ruby
30
+ selinux_user 'test_u' do
31
+ level 's0'
32
+ range 's0'
33
+ roles %w(sysadm_r staff_r)
34
+ end
35
+ ```
36
+ DOC
37
+
38
+ property :user, String,
39
+ name_property: true,
40
+ description: "An optional property to set the SELinux user value if it differs from the resource block's name."
41
+
42
+ property :level, String,
43
+ description: "MLS/MCS security level for the SELinux user."
44
+
45
+ property :range, String,
46
+ description: "MLS/MCS security range for the SELinux user."
47
+
48
+ property :roles, Array,
49
+ description: "Associated SELinux roles for the user.",
50
+ coerce: proc { |r| Array(r).sort }
51
+
52
+ load_current_value do |new_resource|
53
+ users = shell_out!("semanage user -l").stdout.split("\n")
54
+
55
+ current_user = users.grep(/^#{Regexp.escape(new_resource.user)}\s+/) do |u|
56
+ u.match(/^(?<user>[^\s]+)\s+(?<prefix>[^\s]+)\s+(?<level>[^\s]+)\s+(?<range>[^\s]+)\s+(?<roles>.*)$/)
57
+ # match returns [<Match 'data'>] or [], shift converts that to <Match 'data'> or nil
58
+ end.shift
59
+
60
+ current_value_does_not_exist! unless current_user
61
+
62
+ # Existing resources should maintain their current configuration unless otherwise specified
63
+ new_resource.level ||= current_user[:level]
64
+ new_resource.range ||= current_user[:range]
65
+ new_resource.roles ||= current_user[:roles].to_s.split.sort
66
+
67
+ level current_user[:level]
68
+ range current_user[:range]
69
+ roles current_user[:roles].to_s.split.sort
70
+ end
71
+
72
+ action_class do
73
+ include Chef::SELinux::CommonHelpers
74
+
75
+ def semanage_user_args
76
+ # Generate arguments for semanage user -a or -m
77
+ args = ""
78
+
79
+ args += " -L #{new_resource.level}" if new_resource.level
80
+ args += " -r #{new_resource.range}" if new_resource.range
81
+ args += " -R '#{new_resource.roles.join(" ")}'" unless new_resource.roles.to_a.empty?
82
+
83
+ args
84
+ end
85
+ end
86
+
87
+ action :manage, description: "Sets the SELinux user to the desired settings regardless of previous state." do
88
+ run_action(:add)
89
+ run_action(:modify)
90
+ end
91
+
92
+ # Create if doesn't exist, do not touch if user already exists
93
+ action :add, description: "Creates the SELinux user if not previously created." do
94
+ raise "The roles property must be populated to create a new SELinux user" if new_resource.roles.to_a.empty?
95
+
96
+ if selinux_disabled?
97
+ Chef::Log.warn("Unable to add SELinux user #{new_resource.user} as SELinux is disabled")
98
+ return
99
+ end
100
+
101
+ unless current_resource
102
+ converge_if_changed do
103
+ shell_out!("semanage user -a#{semanage_user_args} #{new_resource.user}")
104
+ end
105
+ end
106
+ end
107
+
108
+ # Only modify port if it exists & doesn't have the correct context already
109
+ action :modify, description: "Updates the SELinux user if previously created." do
110
+ if selinux_disabled?
111
+ Chef::Log.warn("Unable to modify SELinux user #{new_resource.user} as SELinux is disabled")
112
+ return
113
+ end
114
+
115
+ if current_resource
116
+ converge_if_changed do
117
+ shell_out!("semanage user -m#{semanage_user_args} #{new_resource.user}")
118
+ end
119
+ end
120
+ end
121
+
122
+ # Delete if exists
123
+ action :delete, description: "Removes the SELinux user if previously created." do
124
+ if selinux_disabled?
125
+ Chef::Log.warn("Unable to delete SELinux user #{new_resource.user} as SELinux is disabled")
126
+ return
127
+ end
128
+
129
+ if current_resource
130
+ converge_by "deleting SELinux user #{new_resource.user}" do
131
+ shell_out!("semanage user -d #{new_resource.user}")
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
@@ -81,7 +81,7 @@ class Chef
81
81
  # specify overrides for the start_command, stop_command and
82
82
  # restart_command properties.
83
83
  property :init_command, String,
84
- description: "The path to the init script that is associated with the service. Use init_command to prevent the need to specify overrides for the start_command, stop_command, and restart_command properties. When this property is not specified, the #{ChefUtils::Dist::Infra::PRODUCT} will use the default init command for the service provider being used.",
84
+ description: "The path to the init script that is associated with the service. Use `init_command` to prevent the need to specify overrides for the `start_command`, `stop_command`, and `restart_command` properties. When this property is not specified, the #{ChefUtils::Dist::Infra::PRODUCT} will use the default init command for the service provider being used.",
85
85
  desired_state: false
86
86
 
87
87
  # if the service is enabled or not
@@ -74,12 +74,12 @@ class Chef
74
74
  alias_method :group, :gid
75
75
 
76
76
  property :expire_date, [ String, NilClass ],
77
- description: "(Linux) The date on which the user account will be disabled. The date is specified in the format YYYY-MM-DD.",
77
+ description: "(Linux) The date on which the user account will be disabled. The date is specified in YYYY-MM-DD format.",
78
78
  introduced: "18.0",
79
79
  desired_state: false
80
80
 
81
81
  property :inactive, [ String, Integer, NilClass ],
82
- description: "(Linux) The number of days after a password expires until the account is permanently disabled. A value of 0 disables the account as soon as the password has expired, and a value of -1 disables the feature.",
82
+ description: "(Linux) The number of days after a password expires until the account is permanently disabled. A value of `0` disables the account as soon as the password has expired, and a value of `-1` disables the feature.",
83
83
  introduced: "18.0",
84
84
  desired_state: false
85
85
  end
@@ -23,12 +23,14 @@ class Chef
23
23
  class WindowsUserPrivilege < Chef::Resource
24
24
 
25
25
  provides :windows_user_privilege
26
- description "The windows_user_privilege resource allows to add a privilege to a principal or (User/Group).\n Ref: https://docs.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/user-rights-assignment"
26
+ description "Use the **windows_user_privilege** resource to set privileges for a principal, user, or group.\n See [Microsoft's user rights assignment documentation](https://learn.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/user-rights-assignment) for more information."
27
27
 
28
28
  introduced "16.0"
29
29
 
30
30
  examples <<~DOC
31
- **Set the SeNetworkLogonRight Privilege for the Builtin Administrators Group and Authenticated Users**:
31
+ **Set the SeNetworkLogonRight privilege for the Builtin Administrators and Authenticated Users groups**:
32
+
33
+ The `:set` action will add this privilege for these two groups and remove this privilege from all other groups or users.
32
34
 
33
35
  ```ruby
34
36
  windows_user_privilege 'Network Logon Rights' do
@@ -38,7 +40,9 @@ class Chef
38
40
  end
39
41
  ```
40
42
 
41
- **Provide only the Builtin Guests and Administrator Groups with the SeCreatePageFile Privilege**:
43
+ **Set the SeCreatePagefilePrivilege privilege for the Builtin Guests and Administrator groups**:
44
+
45
+ The `:set` action will add this privilege for these two groups and remove this privilege from all other groups or users.
42
46
 
43
47
  ```ruby
44
48
  windows_user_privilege 'Create Pagefile' do
@@ -48,7 +52,7 @@ class Chef
48
52
  end
49
53
  ```
50
54
 
51
- **Add the SeDenyRemoteInteractiveLogonRight Privilege to the 'Remote interactive logon' principal**:
55
+ **Add the SeDenyRemoteInteractiveLogonRight privilege to the 'Remote interactive logon' principal**:
52
56
 
53
57
  ```ruby
54
58
  windows_user_privilege 'Remote interactive logon' do
@@ -57,7 +61,7 @@ class Chef
57
61
  end
58
62
  ```
59
63
 
60
- **Add to the Builtin Guests Group the SeCreatePageFile Privilege**:
64
+ **Add the SeCreatePageFilePrivilege privilege to the Builtin Guests group**:
61
65
 
62
66
  ```ruby
63
67
  windows_user_privilege 'Guests add Create Pagefile' do
@@ -67,7 +71,7 @@ class Chef
67
71
  end
68
72
  ```
69
73
 
70
- **Remove the SeCreatePageFile Privilege from the Builtin Guests Group**:
74
+ **Remove the SeCreatePageFilePrivilege privilege from the Builtin Guests group**:
71
75
 
72
76
  ```ruby
73
77
  windows_user_privilege 'Create Pagefile' do
@@ -77,7 +81,7 @@ class Chef
77
81
  end
78
82
  ```
79
83
 
80
- **Clear all users from the SeDenyNetworkLogonRight Privilege**:
84
+ **Clear the SeDenyNetworkLogonRight privilege from all users**:
81
85
 
82
86
  ```ruby
83
87
  windows_user_privilege 'Allow any user the Network Logon right' do
@@ -135,15 +139,15 @@ class Chef
135
139
  }.freeze
136
140
 
137
141
  property :principal, String,
138
- description: "An optional property to add the privilege for given principal. Use only with add and remove action. Principal can either be a User/Group or one of special identities found here Ref: https://docs.microsoft.com/en-us/windows/security/identity-protection/access-control/special-identities",
142
+ description: "An optional property to add the privilege for given principal. Use only with add and remove action. Principal can either be a user, group, or [special identity](https://docs.microsoft.com/en-us/windows/security/identity-protection/access-control/special-identities).",
139
143
  name_property: true
140
144
 
141
145
  property :users, [Array, String],
142
- description: "An optional property to set the privilege for given users. Use only with set action.",
146
+ description: "An optional property to set the privilege for the specified users. Use only with `:set` action",
143
147
  coerce: proc { |v| Array(v) }
144
148
 
145
149
  property :privilege, [Array, String],
146
- description: "One or more privileges to set for principal or users/groups. For more information on what each privilege does Ref: https://learn.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/user-rights-assignment",
150
+ description: "One or more privileges to set for principal or users/groups. For more information, see [Microsoft's documentation on what each privilege does](https://learn.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/user-rights-assignment).",
147
151
  required: true,
148
152
  coerce: proc { |v| Array(v) },
149
153
  callbacks: {
@@ -127,10 +127,12 @@ require_relative "resource/script"
127
127
  require_relative "resource/selinux_boolean"
128
128
  require_relative "resource/selinux_fcontext"
129
129
  require_relative "resource/selinux_install"
130
+ require_relative "resource/selinux_login"
130
131
  require_relative "resource/selinux_module"
131
132
  require_relative "resource/selinux_permissive"
132
133
  require_relative "resource/selinux_port"
133
134
  require_relative "resource/selinux_state"
135
+ require_relative "resource/selinux_user"
134
136
  require_relative "resource/service"
135
137
  require_relative "resource/sudo"
136
138
  require_relative "resource/sysctl"
data/lib/chef/version.rb CHANGED
@@ -23,7 +23,7 @@ require_relative "version_string"
23
23
 
24
24
  class Chef
25
25
  CHEF_ROOT = File.expand_path("..", __dir__)
26
- VERSION = Chef::VersionString.new("18.1.0")
26
+ VERSION = Chef::VersionString.new("18.2.7")
27
27
  end
28
28
 
29
29
  #
@@ -1,27 +1,38 @@
1
- -----BEGIN CERTIFICATE-----
2
- MIIEjzCCA3egAwIBAgIQBp4dt3/PHfupevXlyaJANzANBgkqhkiG9w0BAQUFADBh
3
- MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
4
- d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
5
- QTAeFw0xMzAzMDgxMjAwMDBaFw0yMzAzMDgxMjAwMDBaMEgxCzAJBgNVBAYTAlVT
6
- MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxIjAgBgNVBAMTGURpZ2lDZXJ0IFNlY3Vy
7
- ZSBTZXJ2ZXIgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC7V+Qh
8
- qdWbYDd+jqFhf4HiGsJ1ZNmRUAvkNkQkbjDSm3on+sJqrmpwCTi5IArIZRBKiKwx
9
- 8tyS8mOhXYBjWYCSIxzm73ZKUDXJ2HE4ue3w5kKu0zgmeTD5IpTG26Y/QXiQ2N5c
10
- fml9+JAVOtChoL76srIZodgr0c6/a91Jq6OS/rWryME+7gEA2KlEuEJziMNh9atK
11
- gygK0tRJ+mqxzd9XLJTl4sqDX7e6YlwvaKXwwLn9K9HpH9gaYhW9/z2m98vv5ttl
12
- LyU47PvmIGZYljQZ0hXOIdMkzNkUb9j+Vcfnb7YPGoxJvinyulqagSY3JG/XSBJs
13
- Lln1nBi72fZo4t9FAgMBAAGjggFaMIIBVjASBgNVHRMBAf8ECDAGAQH/AgEAMA4G
14
- A1UdDwEB/wQEAwIBhjA0BggrBgEFBQcBAQQoMCYwJAYIKwYBBQUHMAGGGGh0dHA6
15
- Ly9vY3NwLmRpZ2ljZXJ0LmNvbTB7BgNVHR8EdDByMDegNaAzhjFodHRwOi8vY3Js
16
- My5kaWdpY2VydC5jb20vRGlnaUNlcnRHbG9iYWxSb290Q0EuY3JsMDegNaAzhjFo
17
- dHRwOi8vY3JsNC5kaWdpY2VydC5jb20vRGlnaUNlcnRHbG9iYWxSb290Q0EuY3Js
18
- MD0GA1UdIAQ2MDQwMgYEVR0gADAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5k
19
- aWdpY2VydC5jb20vQ1BTMB0GA1UdDgQWBBSQcds363PI79zVHhK2NLorWqCmkjAf
20
- BgNVHSMEGDAWgBQD3lA1VtFMu2bwo+IbG8OXsj3RVTANBgkqhkiG9w0BAQUFAAOC
21
- AQEAMM7RlVEArgYLoQ4CwBestn+PIPZAdXQczHixpE/q9NDEnaLegQcmH0CIUfAf
22
- z7dMQJnQ9DxxmHOIlywZ126Ej6QfnFog41FcsMWemWpPyGn3EP9OrRnZyVizM64M
23
- 2ZYpnnGycGOjtpkWQh1l8/egHn3F1GUUsmKE1GxcCAzYbJMrtHZZitF//wPYwl24
24
- LyLWOPD2nGt9RuuZdPfrSg6ppgTre87wXGuYMVqYQOtpxAX0IKjKCDplbDgV9Vws
25
- slXkLGtB8L5cRspKKaBIXiDSRf8F3jSvcEuBOeLKB1d8tjHcISnivpcOd5AUUUDh
26
- v+PMGxmcJcqnBrJT3yOyzxIZow==
27
- -----END CERTIFICATE-----
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIGrTCCBJWgAwIBAgIQDo0oQK5IJZBWGLOoqeF6RzANBgkqhkiG9w0BAQwFADBJ
3
+ MQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xITAfBgNVBAMT
4
+ GERpZ2lDZXJ0IFJTQTQwOTYgUm9vdCBHNTAeFw0yMTA0MTQwMDAwMDBaFw0zMTA0
5
+ MTMyMzU5NTlaMFQxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5j
6
+ LjEsMCoGA1UEAxMjRGlnaUNlcnQgRzUgUlNBNDA5NiBTSEEzODQgMjAyMSBDQTEw
7
+ ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDCwLlUmeGwUTj93uzejg2I
8
+ tHjaSqm+knZ8az09cBAZFLFU9sKDzBHgf43/GpIWIHGLDUGXXZkKtkjJhl6POqda
9
+ XWt/4avSsQgkELz2uefSxhzELBl4o1U50EULTlri3zUBQ11Jr/hfJLxdMAJqKv21
10
+ iVD8GfFDs12Hy08h7IxuA5ROVdBQS2OiU/6Vd4A3uVpzyjaxQsfAvkwz9+3jsozf
11
+ G+kWW+6Fxa3Vt4EbX+3afaBLeIyBlQvPd3pUY8irY3T6MHlglEblraxyGZ3ifvFu
12
+ Vt7S98D5+U4CMFzzGSzCCqMxTkgasTMhP8+PjXRN+mL56xyfw/uVmN9vRPqgbRUD
13
+ g95zx+CRFXgpUQ8yslpl+ECSqCe0cYxm+jWz00VFWtUZAwpE4REGOVdmNGrfNR16
14
+ h7dggpFVfeFy7qCwd9up/sWkBmkZB1zL9ENjg68EH5aEbh+jlbF6HuLv4+jibVlD
15
+ /r+ZW/vJgnMXmUYW1gDl3L//vQ/V4ElqRYzxsSVsq3dwW0SYzI31PKFEb8sqI5IN
16
+ P10MtFtZ1DgISF9I8LJ35dBDqguoonGC0/d+iq2S7ipcpFIo/u3tK/Nu0QvKMEN6
17
+ Dlx6Yhssscj2PhiADKjhRnweWUj/2eKuX8Cb6UmXvh+R4Dm0iEIGop1/r37GUo0z
18
+ nqNszrYZz1zd4GWG6puFWQIDAQABo4IBhDCCAYAwEgYDVR0TAQH/BAgwBgEB/wIB
19
+ ADAdBgNVHQ4EFgQUbYE39zhEfkdCe1al7Lt3ZyEJ9DwwHwYDVR0jBBgwFoAUYm23
20
+ kU/E6qNiYI+g0L61jwZ8aAAwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsG
21
+ AQUFBwMBBggrBgEFBQcDAjB3BggrBgEFBQcBAQRrMGkwJAYIKwYBBQUHMAGGGGh0
22
+ dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBBBggrBgEFBQcwAoY1aHR0cDovL2NhY2Vy
23
+ dHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0UlNBNDA5NlJvb3RHNS5jcnQwQwYDVR0f
24
+ BDwwOjA4oDagNIYyaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0UlNB
25
+ NDA5NlJvb3RHNS5jcmwwPQYDVR0gBDYwNDALBglghkgBhv1sAgEwBwYFZ4EMAQEw
26
+ CAYGZ4EMAQIBMAgGBmeBDAECAjAIBgZngQwBAgMwDQYJKoZIhvcNAQEMBQADggIB
27
+ AGHJE9aY60MSsfdEfqIcrdE0c1dXxis9E1l9at6g18Jpyc1C6PsUHdmo6rJWq8Xe
28
+ NNPkD/4fKhJsrd9TRlUlpIgKiJZW1ituKHV6Ghm7DIRSyx0aMpP9NJ3heV3CIgZr
29
+ MLtJEFuG5WfolWIfu7sle2lYjA3HxA/xQo803jGOhxbEDX/BTzHo/1X7YGvwpRqJ
30
+ +7J1B+2l+TA1r9vAlLfIDQRazVYRNxHpJDOwU0ffKaEPbRrgPtogO+8hLSml9Zoe
31
+ Y8w94f31XbvBFxSbSVpX+/QctNdwx2VuIoRcT8WZ0lZ9aenna5q5AE1C8oTtbw2T
32
+ qoz4NCaM5XPgjvb0DGPBeH8jWveNo1BmClQA2qYXL55f00m8AZ4Hf6oYANt/zbuM
33
+ QPhAoSHWwW4V4Pug3XPXM70LlY50y9kPD/57eHryhO2oXQLLx+l6mg8xzL6vKsHT
34
+ E30whFM32vVTpjejLZ9hJBAJURFaUrH2TZyAmoVbCNy50yuHYQ6FooYpbsbnpYPi
35
+ KW/E9bc201rqm/GQOWJ4zOJ8a5Etn3zY+rlPaxjJvxc3pSMfgtwwrm9KGXHsI1Gf
36
+ ULMwUbXclKV2qR8d6ECtUOIRxoQKutN85lmwB05yddu6uQQg0hHeaGFUk7EU90SV
37
+ ib/FA/op9sXfS3CkOnHQISY0JbWxrzC6eHaKeQi6lR1I
38
+ -----END CERTIFICATE-----
@@ -1,57 +1,36 @@
1
1
  -----BEGIN CERTIFICATE-----
2
- MIIElDCCA3ygAwIBAgIQAf2j627KdciIQ4tyS8+8kTANBgkqhkiG9w0BAQsFADBh
2
+ MIIGTjCCBTagAwIBAgIQBK55YGZmkBq5xX+mbFvczTANBgkqhkiG9w0BAQsFADBl
3
3
  MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
4
- d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
5
- QTAeFw0xMzAzMDgxMjAwMDBaFw0yMzAzMDgxMjAwMDBaME0xCzAJBgNVBAYTAlVT
6
- MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxJzAlBgNVBAMTHkRpZ2lDZXJ0IFNIQTIg
7
- U2VjdXJlIFNlcnZlciBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
8
- ANyuWJBNwcQwFZA1W248ghX1LFy949v/cUP6ZCWA1O4Yok3wZtAKc24RmDYXZK83
9
- nf36QYSvx6+M/hpzTc8zl5CilodTgyu5pnVILR1WN3vaMTIa16yrBvSqXUu3R0bd
10
- KpPDkC55gIDvEwRqFDu1m5K+wgdlTvza/P96rtxcflUxDOg5B6TXvi/TC2rSsd9f
11
- /ld0Uzs1gN2ujkSYs58O09rg1/RrKatEp0tYhG2SS4HD2nOLEpdIkARFdRrdNzGX
12
- kujNVA075ME/OV4uuPNcfhCOhkEAjUVmR7ChZc6gqikJTvOX6+guqw9ypzAO+sf0
13
- /RR3w6RbKFfCs/mC/bdFWJsCAwEAAaOCAVowggFWMBIGA1UdEwEB/wQIMAYBAf8C
14
- AQAwDgYDVR0PAQH/BAQDAgGGMDQGCCsGAQUFBwEBBCgwJjAkBggrBgEFBQcwAYYY
15
- aHR0cDovL29jc3AuZGlnaWNlcnQuY29tMHsGA1UdHwR0MHIwN6A1oDOGMWh0dHA6
16
- Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RDQS5jcmwwN6A1
17
- oDOGMWh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RD
18
- QS5jcmwwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8v
19
- d3d3LmRpZ2ljZXJ0LmNvbS9DUFMwHQYDVR0OBBYEFA+AYRyCMWHVLyjnjUY4tCzh
20
- xtniMB8GA1UdIwQYMBaAFAPeUDVW0Uy7ZvCj4hsbw5eyPdFVMA0GCSqGSIb3DQEB
21
- CwUAA4IBAQAjPt9L0jFCpbZ+QlwaRMxp0Wi0XUvgBCFsS+JtzLHgl4+mUwnNqipl
22
- 5TlPHoOlblyYoiQm5vuh7ZPHLgLGTUq/sELfeNqzqPlt/yGFUzZgTHbO7Djc1lGA
23
- 8MXW5dRNJ2Srm8c+cftIl7gzbckTB+6WohsYFfZcTEDts8Ls/3HB40f/1LkAtDdC
24
- 2iDJ6m6K7hQGrn2iWZiIqBtvLfTyyRRfJs8sjX7tN8Cp1Tm5gr8ZDOo0rwAhaPit
25
- c+LJMto4JQtV05od8GiG7S5BNO98pVAdvzr508EIDObtHopYJeS4d60tbvVS3bR0
26
- j6tJLp07kzQoH3jOlOrHvdPJbRzeXDLz
27
- -----END CERTIFICATE-----
28
- -----BEGIN CERTIFICATE-----
29
- MIIFDTCCA/WgAwIBAgIQBZ8R1sZP2Lbc8x554UUQ2DANBgkqhkiG9w0BAQsFADBN
30
- MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMScwJQYDVQQDEx5E
31
- aWdpQ2VydCBTSEEyIFNlY3VyZSBTZXJ2ZXIgQ0EwHhcNMTQxMTEwMDAwMDAwWhcN
32
- MTcxMTE0MTIwMDAwWjBlMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv
33
- bjEQMA4GA1UEBxMHU2VhdHRsZTEbMBkGA1UEChMSQ2hlZiBTb2Z0d2FyZSwgSW5j
34
- MRIwEAYDVQQDDAkqLmNoZWYuaW8wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
35
- AoIBAQC3xCIczkV10O5jTDpbd4YlPLC6kfnVoOkno2N/OOlcLQu3ulj/Lj1j4r6e
36
- 2XthJLcFgTO+y+1/IKnnpLKDfkx1YngWEBXEBP+MrrpDUKKs053s45/bI9QBPISA
37
- tXgnYxMH9Glo6FWWd13TUq++OKGw1p1wazH64XK4MAf5y/lkmWXIWumNuO35ZqtB
38
- ME3wJISwVHzHB2CQjlDklt+Mb0APEiIFIZflgu9JNBYzLdvUtxiz15FUZQI7SsYL
39
- TfXOD1KBNMWqN8snG2e5gRAzB2D161DFvAZt8OiYUe+3QurNlTYVzeHv1ok6UqgM
40
- ZcLzg8m801rRip0D7FCGvMCU/ktdAgMBAAGjggHPMIIByzAfBgNVHSMEGDAWgBQP
41
- gGEcgjFh1S8o541GOLQs4cbZ4jAdBgNVHQ4EFgQUwldjw4Pb4HV+wxGZ7MSSRh+d
42
- pm4wHQYDVR0RBBYwFIIJKi5jaGVmLmlvggdjaGVmLmlvMA4GA1UdDwEB/wQEAwIF
43
- oDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwawYDVR0fBGQwYjAvoC2g
44
- K4YpaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NzY2Etc2hhMi1nMy5jcmwwL6At
45
- oCuGKWh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9zc2NhLXNoYTItZzMuY3JsMEIG
46
- A1UdIAQ7MDkwNwYJYIZIAYb9bAEBMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3
47
- LmRpZ2ljZXJ0LmNvbS9DUFMwfAYIKwYBBQUHAQEEcDBuMCQGCCsGAQUFBzABhhho
48
- dHRwOi8vb2NzcC5kaWdpY2VydC5jb20wRgYIKwYBBQUHMAKGOmh0dHA6Ly9jYWNl
49
- cnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJTZWN1cmVTZXJ2ZXJDQS5jcnQw
50
- DAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAQEAvcTWenNuvvrhX2omm8LQ
51
- zWOuu8jqpoflACwD4lOSZ4TgOe4pQGCjXq8aRBD5k+goqQrPVf9lHnelUHFQac0Q
52
- 5WT4YUmisUbF0S4uY5OGQymM52MvUWG4ODL4gaWhFvN+HAXrDPP/9iitsjV0QOnl
53
- CDq7Q4/XYRYW3opu5nLLbfW6v4QvF5yzZagEACGs7Vt32p6l391UcU8f6wiB3uMD
54
- eioCvjpv/+2YOUNlDPCM3uBubjUhHOwO817wBxXkzdk1OSRe4jzcw/uX6wL7birt
55
- fbaSkpilvVX529pSzB2Lvi9xWOoGMM578dpQ0h3PwhmmvKhhCWP+pI05k3oSkYCP
56
- ng==
4
+ d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv
5
+ b3QgQ0EwHhcNMTMxMTA1MTIwMDAwWhcNMjgxMTA1MTIwMDAwWjBlMQswCQYDVQQG
6
+ EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl
7
+ cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBTSEEyIEFzc3VyZWQgSUQgQ0EwggEi
8
+ MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDc+BEjP2q178AneRstBYeiEEMx
9
+ 3w7UFRtPd6Qizj6McPC+B47dJyq8AR22LArK3WlYH0HtagUf2mN4WR4iLCv4un7J
10
+ NTtW8R98Qn4lsCMZxkU41z1E+SB8YK4csFoYBL6PO/ep8JSapgxjSbZBF1NAMr1P
11
+ 5lB6UB8lRejxia/N/17/UPPwFxH/vcWJ9b1iudj7jkUEhW2ZzcVITf0mqwI2Reo2
12
+ 119q4hqCQQrc6dn1kReOxiGtODwT5h5/ZpzVTdlG2vbPUqd9OyTDtMFRNcab69Tv
13
+ fuR7A+FEvXoLN+BPy4KKDXEY5KbgiSwb87JzPMGwkp4Yfb2rfcV9CKEswp9zAgMB
14
+ AAGjggL4MIIC9DASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjA0
15
+ BggrBgEFBQcBAQQoMCYwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0
16
+ LmNvbTCBgQYDVR0fBHoweDA6oDigNoY0aHR0cDovL2NybDQuZGlnaWNlcnQuY29t
17
+ L0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNybDA6oDigNoY0aHR0cDovL2NybDMu
18
+ ZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNybDAdBgNVHSUE
19
+ FjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwggGzBgNVHSAEggGqMIIBpjCCAaIGCmCG
20
+ SAGG/WwAAgQwggGSMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5j
21
+ b20vQ1BTMIIBZAYIKwYBBQUHAgIwggFWHoIBUgBBAG4AeQAgAHUAcwBlACAAbwBm
22
+ ACAAdABoAGkAcwAgAEMAZQByAHQAaQBmAGkAYwBhAHQAZQAgAGMAbwBuAHMAdABp
23
+ AHQAdQB0AGUAcwAgAGEAYwBjAGUAcAB0AGEAbgBjAGUAIABvAGYAIAB0AGgAZQAg
24
+ AEQAaQBnAGkAQwBlAHIAdAAgAEMAUAAvAEMAUABTACAAYQBuAGQAIAB0AGgAZQAg
25
+ AFIAZQBsAHkAaQBuAGcAIABQAGEAcgB0AHkAIABBAGcAcgBlAGUAbQBlAG4AdAAg
26
+ AHcAaABpAGMAaAAgAGwAaQBtAGkAdAAgAGwAaQBhAGIAaQBsAGkAdAB5ACAAYQBu
27
+ AGQAIABhAHIAZQAgAGkAbgBjAG8AcgBwAG8AcgBhAHQAZQBkACAAaABlAHIAZQBp
28
+ AG4AIABiAHkAIAByAGUAZgBlAHIAZQBuAGMAZQAuMB0GA1UdDgQWBBTnAiOAAE/Y
29
+ 17yUC9k/dDlJMjyKeTAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzAN
30
+ BgkqhkiG9w0BAQsFAAOCAQEATtSJJ7n9HYd3fg8oBZDxCi/JOz69k5yQxq/6kVGH
31
+ MlRr6MrBcVFcmY61+uBiGZmmB5p8Eyfb5QKihBLZFfYKRFfENI9tcx861qABPd7j
32
+ guRFa7LrJf2AXh05kL5bQvbOkWDj+aBWDEgQzjNoe82Tq/Bqy09YD7l7XRsEgZ6n
33
+ IuJXSSfukpMIvmkIUwI6Ll3IGfRQgE4C2bBdkbSTh/mWloFVQI5m7YLYuyhf7Uxh
34
+ 7QZYKBlTEUS8RyApsgRs2IlUmTt122d4LB6SeMZVPVgSETJuvUMMTTTbe8ZC2+y+
35
+ q5thTAaS447fISpQVwTAYKI11SSeZjcJSc/V+GWz4OJuwg==
57
36
  -----END CERTIFICATE-----
@@ -38,12 +38,12 @@ describe Chef::Resource::MacosUserDefaults, :macos_only do
38
38
  expect(resource.domain).to eq("NSGlobalDomain")
39
39
  end
40
40
 
41
- it "nil for the host property" do
42
- expect(resource.host).to be_nil
41
+ it ":all for the host property" do
42
+ expect(resource.host).to eq(:all)
43
43
  end
44
44
 
45
- it "nil for the user property" do
46
- expect(resource.user).to be_nil
45
+ it ":current for the user property" do
46
+ expect(resource.user).to eq(:current)
47
47
  end
48
48
 
49
49
  it ":write for resource action" do
@@ -35,14 +35,14 @@ describe "chef-client" do
35
35
  @server = @api = nil
36
36
  end
37
37
 
38
- def install_certificate_in_store(client_name)
38
+ def install_certificate_in_store(client_name, store_location)
39
39
  if ChefUtils.windows?
40
40
  powershell_exec! <<~EOH
41
41
  if (-not (($PSVersionTable.PSVersion.Major -ge 5) -and ($PSVersionTable.PSVersion.Build -ge 22000)) ) {
42
- New-SelfSignedCertificate -CertStoreLocation Cert:\\LocalMachine\\My -DnsName "#{client_name}"
42
+ New-SelfSignedCertificate -CertStoreLocation Cert:\\#{store_location}\\My -DnsName "#{client_name}"
43
43
  }
44
44
  else {
45
- New-SelfSignedCertificate -CertStoreLocation Cert:\\LocalMachine\\My -Subject "#{client_name}" -FriendlyName "#{client_name}" -KeyExportPolicy Exportable
45
+ New-SelfSignedCertificate -CertStoreLocation Cert:\\#{store_location}\\My -Subject "#{client_name}" -FriendlyName "#{client_name}" -KeyExportPolicy Exportable
46
46
  }
47
47
  EOH
48
48
  end
@@ -50,14 +50,6 @@ describe "chef-client" do
50
50
 
51
51
  def create_registry_key
52
52
  ::Chef::HTTP::Authenticator.get_cert_password
53
- # @win32registry = Chef::Win32::Registry.new
54
- # path = "HKEY_LOCAL_MACHINE\\Software\\Progress\\Authentication"
55
- # unless @win32registry.key_exists?(path)
56
- # @win32registry.create_key(path, true)
57
- # end
58
- # password = SOME_CHARS.sample(1 + rand(SOME_CHARS.count)).join[0...14]
59
- # values = { name: "PfxPass", type: :string, data: password }
60
- # @win32registry.set_value(path, values)
61
53
  end
62
54
 
63
55
  def remove_certificate_from_store
@@ -111,6 +103,9 @@ describe "chef-client" do
111
103
  tempfile.close
112
104
  @path = tempfile.path
113
105
  Chef::Config.validation_key = @path
106
+ if ChefUtils.windows?
107
+ create_registry_key
108
+ end
114
109
 
115
110
  file "config/client.rb", <<~EOM
116
111
  local_mode true
@@ -201,17 +196,27 @@ describe "chef-client" do
201
196
 
202
197
  if ChefUtils.windows?
203
198
  context "and the private key is in the Windows CertStore" do
204
- before do
205
- install_certificate_in_store(client_name)
199
+
200
+ it "should verify that the cert is loaded in the \\LocalMachine\\My store" do
201
+ Chef::Config[:auth_key_registry_type] = "machine"
202
+ install_certificate_in_store(client_name, "LocalMachine")
206
203
  create_registry_key
204
+ expect(Chef::HTTP::Authenticator.check_certstore_for_key(hostname)).to eq(true)
207
205
  end
208
206
 
209
- after do
207
+ it "should verify that the export password for the pfx is loaded in the Registry" do
208
+ expect(verify_export_password_exists.result).to eq(true)
209
+ end
210
+
211
+ it "should verify that a private key is returned to me" do
212
+ expect(Chef::HTTP::Authenticator.retrieve_certificate_key(client_name)).not_to be nil
210
213
  remove_certificate_from_store
211
- remove_registry_key
212
214
  end
213
215
 
214
- it "should verify that the cert is loaded in the LocalMachine\\My" do
216
+ it "should verify that the cert is loaded in the \\CurrentUser\\My store" do
217
+ Chef::Config[:auth_key_registry_type] = "user"
218
+ install_certificate_in_store(client_name, "CurrentUser")
219
+ create_registry_key
215
220
  expect(Chef::HTTP::Authenticator.check_certstore_for_key(hostname)).to eq(true)
216
221
  end
217
222
 
@@ -221,6 +226,7 @@ describe "chef-client" do
221
226
 
222
227
  it "should verify that a private key is returned to me" do
223
228
  expect(Chef::HTTP::Authenticator.retrieve_certificate_key(client_name)).not_to be nil
229
+ remove_certificate_from_store
224
230
  end
225
231
  end
226
232
  end
data/spec/spec_helper.rb CHANGED
@@ -138,9 +138,9 @@ RSpec.configure do |config|
138
138
 
139
139
  config.filter_run_excluding skip_buildkite: true if ENV["BUILDKITE"]
140
140
 
141
- config.filter_run_excluding fips_mode: !fips_mode_build? unless opensuse?
142
- # RubyDistros OpenSUSE docker images have a broken fips
143
- config.filter_run_excluding :fips_mode if opensuse?
141
+ config.filter_run_excluding fips_mode: !fips_mode_build?
142
+ # Skip fips on windows
143
+ # config.filter_run_excluding :fips_mode if windows?
144
144
 
145
145
  config.filter_run_excluding windows_only: true unless windows?
146
146
  config.filter_run_excluding not_supported_on_windows: true if windows?
@@ -310,25 +310,49 @@ describe Chef::Client, :windows_only do
310
310
  end
311
311
 
312
312
  context "when the client intially boots the first time" do
313
- it "verfies that a certificate was correctly created and exists in the Cert Store" do
313
+ it "verfies that a certificate was correctly created and exists in the LocalMachine Cert Store" do
314
+ Chef::Config[:node_name] = "test"
314
315
  new_pfx = my_client.generate_pfx_package(cert_name, end_date)
315
316
  my_client.import_pfx_to_store(new_pfx)
316
317
  expect(my_client.check_certstore_for_key(cert_name)).not_to be false
318
+ delete_certificate(cert_name)
317
319
  end
318
320
 
319
321
  it "correctly returns a new Publc Key" do
320
322
  new_pfx = my_client.generate_pfx_package(cert_name, end_date)
321
323
  cert_object = new_pfx.certificate.public_key.to_pem
322
324
  expect(cert_object.to_s).to match(/PUBLIC KEY/)
325
+ delete_certificate(cert_name)
326
+ end
327
+
328
+ end
329
+
330
+ context "when the client intially boots the first time and auth_key_registry_type is set to 'user' " do
331
+ it "verfies that a certificate was correctly created and exists in the CurrentUser Cert Store" do
332
+ Chef::Config[:node_name] = "test"
333
+ Chef::Config[:auth_key_registry_type] = "user"
334
+ new_pfx = my_client.generate_pfx_package(cert_name, end_date)
335
+ my_client.import_pfx_to_store(new_pfx)
336
+ expect(my_client.check_certstore_for_key(cert_name)).not_to be false
337
+ delete_certificate(cert_name)
338
+ end
339
+
340
+ it "correctly returns a new Publc Key" do
341
+ Chef::Config[:auth_key_registry_type] = "user"
342
+ new_pfx = my_client.generate_pfx_package(cert_name, end_date)
343
+ cert_object = new_pfx.certificate.public_key.to_pem
344
+ expect(cert_object.to_s).to match(/PUBLIC KEY/)
345
+ delete_certificate(cert_name)
323
346
  end
324
347
 
325
348
  end
326
349
 
327
350
  def delete_certificate(cert_name)
351
+ Chef::Config[:auth_key_registry_type] == "user" ? store = "CurrentUser" : store = "LocalMachine"
328
352
  require "chef/mixin/powershell_exec"
329
353
  extend Chef::Mixin::PowershellExec
330
354
  powershell_code = <<~CODE
331
- Get-ChildItem -path cert:\\LocalMachine\\My -Recurse -Force | Where-Object { $_.Subject -Match "#{cert_name}" } | Remove-item
355
+ Get-ChildItem -path cert:\\#{store}\\My -Recurse -Force | Where-Object { $_.Subject -Match "#{cert_name}" } | Remove-item
332
356
  CODE
333
357
  powershell_exec!(powershell_code)
334
358
  end
@@ -49,6 +49,14 @@ describe Chef::Compliance::Runner do
49
49
  expect(runner).not_to be_enabled
50
50
  end
51
51
 
52
+ it "is false if the node attributes have audit profiles and the audit cookbook is present, and the complince mode attribute is false" do
53
+ stub_const("::Reporter::ChefAutomate", true)
54
+ node.normal["audit"]["profiles"]["ssh"] = { 'compliance': "base/ssh" }
55
+ node.normal["audit"]["compliance_phase"] = false
56
+
57
+ expect(runner).not_to be_enabled
58
+ end
59
+
52
60
  it "is true if the node attributes have audit profiles and the audit cookbook is present, and the complince mode attribute is true" do
53
61
  stub_const("::Reporter::ChefAutomate", true)
54
62
  node.normal["audit"]["profiles"]["ssh"] = { 'compliance': "base/ssh" }