chef 18.9.4 → 18.11.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +16 -12
- data/README.md +0 -1
- data/Rakefile +21 -5
- data/chef-universal-mingw-ucrt.gemspec +4 -2
- data/chef.gemspec +17 -14
- data/lib/chef/application/apply.rb +1 -1
- data/lib/chef/application/base.rb +4 -4
- data/lib/chef/application/exit_code.rb +1 -1
- data/lib/chef/chef_fs/command_line.rb +4 -4
- data/lib/chef/chef_fs/file_system/chef_server/cookbook_dir.rb +1 -1
- data/lib/chef/chef_fs/file_system/chef_server/cookbooks_dir.rb +2 -3
- data/lib/chef/client.rb +2 -3
- data/lib/chef/compliance/fetcher/chef_server.rb +1 -1
- data/lib/chef/compliance/reporter/cli.rb +2 -2
- data/lib/chef/compliance/runner.rb +19 -1
- data/lib/chef/dsl/chef_vault.rb +1 -1
- data/lib/chef/dsl/rest_resource.rb +223 -16
- data/lib/chef/encrypted_data_bag_item/decryptor.rb +1 -5
- data/lib/chef/environment.rb +1 -1
- data/lib/chef/exceptions.rb +1 -1
- data/lib/chef/file_cache.rb +1 -5
- data/lib/chef/formatters/error_description.rb +8 -1
- data/lib/chef/formatters/error_inspectors/compile_error_inspector.rb +1 -1
- data/lib/chef/formatters/error_inspectors/cookbook_resolve_error_inspector.rb +1 -1
- data/lib/chef/formatters/error_inspectors/cookbook_sync_error_inspector.rb +1 -1
- data/lib/chef/group.rb +1 -1
- data/lib/chef/handler/slow_report.rb +1 -1
- data/lib/chef/http/authenticator.rb +25 -12
- data/lib/chef/mixin/api_version_request_handling.rb +1 -1
- data/lib/chef/mixin/powershell_type_coercions.rb +2 -2
- data/lib/chef/mixin/securable.rb +2 -2
- data/lib/chef/mixin/template.rb +25 -3
- data/lib/chef/mixin/versioned_api.rb +1 -1
- data/lib/chef/monkey_patches/net-http.rb +8 -8
- data/lib/chef/monkey_patches/reline-windows.rb +116 -0
- data/lib/chef/property.rb +1 -1
- data/lib/chef/provider/cron.rb +1 -1
- data/lib/chef/provider/directory.rb +11 -0
- data/lib/chef/provider/dsc_resource.rb +2 -2
- data/lib/chef/provider/file/content.rb +3 -2
- data/lib/chef/provider/file.rb +1 -1
- data/lib/chef/provider/git.rb +1 -1
- data/lib/chef/provider/ifconfig/debian.rb +1 -1
- data/lib/chef/provider/ifconfig/redhat.rb +1 -1
- data/lib/chef/provider/mount/linux.rb +1 -1
- data/lib/chef/provider/mount/windows.rb +4 -4
- data/lib/chef/provider/package/chocolatey.rb +78 -19
- data/lib/chef/provider/package/dnf/dnf_helper.py +355 -65
- data/lib/chef/provider/package/dnf/python_helper.rb +7 -4
- data/lib/chef/provider/package/dnf.rb +25 -6
- data/lib/chef/provider/package/homebrew.rb +3 -3
- data/lib/chef/provider/package/rubygems.rb +25 -2
- data/lib/chef/provider/package/snap.rb +1 -1
- data/lib/chef/provider/package/windows/exe.rb +1 -1
- data/lib/chef/provider/package/windows/msi.rb +1 -1
- data/lib/chef/provider/package/yum/rpm_utils.rb +2 -2
- data/lib/chef/provider/package/yum.rb +1 -1
- data/lib/chef/provider/powershell_script.rb +84 -84
- data/lib/chef/provider/service/debian.rb +2 -4
- data/lib/chef/provider/user/dscl.rb +1 -1
- data/lib/chef/provider/user/mac.rb +1 -1
- data/lib/chef/provider/windows_script.rb +1 -1
- data/lib/chef/resource/_rest_resource.rb +9 -7
- data/lib/chef/resource/alternatives.rb +41 -41
- data/lib/chef/resource/apt_package.rb +31 -31
- data/lib/chef/resource/apt_preference.rb +22 -22
- data/lib/chef/resource/apt_repository.rb +2 -2
- data/lib/chef/resource/archive_file.rb +52 -18
- data/lib/chef/resource/bash.rb +129 -129
- data/lib/chef/resource/bff_package.rb +15 -15
- data/lib/chef/resource/breakpoint.rb +44 -44
- data/lib/chef/resource/cab_package.rb +22 -22
- data/lib/chef/resource/chef_client_config.rb +251 -89
- data/lib/chef/resource/chef_client_cron.rb +18 -18
- data/lib/chef/resource/chef_client_launchd.rb +1 -1
- data/lib/chef/resource/chef_client_scheduled_task.rb +31 -31
- data/lib/chef/resource/chef_client_systemd_timer.rb +16 -16
- data/lib/chef/resource/chef_client_trusted_certificate.rb +28 -28
- data/lib/chef/resource/chef_handler.rb +107 -107
- data/lib/chef/resource/chef_vault_secret.rb +1 -1
- data/lib/chef/resource/chocolatey_config.rb +14 -14
- data/lib/chef/resource/chocolatey_feature.rb +1 -1
- data/lib/chef/resource/chocolatey_installer.rb +60 -42
- data/lib/chef/resource/chocolatey_package.rb +1 -1
- data/lib/chef/resource/chocolatey_source.rb +15 -15
- data/lib/chef/resource/cron/_cron_shared.rb +0 -2
- data/lib/chef/resource/cron/cron.rb +70 -70
- data/lib/chef/resource/csh.rb +5 -5
- data/lib/chef/resource/directory.rb +6 -6
- data/lib/chef/resource/dpkg_package.rb +3 -3
- data/lib/chef/resource/group.rb +28 -28
- data/lib/chef/resource/habitat/habitat_package.rb +80 -80
- data/lib/chef/resource/habitat/habitat_sup.rb +93 -95
- data/lib/chef/resource/habitat/habitat_sup_systemd.rb +10 -10
- data/lib/chef/resource/habitat/habitat_sup_windows.rb +3 -3
- data/lib/chef/resource/habitat_config.rb +13 -13
- data/lib/chef/resource/habitat_install.rb +17 -17
- data/lib/chef/resource/habitat_service.rb +1 -1
- data/lib/chef/resource/habitat_user_toml.rb +12 -12
- data/lib/chef/resource/helpers/cron_validations.rb +2 -2
- data/lib/chef/resource/homebrew_cask.rb +1 -1
- data/lib/chef/resource/homebrew_package.rb +20 -20
- data/lib/chef/resource/homebrew_tap.rb +1 -1
- data/lib/chef/resource/hostname.rb +2 -2
- data/lib/chef/resource/http_request.rb +2 -2
- data/lib/chef/resource/ifconfig.rb +34 -34
- data/lib/chef/resource/inspec_input.rb +37 -37
- data/lib/chef/resource/inspec_waiver.rb +63 -63
- data/lib/chef/resource/inspec_waiver_file_entry.rb +25 -25
- data/lib/chef/resource/ksh.rb +5 -5
- data/lib/chef/resource/launchd.rb +2 -2
- data/lib/chef/resource/link.rb +8 -8
- data/lib/chef/resource/locale.rb +6 -6
- data/lib/chef/resource/log.rb +4 -4
- data/lib/chef/resource/mdadm.rb +36 -36
- data/lib/chef/resource/mount.rb +3 -3
- data/lib/chef/resource/msu_package.rb +1 -1
- data/lib/chef/resource/ohai.rb +32 -32
- data/lib/chef/resource/ohai_hint.rb +24 -24
- data/lib/chef/resource/openssl_ec_private_key.rb +2 -2
- data/lib/chef/resource/openssl_ec_public_key.rb +2 -2
- data/lib/chef/resource/openssl_rsa_private_key.rb +1 -1
- data/lib/chef/resource/openssl_rsa_public_key.rb +2 -2
- data/lib/chef/resource/openssl_x509_certificate.rb +1 -1
- data/lib/chef/resource/openssl_x509_crl.rb +15 -15
- data/lib/chef/resource/openssl_x509_request.rb +2 -2
- data/lib/chef/resource/osx_profile.rb +54 -54
- data/lib/chef/resource/package.rb +6 -6
- data/lib/chef/resource/perl.rb +5 -5
- data/lib/chef/resource/plist.rb +4 -4
- data/lib/chef/resource/powershell_package_source.rb +12 -12
- data/lib/chef/resource/python.rb +4 -4
- data/lib/chef/resource/reboot.rb +5 -5
- data/lib/chef/resource/registry_key.rb +81 -81
- data/lib/chef/resource/remote_file.rb +72 -72
- data/lib/chef/resource/resource_notification.rb +4 -4
- data/lib/chef/resource/rhsm_errata_level.rb +1 -1
- data/lib/chef/resource/rhsm_register.rb +2 -2
- data/lib/chef/resource/scm/git.rb +79 -79
- data/lib/chef/resource/scm/subversion.rb +9 -9
- data/lib/chef/resource/script.rb +3 -3
- data/lib/chef/resource/selinux_boolean.rb +12 -12
- data/lib/chef/resource/selinux_fcontext.rb +21 -21
- data/lib/chef/resource/selinux_install.rb +18 -18
- data/lib/chef/resource/selinux_login.rb +11 -11
- data/lib/chef/resource/selinux_module.rb +16 -16
- data/lib/chef/resource/selinux_permissive.rb +9 -9
- data/lib/chef/resource/selinux_port.rb +16 -16
- data/lib/chef/resource/selinux_state.rb +28 -28
- data/lib/chef/resource/selinux_user.rb +14 -14
- data/lib/chef/resource/service.rb +5 -5
- data/lib/chef/resource/snap_package.rb +16 -16
- data/lib/chef/resource/ssh_known_hosts_entry.rb +10 -10
- data/lib/chef/resource/sudo.rb +68 -68
- data/lib/chef/resource/swap_file.rb +12 -12
- data/lib/chef/resource/sysctl.rb +42 -42
- data/lib/chef/resource/systemd_unit.rb +38 -38
- data/lib/chef/resource/timezone.rb +16 -16
- data/lib/chef/resource/user/mac_user.rb +3 -3
- data/lib/chef/resource/user.rb +6 -6
- data/lib/chef/resource/user_ulimit.rb +22 -22
- data/lib/chef/resource/windows_ad_join.rb +25 -25
- data/lib/chef/resource/windows_audit_policy.rb +34 -34
- data/lib/chef/resource/windows_auto_run.rb +8 -8
- data/lib/chef/resource/windows_certificate.rb +20 -20
- data/lib/chef/resource/windows_defender.rb +22 -22
- data/lib/chef/resource/windows_defender_exclusion.rb +17 -17
- data/lib/chef/resource/windows_env.rb +6 -6
- data/lib/chef/resource/windows_feature.rb +42 -42
- data/lib/chef/resource/windows_feature_dism.rb +8 -8
- data/lib/chef/resource/windows_feature_powershell.rb +20 -20
- data/lib/chef/resource/windows_firewall_profile.rb +28 -28
- data/lib/chef/resource/windows_firewall_rule.rb +47 -47
- data/lib/chef/resource/windows_font.rb +7 -7
- data/lib/chef/resource/windows_package.rb +59 -59
- data/lib/chef/resource/windows_pagefile.rb +29 -29
- data/lib/chef/resource/windows_path.rb +12 -12
- data/lib/chef/resource/windows_printer.rb +28 -28
- data/lib/chef/resource/windows_printer_port.rb +21 -21
- data/lib/chef/resource/windows_security_policy.rb +23 -23
- data/lib/chef/resource/windows_service.rb +108 -108
- data/lib/chef/resource/windows_share.rb +19 -19
- data/lib/chef/resource/windows_shortcut.rb +7 -7
- data/lib/chef/resource/windows_task.rb +105 -105
- data/lib/chef/resource/windows_uac.rb +14 -14
- data/lib/chef/resource/windows_update_settings.rb +27 -27
- data/lib/chef/resource/windows_user_privilege.rb +59 -59
- data/lib/chef/resource/windows_workgroup.rb +12 -12
- data/lib/chef/resource/yum_package.rb +1 -1
- data/lib/chef/resource/yum_repository.rb +36 -36
- data/lib/chef/resource.rb +1 -1
- data/lib/chef/resource_collection/resource_set.rb +2 -3
- data/lib/chef/resource_inspector.rb +1 -2
- data/lib/chef/run_context.rb +2 -2
- data/lib/chef/runner.rb +1 -1
- data/lib/chef/secret_fetcher/akeyless_vault.rb +0 -1
- data/lib/chef/secret_fetcher/hashi_vault.rb +0 -1
- data/lib/chef/shell/ext.rb +20 -20
- data/lib/chef/shell/shell_session.rb +1 -1
- data/lib/chef/shell.rb +7 -0
- data/lib/chef/version.rb +1 -1
- data/lib/chef/version_constraint.rb +1 -1
- data/lib/chef/win32/file/version_info.rb +1 -1
- metadata +63 -38
|
@@ -20,56 +20,263 @@ require "chef/constants" unless defined?(NOT_PASSED)
|
|
|
20
20
|
class Chef
|
|
21
21
|
module DSL
|
|
22
22
|
module RestResource
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def inherited_accessor(name)
|
|
26
|
+
superclass.public_send(name) if superclass.respond_to?(name)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
public
|
|
30
|
+
|
|
31
|
+
# Define property mapping between resource properties and JSON API fields
|
|
32
|
+
#
|
|
33
|
+
# Maps resource properties to their corresponding locations in the JSON
|
|
34
|
+
# API payload. Supports both simple 1:1 mappings and complex transformations.
|
|
35
|
+
#
|
|
36
|
+
# @param rest_property_map [Hash, Array, NOT_PASSED] The property mapping configuration
|
|
37
|
+
# - Hash: Keys are property symbols, values are JMESPath strings or symbol references
|
|
38
|
+
# - Array: Simple 1:1 mapping (property name matches JSON field name)
|
|
39
|
+
# - NOT_PASSED: Acts as getter, returns current mapping
|
|
40
|
+
#
|
|
41
|
+
# @return [Hash] The current property mapping
|
|
42
|
+
#
|
|
43
|
+
# @example Simple 1:1 mapping
|
|
44
|
+
# rest_property_map [:username, :email, :role]
|
|
45
|
+
# # Equivalent to: { username: 'username', email: 'email', role: 'role' }
|
|
46
|
+
#
|
|
47
|
+
# @example Nested JSON paths
|
|
48
|
+
# rest_property_map({
|
|
49
|
+
# username: 'user.name',
|
|
50
|
+
# email: 'user.contact.email',
|
|
51
|
+
# role: 'permissions.role'
|
|
52
|
+
# })
|
|
53
|
+
#
|
|
54
|
+
# @example Custom mapping functions
|
|
55
|
+
# rest_property_map({
|
|
56
|
+
# username: 'username',
|
|
57
|
+
# tags: :tags_mapping # Calls tags_from_json and tags_to_json methods
|
|
58
|
+
# })
|
|
59
|
+
#
|
|
60
|
+
# @see #json_to_property Method that uses this mapping to extract values
|
|
61
|
+
# @see #property_to_json Method that uses this mapping to create JSON
|
|
23
62
|
def rest_property_map(rest_property_map = NOT_PASSED)
|
|
24
|
-
|
|
63
|
+
unless rest_property_map.equal?(NOT_PASSED)
|
|
25
64
|
rest_property_map = rest_property_map.to_h { |k| [k.to_sym, k] } if rest_property_map.is_a? Array
|
|
26
65
|
|
|
27
66
|
@rest_property_map = rest_property_map
|
|
28
67
|
end
|
|
29
|
-
@rest_property_map
|
|
68
|
+
@rest_property_map || inherited_accessor(:rest_property_map)
|
|
30
69
|
end
|
|
31
70
|
|
|
32
|
-
#
|
|
71
|
+
# Define the REST API collection URL
|
|
72
|
+
#
|
|
73
|
+
# Sets the base URL for the collection of resources. This URL is used for:
|
|
74
|
+
# - GET requests to list all resources
|
|
75
|
+
# - POST requests to create new resources
|
|
76
|
+
#
|
|
77
|
+
# @param rest_api_collection [String, NOT_PASSED] The collection URL path
|
|
78
|
+
# - String: Must be an absolute path starting with '/'
|
|
79
|
+
# - NOT_PASSED: Acts as getter, returns current collection URL
|
|
80
|
+
#
|
|
81
|
+
# @return [String] The current collection URL
|
|
82
|
+
#
|
|
83
|
+
# @raise [ArgumentError] If the path doesn't start with '/'
|
|
84
|
+
#
|
|
85
|
+
# @example
|
|
86
|
+
# rest_api_collection '/api/v1/users'
|
|
87
|
+
# # GET /api/v1/users # List all users
|
|
88
|
+
# # POST /api/v1/users # Create new user
|
|
33
89
|
def rest_api_collection(rest_api_collection = NOT_PASSED)
|
|
34
|
-
|
|
90
|
+
unless rest_api_collection.equal?(NOT_PASSED)
|
|
35
91
|
raise ArgumentError, "You must pass an absolute path to rest_api_collection" unless rest_api_collection.start_with? "/"
|
|
36
92
|
|
|
37
93
|
@rest_api_collection = rest_api_collection
|
|
38
94
|
end
|
|
39
95
|
|
|
40
|
-
@rest_api_collection
|
|
96
|
+
@rest_api_collection || inherited_accessor(:rest_api_collection)
|
|
41
97
|
end
|
|
42
98
|
|
|
43
|
-
#
|
|
99
|
+
# Define the REST API document URL with RFC 6570 template support
|
|
100
|
+
#
|
|
101
|
+
# Sets the URL pattern for individual resource documents. The URL can include
|
|
102
|
+
# RFC 6570 URI templates that will be expanded using property values. This URL
|
|
103
|
+
# is used for:
|
|
104
|
+
# - GET requests to retrieve a specific resource
|
|
105
|
+
# - PATCH/PUT requests to update a resource
|
|
106
|
+
# - DELETE requests to remove a resource
|
|
107
|
+
#
|
|
108
|
+
# @param rest_api_document [String, NOT_PASSED] The document URL pattern
|
|
109
|
+
# - String: Must be an absolute path starting with '/'
|
|
110
|
+
# - Can include RFC 6570 templates like {property_name}
|
|
111
|
+
# - NOT_PASSED: Acts as getter, returns current document URL
|
|
112
|
+
#
|
|
113
|
+
# @param first_element_only [Boolean] If true and API returns array, extract first element only
|
|
114
|
+
#
|
|
115
|
+
# @return [String] The current document URL pattern
|
|
116
|
+
#
|
|
117
|
+
# @raise [ArgumentError] If the path doesn't start with '/'
|
|
118
|
+
#
|
|
119
|
+
# @example Path-based URL
|
|
120
|
+
# rest_api_document '/api/v1/users/{username}'
|
|
121
|
+
# # With username='john':
|
|
122
|
+
# # GET /api/v1/users/john
|
|
123
|
+
# # PATCH /api/v1/users/john
|
|
124
|
+
# # DELETE /api/v1/users/john
|
|
125
|
+
#
|
|
126
|
+
# @example Query-based URL
|
|
127
|
+
# rest_api_document '/api/v1/users?name={username}&email={email}'
|
|
128
|
+
# # With username='john', email='john@example.com':
|
|
129
|
+
# # GET /api/v1/users?name=john&email=john@example.com
|
|
130
|
+
#
|
|
131
|
+
# @example With first_element_only
|
|
132
|
+
# rest_api_document '/api/v1/users?name={username}', first_element_only: true
|
|
133
|
+
# # API returns: [{"name": "john", ...}]
|
|
134
|
+
# # Resource sees: {"name": "john", ...}
|
|
135
|
+
#
|
|
136
|
+
# @see https://tools.ietf.org/html/rfc6570 RFC 6570 URI Template specification
|
|
44
137
|
def rest_api_document(rest_api_document = NOT_PASSED, first_element_only: false)
|
|
45
|
-
|
|
138
|
+
unless rest_api_document.equal?(NOT_PASSED)
|
|
46
139
|
raise ArgumentError, "You must pass an absolute path to rest_api_document" unless rest_api_document.start_with? "/"
|
|
47
140
|
|
|
48
141
|
@rest_api_document = rest_api_document
|
|
49
142
|
@rest_api_document_first_element_only = first_element_only
|
|
50
143
|
end
|
|
51
|
-
@rest_api_document
|
|
144
|
+
@rest_api_document ||
|
|
145
|
+
inherited_accessor(:rest_api_document) ||
|
|
146
|
+
(rest_api_collection && rest_identity_property ? "#{rest_api_collection}/{#{rest_identity_property}}" : nil)
|
|
52
147
|
end
|
|
53
148
|
|
|
54
|
-
#
|
|
149
|
+
# Define explicit identity mapping for resource identification
|
|
150
|
+
#
|
|
151
|
+
# Explicitly specifies which JSON fields and resource properties uniquely
|
|
152
|
+
# identify a resource. Use this when automatic identity inference from the
|
|
153
|
+
# document URL is insufficient or when dealing with composite keys.
|
|
154
|
+
#
|
|
155
|
+
# If not specified, the identity is automatically inferred from RFC 6570
|
|
156
|
+
# templates in the document URL.
|
|
157
|
+
#
|
|
158
|
+
# @param rest_identity_map [Hash, NOT_PASSED] Mapping of JSON paths to properties
|
|
159
|
+
# - Hash: Keys are JMESPath-like strings, values are property symbols
|
|
160
|
+
# - NOT_PASSED: Acts as getter, returns current identity mapping
|
|
161
|
+
#
|
|
162
|
+
# @return [Hash, nil] The current identity mapping or nil if using auto-inference
|
|
163
|
+
#
|
|
164
|
+
# @example Simple identity
|
|
165
|
+
# property :username, String, identity: true
|
|
166
|
+
# rest_identity_map({ 'username' => :username })
|
|
167
|
+
#
|
|
168
|
+
# @example Composite identity
|
|
169
|
+
# property :name, String
|
|
170
|
+
# property :namespace, String
|
|
171
|
+
#
|
|
172
|
+
# rest_identity_map({
|
|
173
|
+
# 'name' => :name,
|
|
174
|
+
# 'namespace' => :namespace
|
|
175
|
+
# })
|
|
176
|
+
#
|
|
177
|
+
# @example Nested identity fields
|
|
178
|
+
# property :user_id, String
|
|
179
|
+
# property :org_id, String
|
|
180
|
+
#
|
|
181
|
+
# rest_identity_map({
|
|
182
|
+
# 'user.id' => :user_id,
|
|
183
|
+
# 'organization.id' => :org_id
|
|
184
|
+
# })
|
|
55
185
|
def rest_identity_map(rest_identity_map = NOT_PASSED)
|
|
56
|
-
@rest_identity_map = rest_identity_map
|
|
57
|
-
@rest_identity_map
|
|
186
|
+
@rest_identity_map = rest_identity_map unless rest_identity_map.equal?(NOT_PASSED)
|
|
187
|
+
@rest_identity_map || inherited_accessor(:rest_identity_map)
|
|
58
188
|
end
|
|
59
189
|
|
|
60
|
-
#
|
|
190
|
+
# Declare properties that should only be sent during resource creation
|
|
191
|
+
#
|
|
192
|
+
# Specifies which properties should only be included in POST (create) requests
|
|
193
|
+
# and excluded from PATCH/PUT (update) requests. This is useful for properties
|
|
194
|
+
# that can only be set during initial creation or would cause errors if
|
|
195
|
+
# included in updates.
|
|
196
|
+
#
|
|
197
|
+
# @param rest_post_only_properties [Symbol, Array<Symbol>, NOT_PASSED] Properties to mark
|
|
198
|
+
# - Symbol: Single property name
|
|
199
|
+
# - Array<Symbol>: Multiple property names
|
|
200
|
+
# - NOT_PASSED: Acts as getter, returns current post-only properties
|
|
201
|
+
#
|
|
202
|
+
# @return [Array<Symbol>] Current list of post-only properties (empty array if none)
|
|
203
|
+
#
|
|
204
|
+
# @example Single property
|
|
205
|
+
# property :password, String, sensitive: true
|
|
206
|
+
# property :username, String
|
|
207
|
+
#
|
|
208
|
+
# rest_post_only_properties :password
|
|
209
|
+
# # Password only sent when creating user, not when updating
|
|
210
|
+
#
|
|
211
|
+
# @example Multiple properties
|
|
212
|
+
# property :password, String, sensitive: true
|
|
213
|
+
# property :initial_role, String
|
|
214
|
+
# property :username, String
|
|
215
|
+
#
|
|
216
|
+
# rest_post_only_properties [:password, :initial_role]
|
|
217
|
+
#
|
|
218
|
+
# @example Common use cases
|
|
219
|
+
# # Passwords that can't be updated via API
|
|
220
|
+
# rest_post_only_properties :admin_password
|
|
221
|
+
#
|
|
222
|
+
# # Resource size that can't be changed after creation
|
|
223
|
+
# rest_post_only_properties :disk_size_gb
|
|
224
|
+
#
|
|
225
|
+
# # Initialization parameters
|
|
226
|
+
# rest_post_only_properties [:template_id, :source_snapshot]
|
|
61
227
|
def rest_post_only_properties(rest_post_only_properties = NOT_PASSED)
|
|
62
|
-
|
|
228
|
+
unless rest_post_only_properties.equal?(NOT_PASSED)
|
|
63
229
|
@rest_post_only_properties = Array(rest_post_only_properties).map(&:to_sym)
|
|
64
230
|
end
|
|
65
|
-
@rest_post_only_properties || []
|
|
231
|
+
@rest_post_only_properties || inherited_accessor(:rest_post_only_properties) || []
|
|
66
232
|
end
|
|
67
233
|
|
|
68
234
|
def rest_api_document_first_element_only(rest_api_document_first_element_only = NOT_PASSED)
|
|
69
|
-
|
|
235
|
+
unless rest_api_document_first_element_only.equal?(NOT_PASSED)
|
|
70
236
|
@rest_api_document_first_element_only = rest_api_document_first_element_only
|
|
71
237
|
end
|
|
72
|
-
@rest_api_document_first_element_only
|
|
238
|
+
@rest_api_document_first_element_only || inherited_accessor(:rest_api_document_first_element_only)
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
# Define the base URL for the REST API
|
|
242
|
+
#
|
|
243
|
+
# Sets the base endpoint URL that is prepended to all collection and document
|
|
244
|
+
# URLs. This allows resource definitions to be self-contained without requiring
|
|
245
|
+
# the Train transport endpoint to be pre-configured.
|
|
246
|
+
#
|
|
247
|
+
# @param rest_api_endpoint [String, NOT_PASSED] The base URL of the REST API
|
|
248
|
+
# - NOT_PASSED: Acts as getter, returns current endpoint URL
|
|
249
|
+
#
|
|
250
|
+
# @return [String, nil] The current endpoint URL
|
|
251
|
+
#
|
|
252
|
+
# @example
|
|
253
|
+
# rest_api_endpoint "https://api.example.com"
|
|
254
|
+
# rest_api_collection "/api/v1/users"
|
|
255
|
+
# # GET https://api.example.com/api/v1/users
|
|
256
|
+
def rest_api_endpoint(rest_api_endpoint = NOT_PASSED)
|
|
257
|
+
@rest_api_endpoint = rest_api_endpoint unless rest_api_endpoint.equal?(NOT_PASSED)
|
|
258
|
+
@rest_api_endpoint || inherited_accessor(:rest_api_endpoint)
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
# Declare the property that uniquely identifies a resource in the REST API
|
|
262
|
+
#
|
|
263
|
+
# Sets the identity property for the resource and auto-generates the document
|
|
264
|
+
# URL as "#{rest_api_collection}/{property}" when no explicit rest_api_document
|
|
265
|
+
# is provided. This is a convenience alternative to setting rest_api_document
|
|
266
|
+
# manually.
|
|
267
|
+
#
|
|
268
|
+
# @param property [Symbol, NOT_PASSED] The property name used as the resource identifier
|
|
269
|
+
# - NOT_PASSED: Acts as getter, returns current identity property
|
|
270
|
+
#
|
|
271
|
+
# @return [Symbol, nil] The current identity property name
|
|
272
|
+
#
|
|
273
|
+
# @example
|
|
274
|
+
# rest_api_collection "/api/v1/users"
|
|
275
|
+
# rest_identity_property :username
|
|
276
|
+
# # Auto-generates rest_api_document as "/api/v1/users/{username}"
|
|
277
|
+
def rest_identity_property(property = NOT_PASSED)
|
|
278
|
+
@rest_identity_property = property unless property.equal?(NOT_PASSED)
|
|
279
|
+
@rest_identity_property || inherited_accessor(:rest_identity_property)
|
|
73
280
|
end
|
|
74
281
|
|
|
75
282
|
end
|
|
@@ -177,11 +177,7 @@ class Chef::EncryptedDataBagItem
|
|
|
177
177
|
digest = OpenSSL::Digest.new("sha256")
|
|
178
178
|
raw_hmac = OpenSSL::HMAC.digest(digest, key, @encrypted_data["encrypted_data"])
|
|
179
179
|
|
|
180
|
-
|
|
181
|
-
true
|
|
182
|
-
else
|
|
183
|
-
raise DecryptionFailure, "Error decrypting data bag value: invalid hmac. Most likely the provided key is incorrect"
|
|
184
|
-
end
|
|
180
|
+
candidate_hmac_matches?(raw_hmac) || raise(DecryptionFailure, "Error decrypting data bag value: invalid hmac. Most likely the provided key is incorrect")
|
|
185
181
|
end
|
|
186
182
|
|
|
187
183
|
private
|
data/lib/chef/environment.rb
CHANGED
|
@@ -35,7 +35,7 @@ class Chef
|
|
|
35
35
|
include Chef::Mixin::ParamsValidate
|
|
36
36
|
include Chef::Mixin::FromFile
|
|
37
37
|
|
|
38
|
-
COMBINED_COOKBOOK_CONSTRAINT = /(.+)(?:\s+)((?:#{Chef::VersionConstraint::OPS.join(
|
|
38
|
+
COMBINED_COOKBOOK_CONSTRAINT = /(.+)(?:\s+)((?:#{Chef::VersionConstraint::OPS.join("|")})(?:\s+).+)$/.freeze
|
|
39
39
|
|
|
40
40
|
def initialize(chef_server_rest: nil)
|
|
41
41
|
@name = ""
|
data/lib/chef/exceptions.rb
CHANGED
|
@@ -532,7 +532,7 @@ class Chef
|
|
|
532
532
|
@resources_found = resources_found
|
|
533
533
|
matches_info = @resources_found.each do |r|
|
|
534
534
|
if r["Module"].nil?
|
|
535
|
-
"Resource #{r["Name"]} was found in #{r["Module"]["Name"]}"
|
|
535
|
+
"Resource #{r["Name"]} was found in #{r["Module"]["Name"]}" # rubocop:disable Lint/Void
|
|
536
536
|
else
|
|
537
537
|
"Resource #{r["Name"]} is a binary resource"
|
|
538
538
|
end
|
data/lib/chef/file_cache.rb
CHANGED
|
@@ -59,10 +59,17 @@ class Chef
|
|
|
59
59
|
|
|
60
60
|
private
|
|
61
61
|
|
|
62
|
+
MAX_DISPLAY_TEXT_LENGTH = 10_000
|
|
63
|
+
|
|
62
64
|
def display_section(heading, text, out)
|
|
63
65
|
out.puts heading
|
|
64
66
|
out.puts "-" * heading.size
|
|
65
|
-
|
|
67
|
+
if text.is_a?(String) && text.length > MAX_DISPLAY_TEXT_LENGTH
|
|
68
|
+
out.puts text[0, MAX_DISPLAY_TEXT_LENGTH]
|
|
69
|
+
out.puts "\n... [truncated #{text.length - MAX_DISPLAY_TEXT_LENGTH} characters of output]"
|
|
70
|
+
else
|
|
71
|
+
out.puts text
|
|
72
|
+
end
|
|
66
73
|
out.puts "\n"
|
|
67
74
|
end
|
|
68
75
|
|
|
@@ -126,7 +126,7 @@ class Chef
|
|
|
126
126
|
end
|
|
127
127
|
|
|
128
128
|
def filtered_bt
|
|
129
|
-
backtrace_lines_in_cookbooks.
|
|
129
|
+
backtrace_lines_in_cookbooks.any? ? backtrace_lines_in_cookbooks : exception.backtrace
|
|
130
130
|
end
|
|
131
131
|
|
|
132
132
|
def found_error_in_cookbooks?
|
|
@@ -69,7 +69,7 @@ class Chef
|
|
|
69
69
|
describe_412_error(error_description)
|
|
70
70
|
when Net::HTTPBadRequest
|
|
71
71
|
describe_400_error(error_description)
|
|
72
|
-
when Net::HTTPNotFound
|
|
72
|
+
when Net::HTTPNotFound # rubocop:disable Lint/EmptyWhen
|
|
73
73
|
when Net::HTTPInternalServerError
|
|
74
74
|
describe_500_error(error_description)
|
|
75
75
|
when Net::HTTPBadGateway, Net::HTTPServiceUnavailable
|
|
@@ -64,7 +64,7 @@ class Chef
|
|
|
64
64
|
describe_401_error(error_description)
|
|
65
65
|
when Net::HTTPBadRequest
|
|
66
66
|
describe_400_error(error_description)
|
|
67
|
-
when Net::HTTPNotFound
|
|
67
|
+
when Net::HTTPNotFound # rubocop:disable Lint/EmptyWhen
|
|
68
68
|
when Net::HTTPInternalServerError
|
|
69
69
|
describe_500_error(error_description)
|
|
70
70
|
when Net::HTTPBadGateway, Net::HTTPServiceUnavailable, Net::HTTPGatewayTimeOut
|
data/lib/chef/group.rb
CHANGED
|
@@ -150,8 +150,9 @@ class Chef
|
|
|
150
150
|
|
|
151
151
|
if !!results
|
|
152
152
|
@raw_key = results
|
|
153
|
-
elsif key_file
|
|
153
|
+
elsif key_file.nil? && raw_key.nil?
|
|
154
154
|
puts "\nNo key detected\n"
|
|
155
|
+
return
|
|
155
156
|
elsif !!key_file
|
|
156
157
|
@raw_key = IO.read(key_file).strip
|
|
157
158
|
elsif !!raw_key
|
|
@@ -305,14 +306,26 @@ class Chef
|
|
|
305
306
|
|
|
306
307
|
if !!check_certstore_for_key(client_name)
|
|
307
308
|
ps_blob = powershell_exec!(get_the_key_ps(client_name, password)).result
|
|
309
|
+
# ps_blob can be false when the PowerShell Catch block fires (e.g. cert export
|
|
310
|
+
# race condition or temporary store lock). Guard before calling Hash#[] to
|
|
311
|
+
# avoid NoMethodError: undefined method `[]' for false:FalseClass.
|
|
312
|
+
return false unless ps_blob.is_a?(Hash) && ps_blob["PSPath"]
|
|
313
|
+
|
|
308
314
|
file_path = ps_blob["PSPath"].split("::")[1]
|
|
309
|
-
|
|
315
|
+
|
|
316
|
+
# Use begin/ensure to guarantee the unique temp file is deleted even if
|
|
317
|
+
# File.binread or OpenSSL::PKCS12.new raises an exception, preventing
|
|
318
|
+
# orphaned PFX files on disk.
|
|
319
|
+
begin
|
|
320
|
+
pkcs = OpenSSL::PKCS12.new(File.binread(file_path), password)
|
|
321
|
+
ensure
|
|
322
|
+
File.delete(file_path) if File.exist?(file_path)
|
|
323
|
+
end
|
|
310
324
|
|
|
311
325
|
# We check the pfx we just extracted the private key from
|
|
312
326
|
# if that cert is expiring in 7 days or less we generate a new pfx/p12 object
|
|
313
327
|
# then we post the new public key from that to the client endpoint on
|
|
314
328
|
# chef server.
|
|
315
|
-
File.delete(file_path)
|
|
316
329
|
key_expiring = is_certificate_expiring?(pkcs)
|
|
317
330
|
if key_expiring
|
|
318
331
|
powershell_exec!(delete_old_key_ps(client_name))
|
|
@@ -335,15 +348,15 @@ class Chef
|
|
|
335
348
|
def self.get_the_key_ps(client_name, password)
|
|
336
349
|
store = get_cert_user
|
|
337
350
|
powershell_code = <<~CODE
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
351
|
+
Try {
|
|
352
|
+
$my_pwd = ConvertTo-SecureString -String "#{password}" -Force -AsPlainText;
|
|
353
|
+
$cert = Get-ChildItem -path cert:\\#{store}\\My -Recurse | Where-Object { $_.Subject -match "chef-#{client_name}$" } -ErrorAction Stop;
|
|
354
|
+
$tempfile = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), [System.IO.Path]::GetRandomFileName() + ".pfx");
|
|
355
|
+
Export-PfxCertificate -Cert $cert -Password $my_pwd -FilePath $tempfile;
|
|
356
|
+
}
|
|
357
|
+
Catch {
|
|
358
|
+
return $false
|
|
359
|
+
}
|
|
347
360
|
CODE
|
|
348
361
|
end
|
|
349
362
|
|
|
@@ -42,7 +42,7 @@ class Chef
|
|
|
42
42
|
max_server_version = Integer(header["max_version"])
|
|
43
43
|
|
|
44
44
|
supported_client_versions.each do |version|
|
|
45
|
-
if version
|
|
45
|
+
if version.between?(min_server_version, max_server_version)
|
|
46
46
|
server_supported_client_versions.push(version)
|
|
47
47
|
end
|
|
48
48
|
end
|
|
@@ -72,8 +72,8 @@ class Chef
|
|
|
72
72
|
# do we need to worry about binary data?
|
|
73
73
|
if unsafe?(s)
|
|
74
74
|
encoded_str = Base64.strict_encode64(s.encode("UTF-8"))
|
|
75
|
-
"([System.Text.Encoding]::UTF8.GetString("\
|
|
76
|
-
"[System.Convert]::FromBase64String('#{encoded_str}')"\
|
|
75
|
+
"([System.Text.Encoding]::UTF8.GetString(" \
|
|
76
|
+
"[System.Convert]::FromBase64String('#{encoded_str}')" \
|
|
77
77
|
"))"
|
|
78
78
|
else
|
|
79
79
|
"'#{s}'"
|
data/lib/chef/mixin/securable.rb
CHANGED
|
@@ -50,9 +50,9 @@ class Chef
|
|
|
50
50
|
|
|
51
51
|
# Windows does not support the sticky or setuid bits
|
|
52
52
|
if ChefUtils.windows?
|
|
53
|
-
Integer(m)
|
|
53
|
+
Integer(m).between?(0, 0777)
|
|
54
54
|
else
|
|
55
|
-
Integer(m)
|
|
55
|
+
Integer(m).between?(0, 07777)
|
|
56
56
|
end
|
|
57
57
|
end,
|
|
58
58
|
}
|
data/lib/chef/mixin/template.rb
CHANGED
|
@@ -93,6 +93,12 @@ class Chef
|
|
|
93
93
|
@_extension_modules = []
|
|
94
94
|
end
|
|
95
95
|
|
|
96
|
+
# Provide a compact inspect so exception messages do not dump the full
|
|
97
|
+
# template context, including node attributes and secrets.
|
|
98
|
+
def inspect
|
|
99
|
+
"#<#{self.class} template_name=#{@template_name.inspect} cookbook_name=#{@cookbook_name.inspect}>"
|
|
100
|
+
end
|
|
101
|
+
|
|
96
102
|
###
|
|
97
103
|
# USER FACING API
|
|
98
104
|
###
|
|
@@ -220,8 +226,15 @@ class Chef
|
|
|
220
226
|
@original_exception, @template, @context, @options = original_exception, template, context, options
|
|
221
227
|
end
|
|
222
228
|
|
|
229
|
+
MAX_MESSAGE_LENGTH = 10_000
|
|
230
|
+
|
|
223
231
|
def message
|
|
224
|
-
@original_exception.message
|
|
232
|
+
msg = @original_exception.message
|
|
233
|
+
if msg.length > MAX_MESSAGE_LENGTH
|
|
234
|
+
msg[0, MAX_MESSAGE_LENGTH] + "\n... [truncated #{msg.length - MAX_MESSAGE_LENGTH} characters]"
|
|
235
|
+
else
|
|
236
|
+
msg
|
|
237
|
+
end
|
|
225
238
|
end
|
|
226
239
|
|
|
227
240
|
def line_number
|
|
@@ -238,7 +251,7 @@ class Chef
|
|
|
238
251
|
|
|
239
252
|
def source_listing
|
|
240
253
|
@source_listing ||= begin
|
|
241
|
-
lines = @template.split(
|
|
254
|
+
lines = @template.split("\n")
|
|
242
255
|
if line_number
|
|
243
256
|
line_index = line_number - 1
|
|
244
257
|
beginning_line = line_index <= SOURCE_CONTEXT_WINDOW ? 0 : line_index - SOURCE_CONTEXT_WINDOW
|
|
@@ -258,7 +271,16 @@ class Chef
|
|
|
258
271
|
end
|
|
259
272
|
|
|
260
273
|
def to_s
|
|
261
|
-
|
|
274
|
+
location_parts = []
|
|
275
|
+
if @context.respond_to?(:cookbook_name) && @context.cookbook_name
|
|
276
|
+
location_parts << "cookbook: #{@context.cookbook_name}"
|
|
277
|
+
end
|
|
278
|
+
if @context.respond_to?(:template_name) && @context.template_name
|
|
279
|
+
location_parts << "template: #{@context.template_name}"
|
|
280
|
+
end
|
|
281
|
+
location_hint = location_parts.empty? ? "" : " (#{location_parts.join(", ")})"
|
|
282
|
+
|
|
283
|
+
"\n\n#{self.class} (#{message}) #{source_location}#{location_hint}:\n\n" +
|
|
262
284
|
"#{source_listing}\n\n #{original_exception.backtrace.join("\n ")}\n\n"
|
|
263
285
|
end
|
|
264
286
|
end
|
|
@@ -48,7 +48,7 @@ class Chef
|
|
|
48
48
|
version = klass.send(:minimum_api_version)
|
|
49
49
|
# min and max versions will be nil if we've not made a request to the server yet,
|
|
50
50
|
# in which case we'll just start with the highest version and see what happens
|
|
51
|
-
ServerAPIVersions.instance.min_server_version.nil? || (version
|
|
51
|
+
ServerAPIVersions.instance.min_server_version.nil? || (version.between?(ServerAPIVersions.instance.min_server_version, ServerAPIVersions.instance.send(type)))
|
|
52
52
|
end
|
|
53
53
|
.max_by { |a| a.send(:minimum_api_version) }
|
|
54
54
|
end
|
|
@@ -37,9 +37,9 @@ if RUBY_VERSION.split(".")[0..1].join(".") == "3.1"
|
|
|
37
37
|
if use_ssl?
|
|
38
38
|
if proxy?
|
|
39
39
|
plain_sock = BufferedIO.new(s, read_timeout: @read_timeout,
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
write_timeout: @write_timeout,
|
|
41
|
+
continue_timeout: @continue_timeout,
|
|
42
|
+
debug_output: @debug_output)
|
|
43
43
|
buf = "CONNECT #{conn_address}:#{@port} HTTP/#{HTTPVersion}\r\n"
|
|
44
44
|
buf << "Host: #{@address}:#{@port}\r\n"
|
|
45
45
|
if proxy_user
|
|
@@ -65,8 +65,8 @@ if RUBY_VERSION.split(".")[0..1].join(".") == "3.1"
|
|
|
65
65
|
@ssl_context.set_params(ssl_parameters)
|
|
66
66
|
unless @ssl_context.session_cache_mode.nil? # a dummy method on JRuby
|
|
67
67
|
@ssl_context.session_cache_mode =
|
|
68
|
-
|
|
69
|
-
|
|
68
|
+
OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT |
|
|
69
|
+
OpenSSL::SSL::SSLContext::SESSION_CACHE_NO_INTERNAL_STORE
|
|
70
70
|
end
|
|
71
71
|
if @ssl_context.respond_to?(:session_new_cb) # not implemented under JRuby
|
|
72
72
|
@ssl_context.session_new_cb = proc { |sock, sess| @ssl_session = sess }
|
|
@@ -108,9 +108,9 @@ if RUBY_VERSION.split(".")[0..1].join(".") == "3.1"
|
|
|
108
108
|
Chef::Log.debug("SSL established, protocol: #{s.ssl_version}, cipher: #{s.cipher[0]}")
|
|
109
109
|
end
|
|
110
110
|
@socket = BufferedIO.new(s, read_timeout: @read_timeout,
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
111
|
+
write_timeout: @write_timeout,
|
|
112
|
+
continue_timeout: @continue_timeout,
|
|
113
|
+
debug_output: @debug_output)
|
|
114
114
|
@last_communicated = nil
|
|
115
115
|
on_connect
|
|
116
116
|
rescue => exception
|