chef-vault 4.2.5 → 4.2.9

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '0974951af472b372835093b27c8749e84742a232ea3ca1b2431619b833955f33'
4
- data.tar.gz: 29b8a342842474dca7ff663addf310b8d1a968e954840c2c2a16bd0e812bbf9d
3
+ metadata.gz: eee715acb039d8781c64fc31bb0c723a97492adb3b1741757caeeb0a34804434
4
+ data.tar.gz: 9ff5ee7bf0dcce4664ffb2fa1624fac87ed0db8621f99ebb011f056212dece8a
5
5
  SHA512:
6
- metadata.gz: 71e4d13486154f085c0b9eed253e473849f9630cf236f36ca653a8a4e8993a932d8b87f443a37283c66b66a955958026348ca74e629d947f87075c0ed01b06c7
7
- data.tar.gz: e00903b95732ff8c124d731125f465feda8f0c44a0361b8150bf5ce3bc70c8f36138ed55ce149f33a2651a30b16367f1277fc9e78f7efb9d3c7c94e1da44e2fa
6
+ metadata.gz: a9381dea8edb554d1e5b697c6fcbdeb35865979ece9f32f77869e03832ffcf16ff67a807505801923fc04141dc8791432891f7cc366d74a9ab25fb83d298770c
7
+ data.tar.gz: ef6fb7279dc54608780e6ff6741bd258aac1eb3b1683008afd6afaa78c2e27e729aff575e190141a9a6234b875d29d842212291ce042c14332412a0b6f89f902
data/Gemfile CHANGED
@@ -16,11 +16,15 @@ group :development do
16
16
  else
17
17
  gem "contracts", "~> 0.17"
18
18
  gem "chef-zero", "~> 15.0"
19
- gem "chef", ">= 18.5.0"
19
+ if RUBY_PLATFORM.include?("mingw")
20
+ gem "chef", ">= 18.10"
21
+ else
22
+ gem "chef", ">= 18.10", platforms: [:ruby]
23
+ end
20
24
  gem "rspec", "~> 3.0"
21
25
  gem "aruba", "~> 2.3"
22
- gem "knife", "~> 18.0"
23
- gem "chef-utils", ">= 18.5.0" # pin until we drop ruby >=3
26
+ gem "knife", "~> 18.10"
27
+ gem "chef-utils", ">= 18.10", platforms: [:ruby] # pin until we drop ruby >=3
24
28
  end
25
29
  end
26
30
 
data/chef-vault.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  # Chef-Vault Gemspec file
2
2
  # Copyright 2013-2015, Nordstrom, Inc.
3
- # Copyright 2017-2019, Chef Software, Inc.
3
+ # Copyright (c) 2013-2025 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved.
4
4
 
5
5
  # Licensed under the Apache License, Version 2.0 (the "License");
6
6
  # you may not use this file except in compliance with the License.
@@ -26,7 +26,10 @@ Gem::Specification.new do |s|
26
26
  s.description = s.summary
27
27
  s.homepage = "https://github.com/chef/chef-vault"
28
28
  s.license = "Apache-2.0"
29
- s.files = %w{LICENSE Gemfile} + Dir.glob("*.gemspec") + `git ls-files`.split("\n").select { |f| f =~ %r{^(?:bin/|lib/)}i }
29
+ s.files = %w{LICENSE Gemfile} +
30
+ Dir.glob("Gemfile*") +
31
+ Dir.glob("*.gemspec") +
32
+ Dir.glob("{lib,spec}/**/*", File::FNM_DOTMATCH).reject { |f| File.directory?(f) }
30
33
  s.require_paths = ["lib"]
31
34
  s.bindir = "bin"
32
35
  s.executables = %w{ chef-vault }
@@ -1,5 +1,5 @@
1
1
  # Author:: Tyler Cloke <tyler@chef.io>
2
- # Copyright:: Copyright 2016, Chef Software, Inc.
2
+ # Copyright:: Copyright (c) 2013-2025 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved.
3
3
  # License:: Apache License, Version 2.0
4
4
 
5
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,5 +1,5 @@
1
1
  # Author:: Tyler Cloke <tyler@chef.io>
2
- # Copyright:: Copyright 2016, Chef Software, Inc.
2
+ # Copyright:: Copyright (c) 2013-2025 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved.
3
3
  # License:: Apache License, Version 2.0
4
4
 
5
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,6 +1,6 @@
1
1
  # Author:: Kevin Moser <kevin.moser@nordstrom.com>
2
2
  # Copyright:: Copyright 2013-15, Nordstrom, Inc.
3
- # Copyright:: Copyright 2015-16, Chef Software, Inc.
3
+ # Copyright:: Copyright (c) 2013-2025 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved.
4
4
  # License:: Apache License, Version 2.0
5
5
 
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,6 +1,6 @@
1
1
  # Description: ChefVault VERSION file
2
2
  # Copyright 2013-15, Nordstrom, Inc.
3
- # Copyright 2015-2017, Chef Software Inc.
3
+ # Copyright (c) 2013-2025 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved.
4
4
 
5
5
  # Licensed under the Apache License, Version 2.0 (the "License");
6
6
  # you may not use this file except in compliance with the License.
@@ -15,6 +15,6 @@
15
15
  # limitations under the License.
16
16
 
17
17
  class ChefVault
18
- VERSION = "4.2.5"
18
+ VERSION = "4.2.9"
19
19
  MAJOR, MINOR, TINY = VERSION.split(".")
20
20
  end
@@ -0,0 +1,37 @@
1
+ require "spec_helper"
2
+ require "chef/knife/mixin/helper"
3
+
4
+ RSpec.describe ChefVault::Mixin::Helper do
5
+ include ChefVault::Mixin::Helper
6
+
7
+ before do
8
+ allow(ChefVault::Log).to receive(:warn)
9
+ end
10
+
11
+ let(:json_base) { { "username": "root" } }
12
+ let(:valid_json) { '{"username": "root", "password": "abcabc"}' }
13
+ let(:malformed_json) { '{"username": ' }
14
+ let(:valid_json_with_special_character) { { "Data": "Null->\u0000<-Byte" } }
15
+
16
+ describe "#values_from_json" do
17
+ it "should raise error when invalid JSON provided" do
18
+ expect { values_from_json(malformed_json) }.to raise_error(JSON::ParserError)
19
+ end
20
+
21
+ it "should not raise error when valid JSON provided" do
22
+ expect { values_from_json(valid_json) }.to_not raise_error
23
+ end
24
+
25
+ it "should not raise error if JSON contains tab, newline, or space characters" do
26
+ ["abc\tabc", "abc\nabc", "abc abc"].each do |pass|
27
+ json_data_with_slash = json_base.merge("password": pass)
28
+ expect { values_from_json(json_data_with_slash.to_json) }.to_not raise_error
29
+ end
30
+ end
31
+
32
+ it "should not warn or error when JSON contains special character sequences" do
33
+ expect(ChefVault::Log).to_not receive(:warn)
34
+ expect { values_from_json(valid_json_with_special_character.to_json) }.to_not raise_error
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,247 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe ChefVault::Actor do
4
+ let(:actor_name) { "actor" }
5
+ let(:public_key_string) do
6
+ "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyMXT9IOV9pkQsxsnhSx8\n8RX6GW3caxkjcXFfHg6E7zUVBFAsfw4B1D+eHAks3qrDB7UrUxsmCBXwU4dQHaQy\ngAn5Sv0Jc4CejDNL2EeCBLZ4TF05odHmuzyDdPkSZP6utpR7+uF7SgVQedFGySIB\nih86aM+HynhkJqgJYhoxkrdo/JcWjpk7YEmWb6p4esnvPWOpbcjIoFs4OjavWBOF\niTfpkS0SkygpLi/iQu9RQfd4hDMWCc6yh3Th/1nVMUd+xQCdUK5wxluAWSv8U0zu\nhiIlZNazpCGHp+3QdP3f6rebmQA8pRM8qT5SlOvCYPk79j+IMUVSYrR4/DTZ+VM+\naQIDAQAB\n-----END PUBLIC KEY-----\n"
7
+ end
8
+
9
+ let(:key_response) do
10
+ {
11
+ "name" => "default",
12
+ "public_key" => "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyMXT9IOV9pkQsxsnhSx8\n8RX6GW3caxkjcXFfHg6E7zUVBFAsfw4B1D+eHAks3qrDB7UrUxsmCBXwU4dQHaQy\ngAn5Sv0Jc4CejDNL2EeCBLZ4TF05odHmuzyDdPkSZP6utpR7+uF7SgVQedFGySIB\nih86aM+HynhkJqgJYhoxkrdo/JcWjpk7YEmWb6p4esnvPWOpbcjIoFs4OjavWBOF\niTfpkS0SkygpLi/iQu9RQfd4hDMWCc6yh3Th/1nVMUd+xQCdUK5wxluAWSv8U0zu\nhiIlZNazpCGHp+3QdP3f6rebmQA8pRM8qT5SlOvCYPk79j+IMUVSYrR4/DTZ+VM+\naQIDAQAB\n-----END PUBLIC KEY-----\n",
13
+ "expiration_date" => "infinity",
14
+ }
15
+ end
16
+
17
+ let(:http_response_code) do
18
+ "404"
19
+ end
20
+
21
+ let(:http_error) do
22
+ http_response = double("http error")
23
+ allow(http_response).to receive(:code).and_return(http_response_code)
24
+ Net::HTTPClientException.new("http error message", http_response)
25
+ end
26
+
27
+ let(:api) { double("api") }
28
+
29
+ subject(:chef_key) { described_class.new(actor_type, actor_name) }
30
+
31
+ describe "#new" do
32
+ context "when something besides 'clients' or 'users' is passed" do
33
+ let(:actor_type) { "charmander" }
34
+ it "throws an error" do
35
+ expect { described_class.new("charmander", actor_name) }.to raise_error(RuntimeError)
36
+ end
37
+ end
38
+
39
+ context "when 'clients' is passed" do
40
+ it "requests a client key" do
41
+ expect_any_instance_of(described_class).to receive(:get_client_key)
42
+ described_class.new("clients", actor_name).key
43
+ end
44
+ end
45
+
46
+ context "when 'admins' is passed" do
47
+ it "requests a admin key" do
48
+ expect_any_instance_of(described_class).to receive(:get_admin_key)
49
+ described_class.new("admins", actor_name).key
50
+ end
51
+ end
52
+ end
53
+
54
+ shared_examples_for "get_key_handling" do
55
+ context "when the default key exists for the requested client" do
56
+ it "sets up a valid key" do
57
+ expect(chef_key).to receive(:get_key).with(request_actor_type).and_return(public_key_string)
58
+ expect(chef_key.send(method)).to eq(public_key_string)
59
+ end
60
+ end
61
+
62
+ context "when get_key returns an http error" do
63
+ before do
64
+ allow(chef_key).to receive(:get_key).with(request_actor_type).and_raise(http_error)
65
+ end
66
+
67
+ context "when the error code is not 404 or 403" do
68
+ let(:http_response_code) { "500" }
69
+
70
+ it "raises the original error" do
71
+ expect { chef_key.send(method) }.to raise_error(http_error)
72
+ end
73
+ end
74
+
75
+ context "when the error code is 403" do
76
+ let(:http_response_code) { "403" }
77
+
78
+ it "prints information for the user to resolve the issue and raises the original error" do
79
+ expect(chef_key).to receive(:print_forbidden_error)
80
+ expect { chef_key.send(method) }.to raise_error(http_error)
81
+ end
82
+ end
83
+ end
84
+ end
85
+
86
+ describe "#get_client_key" do
87
+ let(:request_actor_type) { "clients" }
88
+ let(:actor_type) { "clients" }
89
+ let(:method) { :get_client_key }
90
+
91
+ it_should_behave_like "get_key_handling"
92
+
93
+ context "when get_key returns an http error" do
94
+ before do
95
+ allow(chef_key).to receive(:get_key).with(actor_type).and_raise(http_error)
96
+ end
97
+
98
+ context "when the error code is 404" do
99
+ let(:http_response_code) { "404" }
100
+
101
+ it "raises ChefVault::Exceptions::ClientNotFound" do
102
+ expect { chef_key.get_client_key }.to raise_error(ChefVault::Exceptions::ClientNotFound)
103
+ end
104
+ end
105
+ end
106
+ end # get_client_key
107
+
108
+ describe "#get_admin_key" do
109
+ let(:request_actor_type) { "users" }
110
+ let(:actor_type) { "admins" }
111
+ let(:method) { :get_admin_key }
112
+
113
+ it_should_behave_like "get_key_handling"
114
+
115
+ context "when the first get_key for users returns an http error" do
116
+ before do
117
+ allow(chef_key).to receive(:get_key).with(request_actor_type).and_raise(http_error)
118
+ end
119
+
120
+ context "when the error code from the users get is a 404" do
121
+ let(:http_response_code) { "404" }
122
+
123
+ context "when the second get_key for clients returns an http error" do
124
+
125
+ let(:http_error_2) do
126
+ http_response = double("http error")
127
+ allow(http_response).to receive(:code).and_return(http_response_code_2)
128
+ Net::HTTPClientException.new("http error message", http_response)
129
+ end
130
+
131
+ before do
132
+ allow(chef_key).to receive(:get_key).with("clients").and_raise(http_error_2)
133
+ end
134
+
135
+ context "when it is a 404" do
136
+ let(:http_response_code_2) { "404" }
137
+
138
+ it "rasies ChefVault::Exceptions::AdminNotFound" do
139
+ expect { chef_key.get_admin_key }.to raise_error(ChefVault::Exceptions::AdminNotFound)
140
+ end
141
+ end
142
+
143
+ context "when it is a 403" do
144
+ let(:http_response_code_2) { "403" }
145
+
146
+ it "raises the original error" do
147
+ expect { chef_key.get_admin_key }.to raise_error(http_error_2)
148
+ end
149
+ end
150
+
151
+ context "when it is not a 404" do
152
+ let(:http_response_code_2) { "500" }
153
+
154
+ it "raises the original error" do
155
+ expect { chef_key.get_admin_key }.to raise_error(http_error_2)
156
+ end
157
+ end
158
+ end # when the second get_key for clients returns an http error
159
+
160
+ context "when the second get_key for clients exists with the same name as the admin requested" do
161
+ it "strangely returns the client key as an admin key" do
162
+ expect(chef_key).to receive(:get_key).with(request_actor_type).and_return(public_key_string)
163
+ expect(chef_key.send(method)).to eq(public_key_string)
164
+ end
165
+ end
166
+ end # when the first get_key for users returns an http erro
167
+ end
168
+ end # get_admin_key
169
+
170
+ describe "#get_key" do
171
+
172
+ shared_examples_for "a properly retrieved and error handled key fetch" do
173
+ # mock out the API
174
+ before do
175
+ allow(chef_key).to receive(:api).and_return(api)
176
+ %i{rest_v0 rest_v1 org_scoped_rest_v0 org_scoped_rest_v1}.each do |method|
177
+ allow(api).to receive(method)
178
+ end
179
+ end
180
+
181
+ context "when keys/default returns 200 for org scoped endpoint" do
182
+ before do
183
+ allow(api.org_scoped_rest_v1).to receive(:get).with("#{request_actor_type}/#{actor_name}/keys/default").and_return(key_response)
184
+ end
185
+
186
+ it "returns the public_key" do
187
+ expect(chef_key.get_key(request_actor_type)).to eql(public_key_string)
188
+ end
189
+
190
+ it "hits the proper endpoint" do
191
+ expect(api.org_scoped_rest_v1).to receive(:get).with("#{request_actor_type}/#{actor_name}/keys/default")
192
+ chef_key.get_key(request_actor_type)
193
+ end
194
+ end
195
+
196
+ context "when a 500 is returned" do
197
+ let(:http_response_code) { "500" }
198
+ before do
199
+ allow(api.org_scoped_rest_v1).to receive(:get).with("#{request_actor_type}/#{actor_name}/keys/default").and_raise(http_error)
200
+ end
201
+
202
+ it "raises the http error" do
203
+ expect { chef_key.get_key(request_actor_type) }.to raise_error(http_error)
204
+ end
205
+ end
206
+
207
+ context "when keys/default returns 404" do
208
+ let(:http_response_code) { "404" }
209
+ let(:chef_object) { double("chef object") }
210
+
211
+ before do
212
+ allow(api.org_scoped_rest_v1).to receive(:get).with("#{request_actor_type}/#{actor_name}/keys/default").and_raise(http_error)
213
+ allow(chef_object_type).to receive(:load).with(actor_name).and_return(chef_object)
214
+ allow(chef_object).to receive(:public_key).and_return(public_key_string)
215
+ end
216
+
217
+ it "tries to load the object via Chef::<object>_v1" do
218
+ expect(chef_object_type).to receive(:load).with(actor_name)
219
+ chef_key.get_key(request_actor_type)
220
+ end
221
+
222
+ context "when the Chef::<object>_v1 object loads properly" do
223
+ it "returns the public key" do
224
+ expect(chef_key.get_key(request_actor_type)).to eql(public_key_string)
225
+ end
226
+ end
227
+ end
228
+ end # shared_examples_for
229
+
230
+ context "when a client is passed" do
231
+ let(:request_actor_type) { "clients" }
232
+ let(:actor_type) { "clients" }
233
+ let(:chef_object_type) { Chef::ApiClient }
234
+
235
+ it_behaves_like "a properly retrieved and error handled key fetch"
236
+ end
237
+
238
+ context "when an admin is passed" do
239
+ let(:request_actor_type) { "users" }
240
+ let(:actor_type) { "admins" }
241
+ let(:chef_object_type) { Chef::User }
242
+
243
+ it_behaves_like "a properly retrieved and error handled key fetch"
244
+ end
245
+
246
+ end
247
+ end
@@ -0,0 +1,37 @@
1
+ RSpec.describe ChefVault::Certificate do
2
+ let(:item) { double(ChefVault::Item) }
3
+ let(:cert) { ChefVault::Certificate.new("foo", "bar") }
4
+
5
+ before do
6
+ allow(ChefVault::Item).to receive(:load).with("foo", "bar") { item }
7
+ allow(item).to receive(:[]).with("id") { "bar" }
8
+ allow(item).to receive(:[]).with("contents") { "baz" }
9
+ end
10
+
11
+ describe "#new" do
12
+ it "loads item" do
13
+ expect(ChefVault::Item).to receive(:load).with("foo", "bar")
14
+
15
+ ChefVault::Certificate.new("foo", "bar")
16
+ end
17
+ end
18
+
19
+ describe "#[]" do
20
+ it "given an 'id' parameter, returns its value" do
21
+ expect(cert["id"]).to eq "bar"
22
+ end
23
+ end
24
+
25
+ describe "decrypt_contents" do
26
+ it "echoes warning" do
27
+ expect(ChefVault::Log).to receive(:warn).with("This method is deprecated, please switch to item['value'] calls")
28
+ cert.decrypt_contents
29
+ end
30
+
31
+ it "returns items contents" do
32
+ expect(item).to receive(:[]).with("contents")
33
+
34
+ expect(cert.decrypt_contents).to eq "baz"
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,39 @@
1
+ RSpec.describe ChefVault::ChefApi do
2
+ let(:root_url) { "https://localhost" }
3
+ let(:scoped_url) { "https://localhost/organizations/fakeorg" }
4
+ let(:api_v0_hash) { { api_version: "0" } }
5
+ let(:api_v1_hash) { { api_version: "1" } }
6
+
7
+ before do
8
+ Chef::Config[:chef_server_root] = root_url
9
+ Chef::Config[:chef_server_url] = scoped_url
10
+ end
11
+
12
+ describe "#rest_v0" do
13
+ it "returns an instance of Chef::ServerAPI set to use API version 0 scoped to root" do
14
+ expect(Chef::ServerAPI).to receive(:new).with(root_url, api_v0_hash)
15
+ subject.rest_v0
16
+ end
17
+ end
18
+
19
+ describe "#rest_v1" do
20
+ it "returns an instance of Chef::ServerAPI set to use API version 0 scoped to root" do
21
+ expect(Chef::ServerAPI).to receive(:new).with(root_url, api_v1_hash)
22
+ subject.rest_v1
23
+ end
24
+ end
25
+
26
+ describe "#org_scoped_rest_v0" do
27
+ it "returns an instance of Chef::ServerAPI set to use API version 0 scoped to root" do
28
+ expect(Chef::ServerAPI).to receive(:new).with(scoped_url, api_v0_hash)
29
+ subject.org_scoped_rest_v0
30
+ end
31
+ end
32
+
33
+ describe "#org_scoped_rest_v1" do
34
+ it "returns an instance of Chef::ServerAPI set to use API version 0 scoped to root" do
35
+ expect(Chef::ServerAPI).to receive(:new).with(scoped_url, api_v1_hash)
36
+ subject.org_scoped_rest_v1
37
+ end
38
+ end
39
+ end