cheffish 1.3.1 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +201 -201
  3. data/README.md +120 -117
  4. data/Rakefile +23 -23
  5. data/lib/chef/provider/chef_acl.rb +439 -434
  6. data/lib/chef/provider/chef_client.rb +53 -48
  7. data/lib/chef/provider/chef_container.rb +55 -50
  8. data/lib/chef/provider/chef_data_bag.rb +55 -50
  9. data/lib/chef/provider/chef_data_bag_item.rb +278 -273
  10. data/lib/chef/provider/chef_environment.rb +83 -78
  11. data/lib/chef/provider/chef_group.rb +83 -78
  12. data/lib/chef/provider/chef_mirror.rb +169 -164
  13. data/lib/chef/provider/chef_node.rb +87 -82
  14. data/lib/chef/provider/chef_organization.rb +155 -150
  15. data/lib/chef/provider/chef_resolved_cookbooks.rb +46 -41
  16. data/lib/chef/provider/chef_role.rb +84 -79
  17. data/lib/chef/provider/chef_user.rb +59 -54
  18. data/lib/chef/provider/private_key.rb +225 -220
  19. data/lib/chef/provider/public_key.rb +88 -82
  20. data/lib/chef/resource/chef_acl.rb +69 -65
  21. data/lib/chef/resource/chef_client.rb +48 -44
  22. data/lib/chef/resource/chef_container.rb +22 -18
  23. data/lib/chef/resource/chef_data_bag.rb +22 -18
  24. data/lib/chef/resource/chef_data_bag_item.rb +121 -114
  25. data/lib/chef/resource/chef_environment.rb +77 -71
  26. data/lib/chef/resource/chef_group.rb +53 -49
  27. data/lib/chef/resource/chef_mirror.rb +52 -48
  28. data/lib/chef/resource/chef_node.rb +22 -18
  29. data/lib/chef/resource/chef_organization.rb +69 -64
  30. data/lib/chef/resource/chef_resolved_cookbooks.rb +35 -31
  31. data/lib/chef/resource/chef_role.rb +110 -104
  32. data/lib/chef/resource/chef_user.rb +56 -52
  33. data/lib/chef/resource/private_key.rb +48 -44
  34. data/lib/chef/resource/public_key.rb +25 -21
  35. data/lib/cheffish.rb +235 -233
  36. data/lib/cheffish/actor_provider_base.rb +131 -131
  37. data/lib/cheffish/basic_chef_client.rb +184 -184
  38. data/lib/cheffish/chef_provider_base.rb +246 -246
  39. data/lib/cheffish/chef_run.rb +162 -155
  40. data/lib/cheffish/chef_run_data.rb +19 -19
  41. data/lib/cheffish/chef_run_listener.rb +30 -30
  42. data/lib/cheffish/key_formatter.rb +113 -113
  43. data/lib/cheffish/merged_config.rb +94 -94
  44. data/lib/cheffish/recipe_dsl.rb +157 -157
  45. data/lib/cheffish/rspec.rb +8 -8
  46. data/lib/cheffish/rspec/chef_run_support.rb +83 -83
  47. data/lib/cheffish/rspec/matchers.rb +4 -4
  48. data/lib/cheffish/rspec/matchers/be_idempotent.rb +16 -16
  49. data/lib/cheffish/rspec/matchers/emit_no_warnings_or_errors.rb +15 -15
  50. data/lib/cheffish/rspec/matchers/have_updated.rb +37 -37
  51. data/lib/cheffish/rspec/matchers/partially_match.rb +63 -63
  52. data/lib/cheffish/rspec/recipe_run_wrapper.rb +59 -47
  53. data/lib/cheffish/rspec/repository_support.rb +108 -108
  54. data/lib/cheffish/server_api.rb +52 -52
  55. data/lib/cheffish/version.rb +3 -3
  56. data/lib/cheffish/with_pattern.rb +21 -21
  57. data/spec/functional/fingerprint_spec.rb +64 -64
  58. data/spec/functional/merged_config_spec.rb +19 -19
  59. data/spec/functional/server_api_spec.rb +13 -13
  60. data/spec/integration/chef_acl_spec.rb +879 -879
  61. data/spec/integration/chef_client_spec.rb +105 -105
  62. data/spec/integration/chef_container_spec.rb +33 -33
  63. data/spec/integration/chef_group_spec.rb +309 -309
  64. data/spec/integration/chef_mirror_spec.rb +491 -491
  65. data/spec/integration/chef_node_spec.rb +786 -786
  66. data/spec/integration/chef_organization_spec.rb +226 -226
  67. data/spec/integration/chef_role_spec.rb +78 -0
  68. data/spec/integration/chef_user_spec.rb +85 -85
  69. data/spec/integration/private_key_spec.rb +399 -399
  70. data/spec/integration/recipe_dsl_spec.rb +28 -28
  71. data/spec/integration/rspec/converge_spec.rb +183 -183
  72. data/spec/support/key_support.rb +29 -29
  73. data/spec/support/spec_support.rb +15 -15
  74. data/spec/unit/get_private_key_spec.rb +131 -131
  75. data/spec/unit/recipe_run_wrapper_spec.rb +37 -0
  76. metadata +8 -5
@@ -1,85 +1,85 @@
1
- require 'support/spec_support'
2
- require 'cheffish/rspec/chef_run_support'
3
- require 'support/key_support'
4
- require 'chef/resource/chef_user'
5
- require 'chef/provider/chef_user'
6
-
7
- repo_path = Dir.mktmpdir('chef_repo')
8
-
9
- describe Chef::Resource::ChefUser do
10
- extend Cheffish::RSpec::ChefRunSupport
11
-
12
- with_converge do
13
- private_key "#{repo_path}/blah.pem"
14
- end
15
-
16
- when_the_chef_server 'is empty' do
17
- context 'and we run a recipe that creates user "blah"'do
18
- it 'the user gets created' do
19
- expect_recipe {
20
- chef_user 'blah' do
21
- source_key_path "#{repo_path}/blah.pem"
22
- end
23
- }.to have_updated 'chef_user[blah]', :create
24
- user = get('/users/blah')
25
- expect(user['name']).to eq('blah')
26
- key, format = Cheffish::KeyFormatter.decode(user['public_key'])
27
- expect(key).to be_public_key_for("#{repo_path}/blah.pem")
28
- end
29
- end
30
-
31
- context 'and we run a recipe that creates user "blah" with output_key_path' do
32
- with_converge do
33
- chef_user 'blah' do
34
- source_key_path "#{repo_path}/blah.pem"
35
- output_key_path "#{repo_path}/blah.pub"
36
- end
37
- end
38
-
39
- it 'the output public key gets created' do
40
- expect(IO.read("#{repo_path}/blah.pub")).to start_with('ssh-rsa ')
41
- expect("#{repo_path}/blah.pub").to be_public_key_for("#{repo_path}/blah.pem")
42
- end
43
- end
44
- end
45
-
46
- when_the_chef_12_server 'is in multi-org mode' do
47
- context 'and chef_server_url is pointed at the top level' do
48
- context 'and we run a recipe that creates user "blah"'do
49
- it 'the user gets created' do
50
- expect_recipe {
51
- chef_user 'blah' do
52
- source_key_path "#{repo_path}/blah.pem"
53
- end
54
- }.to have_updated 'chef_user[blah]', :create
55
- user = get('/users/blah')
56
- expect(user['name']).to eq('blah')
57
- key, format = Cheffish::KeyFormatter.decode(user['public_key'])
58
- expect(key).to be_public_key_for("#{repo_path}/blah.pem")
59
- end
60
- end
61
- end
62
-
63
- context 'and chef_server_url is pointed at /organizations/foo' do
64
- organization 'foo'
65
-
66
- before :each do
67
- Chef::Config.chef_server_url = URI.join(Chef::Config.chef_server_url, '/organizations/foo').to_s
68
- end
69
-
70
- context 'and we run a recipe that creates user "blah"'do
71
- it 'the user gets created' do
72
- expect_recipe {
73
- chef_user 'blah' do
74
- source_key_path "#{repo_path}/blah.pem"
75
- end
76
- }.to have_updated 'chef_user[blah]', :create
77
- user = get('/users/blah')
78
- expect(user['name']).to eq('blah')
79
- key, format = Cheffish::KeyFormatter.decode(user['public_key'])
80
- expect(key).to be_public_key_for("#{repo_path}/blah.pem")
81
- end
82
- end
83
- end
84
- end
85
- end
1
+ require 'support/spec_support'
2
+ require 'cheffish/rspec/chef_run_support'
3
+ require 'support/key_support'
4
+ require 'chef/resource/chef_user'
5
+ require 'chef/provider/chef_user'
6
+
7
+ repo_path = Dir.mktmpdir('chef_repo')
8
+
9
+ describe Chef::Resource::ChefUser do
10
+ extend Cheffish::RSpec::ChefRunSupport
11
+
12
+ with_converge do
13
+ private_key "#{repo_path}/blah.pem"
14
+ end
15
+
16
+ when_the_chef_server 'is empty' do
17
+ context 'and we run a recipe that creates user "blah"'do
18
+ it 'the user gets created' do
19
+ expect_recipe {
20
+ chef_user 'blah' do
21
+ source_key_path "#{repo_path}/blah.pem"
22
+ end
23
+ }.to have_updated 'chef_user[blah]', :create
24
+ user = get('/users/blah')
25
+ expect(user['name']).to eq('blah')
26
+ key, format = Cheffish::KeyFormatter.decode(user['public_key'])
27
+ expect(key).to be_public_key_for("#{repo_path}/blah.pem")
28
+ end
29
+ end
30
+
31
+ context 'and we run a recipe that creates user "blah" with output_key_path' do
32
+ with_converge do
33
+ chef_user 'blah' do
34
+ source_key_path "#{repo_path}/blah.pem"
35
+ output_key_path "#{repo_path}/blah.pub"
36
+ end
37
+ end
38
+
39
+ it 'the output public key gets created' do
40
+ expect(IO.read("#{repo_path}/blah.pub")).to start_with('ssh-rsa ')
41
+ expect("#{repo_path}/blah.pub").to be_public_key_for("#{repo_path}/blah.pem")
42
+ end
43
+ end
44
+ end
45
+
46
+ when_the_chef_12_server 'is in multi-org mode' do
47
+ context 'and chef_server_url is pointed at the top level' do
48
+ context 'and we run a recipe that creates user "blah"'do
49
+ it 'the user gets created' do
50
+ expect_recipe {
51
+ chef_user 'blah' do
52
+ source_key_path "#{repo_path}/blah.pem"
53
+ end
54
+ }.to have_updated 'chef_user[blah]', :create
55
+ user = get('/users/blah')
56
+ expect(user['name']).to eq('blah')
57
+ key, format = Cheffish::KeyFormatter.decode(user['public_key'])
58
+ expect(key).to be_public_key_for("#{repo_path}/blah.pem")
59
+ end
60
+ end
61
+ end
62
+
63
+ context 'and chef_server_url is pointed at /organizations/foo' do
64
+ organization 'foo'
65
+
66
+ before :each do
67
+ Chef::Config.chef_server_url = URI.join(Chef::Config.chef_server_url, '/organizations/foo').to_s
68
+ end
69
+
70
+ context 'and we run a recipe that creates user "blah"'do
71
+ it 'the user gets created' do
72
+ expect_recipe {
73
+ chef_user 'blah' do
74
+ source_key_path "#{repo_path}/blah.pem"
75
+ end
76
+ }.to have_updated 'chef_user[blah]', :create
77
+ user = get('/users/blah')
78
+ expect(user['name']).to eq('blah')
79
+ key, format = Cheffish::KeyFormatter.decode(user['public_key'])
80
+ expect(key).to be_public_key_for("#{repo_path}/blah.pem")
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -1,399 +1,399 @@
1
- require 'support/spec_support'
2
- require 'cheffish/rspec/chef_run_support'
3
- require 'chef/resource/private_key'
4
- require 'chef/provider/private_key'
5
- require 'chef/resource/public_key'
6
- require 'chef/provider/public_key'
7
- require 'support/key_support'
8
-
9
- repo_path = Dir.mktmpdir('chef_repo')
10
-
11
- describe Chef::Resource::PrivateKey do
12
- extend Cheffish::RSpec::ChefRunSupport
13
-
14
- before :each do
15
- FileUtils.remove_entry_secure(repo_path)
16
- Dir.mkdir(repo_path)
17
- end
18
-
19
- context 'with a recipe with a private_key' do
20
- it 'the private_key is created in pem format' do
21
- expect_recipe {
22
- private_key "#{repo_path}/blah"
23
- }.to have_updated "private_key[#{repo_path}/blah]", :create
24
- expect(IO.read("#{repo_path}/blah")).to start_with('-----BEGIN')
25
- expect(OpenSSL::PKey.read(IO.read("#{repo_path}/blah"))).to be_kind_of(OpenSSL::PKey::RSA)
26
- end
27
- end
28
-
29
- context 'with a private_key "blah" resource' do
30
- before :each do
31
- Dir.mkdir("#{repo_path}/other_keys")
32
- Chef::Config.private_key_paths = [ repo_path, "#{repo_path}/other_keys" ]
33
- end
34
-
35
- it 'the private key is created in the private_key_write_path' do
36
- expect_recipe {
37
- private_key 'blah'
38
- }.to have_updated "private_key[blah]", :create
39
- expect(Chef::Config.private_key_write_path).to eq(repo_path)
40
- expect(File.exist?("#{repo_path}/blah")).to be true
41
- expect(File.exist?("#{repo_path}/other_keys/blah")).to be false
42
- expect(OpenSSL::PKey.read(IO.read("#{repo_path}/blah"))).to be_kind_of(OpenSSL::PKey::RSA)
43
- expect(OpenSSL::PKey.read(Cheffish.get_private_key('blah'))).to be_kind_of(OpenSSL::PKey::RSA)
44
- end
45
-
46
- context 'and the private key already exists somewhere not in the write path' do
47
- before :each do
48
- recipe { private_key "#{repo_path}/other_keys/blah" }.converge
49
- end
50
-
51
- it 'the private expect(key).to not update' do
52
- expect_recipe {
53
- private_key 'blah'
54
- }.not_to have_updated "private_key[blah]", :create
55
-
56
- expect(File.exist?("#{repo_path}/blah")).to be false
57
- expect(File.exist?("#{repo_path}/other_keys/blah")).to be true
58
- end
59
- end
60
- end
61
-
62
- context 'with a private key' do
63
- before :each do
64
- Cheffish::BasicChefClient.converge_block do
65
- private_key "#{repo_path}/blah"
66
- end
67
- end
68
-
69
- context 'and a private_key that copies it in der format' do
70
- it 'the private_key is copied in der format and is identical' do
71
- expect_recipe {
72
- private_key "#{repo_path}/blah.der" do
73
- source_key_path "#{repo_path}/blah"
74
- format :der
75
- end
76
- }.to have_updated "private_key[#{repo_path}/blah.der]", :create
77
- key_str = IO.read("#{repo_path}/blah.der")
78
- expect(key_str).not_to start_with('-----BEGIN')
79
- expect(key_str).not_to start_with('ssh-')
80
- expect("#{repo_path}/blah.der").to match_private_key("#{repo_path}/blah")
81
- end
82
- end
83
-
84
- it 'a private_key that copies it from in-memory as a string succeeds' do
85
- expect_recipe {
86
- private_key "#{repo_path}/blah.der" do
87
- source_key IO.read("#{repo_path}/blah")
88
- format :der
89
- end
90
- }.to have_updated "private_key[#{repo_path}/blah.der]", :create
91
- key_str = IO.read("#{repo_path}/blah.der")
92
- expect(key_str).not_to start_with('-----BEGIN')
93
- expect(key_str).not_to start_with('ssh-')
94
- expect("#{repo_path}/blah.der").to match_private_key("#{repo_path}/blah")
95
- end
96
-
97
- it 'a private_key that copies it from in-memory as a key succeeds' do
98
- key = OpenSSL::PKey.read(IO.read("#{repo_path}/blah"))
99
- expect_recipe {
100
- private_key "#{repo_path}/blah.der" do
101
- source_key key
102
- format :der
103
- end
104
- }.to have_updated "private_key[#{repo_path}/blah.der]", :create
105
- key_str = IO.read("#{repo_path}/blah.der")
106
- expect(key_str).not_to start_with('-----BEGIN')
107
- expect(key_str).not_to start_with('ssh-')
108
- expect("#{repo_path}/blah.der").to match_private_key("#{repo_path}/blah")
109
- end
110
-
111
- context 'and a public_key recipe' do
112
- it 'the public_key is created' do
113
- expect_recipe {
114
- public_key "#{repo_path}/blah.pub" do
115
- source_key_path "#{repo_path}/blah"
116
- end
117
- }.to have_updated "public_key[#{repo_path}/blah.pub]", :create
118
- expect(IO.read("#{repo_path}/blah.pub")).to start_with('ssh-rsa ')
119
- expect("#{repo_path}/blah.pub").to be_public_key_for "#{repo_path}/blah"
120
- end
121
- end
122
-
123
- context 'and a public key' do
124
- before :each do
125
- Cheffish::BasicChefClient.converge_block do
126
- public_key "#{repo_path}/blah.pub" do
127
- source_key_path "#{repo_path}/blah"
128
- end
129
- end
130
- end
131
-
132
- context 'and public_key resource based off the public key file' do
133
- it 'the second public_key is created' do
134
- expect_recipe {
135
- public_key "#{repo_path}/blah.pub2" do
136
- source_key_path "#{repo_path}/blah.pub"
137
- end
138
- }.to have_updated "public_key[#{repo_path}/blah.pub2]", :create
139
- expect(IO.read("#{repo_path}/blah.pub")).to start_with('ssh-rsa ')
140
- expect("#{repo_path}/blah.pub").to be_public_key_for "#{repo_path}/blah"
141
- end
142
- end
143
-
144
- context 'and another public_key based off the first public_key in-memory in a string' do
145
- it 'the second public_key is created' do
146
- expect_recipe {
147
- public_key "#{repo_path}/blah.pub2" do
148
- source_key IO.read("#{repo_path}/blah.pub")
149
- end
150
- }.to have_updated "public_key[#{repo_path}/blah.pub2]", :create
151
- expect(IO.read("#{repo_path}/blah.pub")).to start_with('ssh-rsa ')
152
- expect("#{repo_path}/blah.pub").to be_public_key_for "#{repo_path}/blah"
153
- end
154
- end
155
-
156
- it 'and another public_key based off the first public_key in-memory in a key, the second public_key is created' do
157
- key, format = Cheffish::KeyFormatter.decode(IO.read("#{repo_path}/blah.pub"))
158
-
159
- expect_recipe {
160
- public_key "#{repo_path}/blah.pub2" do
161
- source_key key
162
- end
163
- }.to have_updated "public_key[#{repo_path}/blah.pub2]", :create
164
- expect(IO.read("#{repo_path}/blah.pub")).to start_with('ssh-rsa ')
165
- expect("#{repo_path}/blah.pub").to be_public_key_for "#{repo_path}/blah"
166
- end
167
-
168
- context 'and another public_key in :pem format based off the first public_key' do
169
- it 'the second public_key is created' do
170
- expect_recipe {
171
- public_key "#{repo_path}/blah.pub2" do
172
- source_key_path "#{repo_path}/blah.pub"
173
- format :pem
174
- end
175
- }.to have_updated "public_key[#{repo_path}/blah.pub2]", :create
176
- expect(IO.read("#{repo_path}/blah.pub")).to start_with('ssh-rsa ')
177
- expect("#{repo_path}/blah.pub").to be_public_key_for "#{repo_path}/blah"
178
- end
179
- end
180
-
181
- context 'and another public_key in :der format based off the first public_key' do
182
- it 'the second public_key is created' do
183
- expect_recipe {
184
- public_key "#{repo_path}/blah.pub2" do
185
- source_key_path "#{repo_path}/blah.pub"
186
- format :pem
187
- end
188
- }.to have_updated "public_key[#{repo_path}/blah.pub2]", :create
189
- expect(IO.read("#{repo_path}/blah.pub")).to start_with('ssh-rsa ')
190
- expect("#{repo_path}/blah.pub").to be_public_key_for "#{repo_path}/blah"
191
- end
192
- end
193
- end
194
-
195
- context 'and a public_key resource in pem format' do
196
- it 'the public_key is created' do
197
- expect_recipe {
198
- public_key "#{repo_path}/blah.pub" do
199
- source_key_path "#{repo_path}/blah"
200
- format :pem
201
- end
202
- }.to have_updated "public_key[#{repo_path}/blah.pub]", :create
203
- expect(IO.read("#{repo_path}/blah.pub")).to start_with('-----BEGIN')
204
- expect("#{repo_path}/blah.pub").to be_public_key_for "#{repo_path}/blah"
205
- end
206
- end
207
-
208
- context 'and a public_key resource in der format' do
209
- it 'the public_key is created in openssh format' do
210
- expect_recipe {
211
- public_key "#{repo_path}/blah.pub" do
212
- source_key_path "#{repo_path}/blah"
213
- format :der
214
- end
215
- }.to have_updated "public_key[#{repo_path}/blah.pub]", :create
216
- expect(IO.read("#{repo_path}/blah.pub")).not_to start_with('-----BEGIN')
217
- expect(IO.read("#{repo_path}/blah.pub")).not_to start_with('ssh-rsa')
218
- expect("#{repo_path}/blah.pub").to be_public_key_for "#{repo_path}/blah"
219
- end
220
- end
221
- end
222
-
223
- context 'with a recipe with a private_key in der format' do
224
- it 'the private_key is created' do
225
- expect_recipe {
226
- private_key "#{repo_path}/blah" do
227
- format :der
228
- end
229
- }.to have_updated "private_key[#{repo_path}/blah]", :create
230
- expect(IO.read("#{repo_path}/blah")).not_to start_with('-----BEGIN')
231
- expect(OpenSSL::PKey.read(IO.read("#{repo_path}/blah"))).to be_kind_of(OpenSSL::PKey::RSA)
232
- end
233
- end
234
-
235
- context 'with a private key in der format' do
236
- before :each do
237
- Cheffish::BasicChefClient.converge_block do
238
- private_key "#{repo_path}/blah" do
239
- format :der
240
- end
241
- end
242
- end
243
-
244
- context 'and a public_key' do
245
- it 'the public_key is created in openssh format' do
246
- expect_recipe {
247
- public_key "#{repo_path}/blah.pub" do
248
- source_key_path "#{repo_path}/blah"
249
- end
250
- }.to have_updated "public_key[#{repo_path}/blah.pub]", :create
251
- expect(IO.read("#{repo_path}/blah.pub")).to start_with('ssh-rsa ')
252
- expect("#{repo_path}/blah.pub").to be_public_key_for "#{repo_path}/blah"
253
- end
254
- end
255
- end
256
-
257
- context 'with a recipe with a private_key with a pass_phrase' do
258
- it 'the private_key is created' do
259
- expect_recipe {
260
- private_key "#{repo_path}/blah" do
261
- pass_phrase 'hello'
262
- end
263
- }.to have_updated "private_key[#{repo_path}/blah]", :create
264
- expect(IO.read("#{repo_path}/blah")).to start_with('-----BEGIN')
265
- expect(OpenSSL::PKey.read(IO.read("#{repo_path}/blah"), 'hello')).to be_kind_of(OpenSSL::PKey::RSA)
266
- end
267
- end
268
-
269
- context 'with a private key with a pass phrase' do
270
- before :each do
271
- Cheffish::BasicChefClient.converge_block do
272
- private_key "#{repo_path}/blah" do
273
- pass_phrase 'hello'
274
- end
275
- end
276
- end
277
-
278
- context 'and a private_key that copies it in der format' do
279
- it 'the private_key is copied in der format and is identical' do
280
- expect_recipe {
281
- private_key "#{repo_path}/blah.der" do
282
- source_key_path "#{repo_path}/blah"
283
- source_key_pass_phrase 'hello'
284
- format :der
285
- end
286
- }.to have_updated "private_key[#{repo_path}/blah.der]", :create
287
- key_str = IO.read("#{repo_path}/blah.der")
288
- expect(key_str).not_to start_with('-----BEGIN')
289
- expect(key_str).not_to start_with('ssh-')
290
- expect("#{repo_path}/blah.der").to match_private_key("#{repo_path}/blah", 'hello')
291
- end
292
- end
293
-
294
- context 'and a private_key resource pointing at it without a pass_phrase' do
295
- it 'the run fails with an exception' do
296
- expect {
297
- converge {
298
- private_key "#{repo_path}/blah"
299
- }
300
- }.to raise_error
301
- end
302
- end
303
-
304
- context 'and a private_key resource with no pass phrase and regenerate_if_different' do
305
- it 'the private_key is regenerated' do
306
- expect_recipe {
307
- private_key "#{repo_path}/blah" do
308
- regenerate_if_different true
309
- end
310
- }.to have_updated "private_key[#{repo_path}/blah]", :create
311
- expect(IO.read("#{repo_path}/blah")).to start_with('-----BEGIN')
312
- expect(OpenSSL::PKey.read(IO.read("#{repo_path}/blah"))).to be_kind_of(OpenSSL::PKey::RSA)
313
- end
314
- end
315
-
316
- it 'a private_key resource that copies it from in-memory as a string succeeds' do
317
- expect_recipe {
318
- private_key "#{repo_path}/blah.der" do
319
- source_key IO.read("#{repo_path}/blah")
320
- source_key_pass_phrase 'hello'
321
- format :der
322
- end
323
- }.to have_updated "private_key[#{repo_path}/blah.der]", :create
324
- key_str = IO.read("#{repo_path}/blah.der")
325
- expect(key_str).not_to start_with('-----BEGIN')
326
- expect(key_str).not_to start_with('ssh-')
327
- expect("#{repo_path}/blah.der").to match_private_key("#{repo_path}/blah", 'hello')
328
- end
329
-
330
- context 'and a public_key' do
331
- it 'the public_key is created in openssh format' do
332
- expect_recipe {
333
- public_key "#{repo_path}/blah.pub" do
334
- source_key_path "#{repo_path}/blah"
335
- source_key_pass_phrase 'hello'
336
- end
337
- }.to have_updated "public_key[#{repo_path}/blah.pub]", :create
338
- expect(IO.read("#{repo_path}/blah.pub")).to start_with('ssh-rsa ')
339
- expect("#{repo_path}/blah.pub").to be_public_key_for "#{repo_path}/blah", 'hello'
340
- end
341
- end
342
-
343
- context 'and a public_key derived from the private key in an in-memory string' do
344
- it 'the public_key is created in openssh format' do
345
- expect_recipe {
346
- public_key "#{repo_path}/blah.pub" do
347
- source_key IO.read("#{repo_path}/blah")
348
- source_key_pass_phrase 'hello'
349
- end
350
- }.to have_updated "public_key[#{repo_path}/blah.pub]", :create
351
- expect(IO.read("#{repo_path}/blah.pub")).to start_with('ssh-rsa ')
352
- expect("#{repo_path}/blah.pub").to be_public_key_for "#{repo_path}/blah", 'hello'
353
- end
354
- end
355
- end
356
-
357
- context 'with a recipe with a private_key and public_key_path' do
358
- it 'the private_key and public_key are created' do
359
- expect_recipe {
360
- private_key "#{repo_path}/blah" do
361
- public_key_path "#{repo_path}/blah.pub"
362
- end
363
- }.to have_updated "private_key[#{repo_path}/blah]", :create
364
- expect(IO.read("#{repo_path}/blah")).to start_with('-----BEGIN')
365
- expect(OpenSSL::PKey.read(IO.read("#{repo_path}/blah"))).to be_kind_of(OpenSSL::PKey::RSA)
366
- expect(IO.read("#{repo_path}/blah.pub")).to start_with('ssh-rsa ')
367
- expect("#{repo_path}/blah.pub").to be_public_key_for("#{repo_path}/blah")
368
- end
369
- end
370
-
371
- context 'with a recipe with a private_key and public_key_path and public_key_format' do
372
- it 'the private_key and public_key are created' do
373
- expect_recipe {
374
- private_key "#{repo_path}/blah" do
375
- public_key_path "#{repo_path}/blah.pub.der"
376
- public_key_format :der
377
- end
378
- }.to have_updated "private_key[#{repo_path}/blah]", :create
379
- expect(IO.read("#{repo_path}/blah")).to start_with('-----BEGIN')
380
- expect(OpenSSL::PKey.read(IO.read("#{repo_path}/blah"))).to be_kind_of(OpenSSL::PKey::RSA)
381
- expect(IO.read("#{repo_path}/blah.pub.der")).not_to start_with('ssh-rsa ')
382
- expect("#{repo_path}/blah.pub.der").to be_public_key_for("#{repo_path}/blah")
383
- end
384
- end
385
-
386
- context 'with a recipe with a private_key with path :none' do
387
- it 'the private_key is created' do
388
- got_private_key = nil
389
- expect_recipe {
390
- private_key 'in_memory' do
391
- path :none
392
- after { |resource, private_key| got_private_key = private_key }
393
- end
394
- }.to have_updated "private_key[in_memory]", :create
395
- expect(got_private_key).to be_kind_of(OpenSSL::PKey::RSA)
396
- end
397
- end
398
-
399
- end
1
+ require 'support/spec_support'
2
+ require 'cheffish/rspec/chef_run_support'
3
+ require 'chef/resource/private_key'
4
+ require 'chef/provider/private_key'
5
+ require 'chef/resource/public_key'
6
+ require 'chef/provider/public_key'
7
+ require 'support/key_support'
8
+
9
+ repo_path = Dir.mktmpdir('chef_repo')
10
+
11
+ describe Chef::Resource::PrivateKey do
12
+ extend Cheffish::RSpec::ChefRunSupport
13
+
14
+ before :each do
15
+ FileUtils.remove_entry_secure(repo_path)
16
+ Dir.mkdir(repo_path)
17
+ end
18
+
19
+ context 'with a recipe with a private_key' do
20
+ it 'the private_key is created in pem format' do
21
+ expect_recipe {
22
+ private_key "#{repo_path}/blah"
23
+ }.to have_updated "private_key[#{repo_path}/blah]", :create
24
+ expect(IO.read("#{repo_path}/blah")).to start_with('-----BEGIN')
25
+ expect(OpenSSL::PKey.read(IO.read("#{repo_path}/blah"))).to be_kind_of(OpenSSL::PKey::RSA)
26
+ end
27
+ end
28
+
29
+ context 'with a private_key "blah" resource' do
30
+ before :each do
31
+ Dir.mkdir("#{repo_path}/other_keys")
32
+ Chef::Config.private_key_paths = [ repo_path, "#{repo_path}/other_keys" ]
33
+ end
34
+
35
+ it 'the private key is created in the private_key_write_path' do
36
+ expect_recipe {
37
+ private_key 'blah'
38
+ }.to have_updated "private_key[blah]", :create
39
+ expect(Chef::Config.private_key_write_path).to eq(repo_path)
40
+ expect(File.exist?("#{repo_path}/blah")).to be true
41
+ expect(File.exist?("#{repo_path}/other_keys/blah")).to be false
42
+ expect(OpenSSL::PKey.read(IO.read("#{repo_path}/blah"))).to be_kind_of(OpenSSL::PKey::RSA)
43
+ expect(OpenSSL::PKey.read(Cheffish.get_private_key('blah'))).to be_kind_of(OpenSSL::PKey::RSA)
44
+ end
45
+
46
+ context 'and the private key already exists somewhere not in the write path' do
47
+ before :each do
48
+ recipe { private_key "#{repo_path}/other_keys/blah" }.converge
49
+ end
50
+
51
+ it 'the private expect(key).to not update' do
52
+ expect_recipe {
53
+ private_key 'blah'
54
+ }.not_to have_updated "private_key[blah]", :create
55
+
56
+ expect(File.exist?("#{repo_path}/blah")).to be false
57
+ expect(File.exist?("#{repo_path}/other_keys/blah")).to be true
58
+ end
59
+ end
60
+ end
61
+
62
+ context 'with a private key' do
63
+ before :each do
64
+ Cheffish::BasicChefClient.converge_block do
65
+ private_key "#{repo_path}/blah"
66
+ end
67
+ end
68
+
69
+ context 'and a private_key that copies it in der format' do
70
+ it 'the private_key is copied in der format and is identical' do
71
+ expect_recipe {
72
+ private_key "#{repo_path}/blah.der" do
73
+ source_key_path "#{repo_path}/blah"
74
+ format :der
75
+ end
76
+ }.to have_updated "private_key[#{repo_path}/blah.der]", :create
77
+ key_str = IO.read("#{repo_path}/blah.der")
78
+ expect(key_str).not_to start_with('-----BEGIN')
79
+ expect(key_str).not_to start_with('ssh-')
80
+ expect("#{repo_path}/blah.der").to match_private_key("#{repo_path}/blah")
81
+ end
82
+ end
83
+
84
+ it 'a private_key that copies it from in-memory as a string succeeds' do
85
+ expect_recipe {
86
+ private_key "#{repo_path}/blah.der" do
87
+ source_key IO.read("#{repo_path}/blah")
88
+ format :der
89
+ end
90
+ }.to have_updated "private_key[#{repo_path}/blah.der]", :create
91
+ key_str = IO.read("#{repo_path}/blah.der")
92
+ expect(key_str).not_to start_with('-----BEGIN')
93
+ expect(key_str).not_to start_with('ssh-')
94
+ expect("#{repo_path}/blah.der").to match_private_key("#{repo_path}/blah")
95
+ end
96
+
97
+ it 'a private_key that copies it from in-memory as a key succeeds' do
98
+ key = OpenSSL::PKey.read(IO.read("#{repo_path}/blah"))
99
+ expect_recipe {
100
+ private_key "#{repo_path}/blah.der" do
101
+ source_key key
102
+ format :der
103
+ end
104
+ }.to have_updated "private_key[#{repo_path}/blah.der]", :create
105
+ key_str = IO.read("#{repo_path}/blah.der")
106
+ expect(key_str).not_to start_with('-----BEGIN')
107
+ expect(key_str).not_to start_with('ssh-')
108
+ expect("#{repo_path}/blah.der").to match_private_key("#{repo_path}/blah")
109
+ end
110
+
111
+ context 'and a public_key recipe' do
112
+ it 'the public_key is created' do
113
+ expect_recipe {
114
+ public_key "#{repo_path}/blah.pub" do
115
+ source_key_path "#{repo_path}/blah"
116
+ end
117
+ }.to have_updated "public_key[#{repo_path}/blah.pub]", :create
118
+ expect(IO.read("#{repo_path}/blah.pub")).to start_with('ssh-rsa ')
119
+ expect("#{repo_path}/blah.pub").to be_public_key_for "#{repo_path}/blah"
120
+ end
121
+ end
122
+
123
+ context 'and a public key' do
124
+ before :each do
125
+ Cheffish::BasicChefClient.converge_block do
126
+ public_key "#{repo_path}/blah.pub" do
127
+ source_key_path "#{repo_path}/blah"
128
+ end
129
+ end
130
+ end
131
+
132
+ context 'and public_key resource based off the public key file' do
133
+ it 'the second public_key is created' do
134
+ expect_recipe {
135
+ public_key "#{repo_path}/blah.pub2" do
136
+ source_key_path "#{repo_path}/blah.pub"
137
+ end
138
+ }.to have_updated "public_key[#{repo_path}/blah.pub2]", :create
139
+ expect(IO.read("#{repo_path}/blah.pub")).to start_with('ssh-rsa ')
140
+ expect("#{repo_path}/blah.pub").to be_public_key_for "#{repo_path}/blah"
141
+ end
142
+ end
143
+
144
+ context 'and another public_key based off the first public_key in-memory in a string' do
145
+ it 'the second public_key is created' do
146
+ expect_recipe {
147
+ public_key "#{repo_path}/blah.pub2" do
148
+ source_key IO.read("#{repo_path}/blah.pub")
149
+ end
150
+ }.to have_updated "public_key[#{repo_path}/blah.pub2]", :create
151
+ expect(IO.read("#{repo_path}/blah.pub")).to start_with('ssh-rsa ')
152
+ expect("#{repo_path}/blah.pub").to be_public_key_for "#{repo_path}/blah"
153
+ end
154
+ end
155
+
156
+ it 'and another public_key based off the first public_key in-memory in a key, the second public_key is created' do
157
+ key, format = Cheffish::KeyFormatter.decode(IO.read("#{repo_path}/blah.pub"))
158
+
159
+ expect_recipe {
160
+ public_key "#{repo_path}/blah.pub2" do
161
+ source_key key
162
+ end
163
+ }.to have_updated "public_key[#{repo_path}/blah.pub2]", :create
164
+ expect(IO.read("#{repo_path}/blah.pub")).to start_with('ssh-rsa ')
165
+ expect("#{repo_path}/blah.pub").to be_public_key_for "#{repo_path}/blah"
166
+ end
167
+
168
+ context 'and another public_key in :pem format based off the first public_key' do
169
+ it 'the second public_key is created' do
170
+ expect_recipe {
171
+ public_key "#{repo_path}/blah.pub2" do
172
+ source_key_path "#{repo_path}/blah.pub"
173
+ format :pem
174
+ end
175
+ }.to have_updated "public_key[#{repo_path}/blah.pub2]", :create
176
+ expect(IO.read("#{repo_path}/blah.pub")).to start_with('ssh-rsa ')
177
+ expect("#{repo_path}/blah.pub").to be_public_key_for "#{repo_path}/blah"
178
+ end
179
+ end
180
+
181
+ context 'and another public_key in :der format based off the first public_key' do
182
+ it 'the second public_key is created' do
183
+ expect_recipe {
184
+ public_key "#{repo_path}/blah.pub2" do
185
+ source_key_path "#{repo_path}/blah.pub"
186
+ format :pem
187
+ end
188
+ }.to have_updated "public_key[#{repo_path}/blah.pub2]", :create
189
+ expect(IO.read("#{repo_path}/blah.pub")).to start_with('ssh-rsa ')
190
+ expect("#{repo_path}/blah.pub").to be_public_key_for "#{repo_path}/blah"
191
+ end
192
+ end
193
+ end
194
+
195
+ context 'and a public_key resource in pem format' do
196
+ it 'the public_key is created' do
197
+ expect_recipe {
198
+ public_key "#{repo_path}/blah.pub" do
199
+ source_key_path "#{repo_path}/blah"
200
+ format :pem
201
+ end
202
+ }.to have_updated "public_key[#{repo_path}/blah.pub]", :create
203
+ expect(IO.read("#{repo_path}/blah.pub")).to start_with('-----BEGIN')
204
+ expect("#{repo_path}/blah.pub").to be_public_key_for "#{repo_path}/blah"
205
+ end
206
+ end
207
+
208
+ context 'and a public_key resource in der format' do
209
+ it 'the public_key is created in openssh format' do
210
+ expect_recipe {
211
+ public_key "#{repo_path}/blah.pub" do
212
+ source_key_path "#{repo_path}/blah"
213
+ format :der
214
+ end
215
+ }.to have_updated "public_key[#{repo_path}/blah.pub]", :create
216
+ expect(IO.read("#{repo_path}/blah.pub")).not_to start_with('-----BEGIN')
217
+ expect(IO.read("#{repo_path}/blah.pub")).not_to start_with('ssh-rsa')
218
+ expect("#{repo_path}/blah.pub").to be_public_key_for "#{repo_path}/blah"
219
+ end
220
+ end
221
+ end
222
+
223
+ context 'with a recipe with a private_key in der format' do
224
+ it 'the private_key is created' do
225
+ expect_recipe {
226
+ private_key "#{repo_path}/blah" do
227
+ format :der
228
+ end
229
+ }.to have_updated "private_key[#{repo_path}/blah]", :create
230
+ expect(IO.read("#{repo_path}/blah")).not_to start_with('-----BEGIN')
231
+ expect(OpenSSL::PKey.read(IO.read("#{repo_path}/blah"))).to be_kind_of(OpenSSL::PKey::RSA)
232
+ end
233
+ end
234
+
235
+ context 'with a private key in der format' do
236
+ before :each do
237
+ Cheffish::BasicChefClient.converge_block do
238
+ private_key "#{repo_path}/blah" do
239
+ format :der
240
+ end
241
+ end
242
+ end
243
+
244
+ context 'and a public_key' do
245
+ it 'the public_key is created in openssh format' do
246
+ expect_recipe {
247
+ public_key "#{repo_path}/blah.pub" do
248
+ source_key_path "#{repo_path}/blah"
249
+ end
250
+ }.to have_updated "public_key[#{repo_path}/blah.pub]", :create
251
+ expect(IO.read("#{repo_path}/blah.pub")).to start_with('ssh-rsa ')
252
+ expect("#{repo_path}/blah.pub").to be_public_key_for "#{repo_path}/blah"
253
+ end
254
+ end
255
+ end
256
+
257
+ context 'with a recipe with a private_key with a pass_phrase' do
258
+ it 'the private_key is created' do
259
+ expect_recipe {
260
+ private_key "#{repo_path}/blah" do
261
+ pass_phrase 'hello'
262
+ end
263
+ }.to have_updated "private_key[#{repo_path}/blah]", :create
264
+ expect(IO.read("#{repo_path}/blah")).to start_with('-----BEGIN')
265
+ expect(OpenSSL::PKey.read(IO.read("#{repo_path}/blah"), 'hello')).to be_kind_of(OpenSSL::PKey::RSA)
266
+ end
267
+ end
268
+
269
+ context 'with a private key with a pass phrase' do
270
+ before :each do
271
+ Cheffish::BasicChefClient.converge_block do
272
+ private_key "#{repo_path}/blah" do
273
+ pass_phrase 'hello'
274
+ end
275
+ end
276
+ end
277
+
278
+ context 'and a private_key that copies it in der format' do
279
+ it 'the private_key is copied in der format and is identical' do
280
+ expect_recipe {
281
+ private_key "#{repo_path}/blah.der" do
282
+ source_key_path "#{repo_path}/blah"
283
+ source_key_pass_phrase 'hello'
284
+ format :der
285
+ end
286
+ }.to have_updated "private_key[#{repo_path}/blah.der]", :create
287
+ key_str = IO.read("#{repo_path}/blah.der")
288
+ expect(key_str).not_to start_with('-----BEGIN')
289
+ expect(key_str).not_to start_with('ssh-')
290
+ expect("#{repo_path}/blah.der").to match_private_key("#{repo_path}/blah", 'hello')
291
+ end
292
+ end
293
+
294
+ context 'and a private_key resource pointing at it without a pass_phrase' do
295
+ it 'the run fails with an exception' do
296
+ expect {
297
+ converge {
298
+ private_key "#{repo_path}/blah"
299
+ }
300
+ }.to raise_error /missing pass phrase?/
301
+ end
302
+ end
303
+
304
+ context 'and a private_key resource with no pass phrase and regenerate_if_different' do
305
+ it 'the private_key is regenerated' do
306
+ expect_recipe {
307
+ private_key "#{repo_path}/blah" do
308
+ regenerate_if_different true
309
+ end
310
+ }.to have_updated "private_key[#{repo_path}/blah]", :create
311
+ expect(IO.read("#{repo_path}/blah")).to start_with('-----BEGIN')
312
+ expect(OpenSSL::PKey.read(IO.read("#{repo_path}/blah"))).to be_kind_of(OpenSSL::PKey::RSA)
313
+ end
314
+ end
315
+
316
+ it 'a private_key resource that copies it from in-memory as a string succeeds' do
317
+ expect_recipe {
318
+ private_key "#{repo_path}/blah.der" do
319
+ source_key IO.read("#{repo_path}/blah")
320
+ source_key_pass_phrase 'hello'
321
+ format :der
322
+ end
323
+ }.to have_updated "private_key[#{repo_path}/blah.der]", :create
324
+ key_str = IO.read("#{repo_path}/blah.der")
325
+ expect(key_str).not_to start_with('-----BEGIN')
326
+ expect(key_str).not_to start_with('ssh-')
327
+ expect("#{repo_path}/blah.der").to match_private_key("#{repo_path}/blah", 'hello')
328
+ end
329
+
330
+ context 'and a public_key' do
331
+ it 'the public_key is created in openssh format' do
332
+ expect_recipe {
333
+ public_key "#{repo_path}/blah.pub" do
334
+ source_key_path "#{repo_path}/blah"
335
+ source_key_pass_phrase 'hello'
336
+ end
337
+ }.to have_updated "public_key[#{repo_path}/blah.pub]", :create
338
+ expect(IO.read("#{repo_path}/blah.pub")).to start_with('ssh-rsa ')
339
+ expect("#{repo_path}/blah.pub").to be_public_key_for "#{repo_path}/blah", 'hello'
340
+ end
341
+ end
342
+
343
+ context 'and a public_key derived from the private key in an in-memory string' do
344
+ it 'the public_key is created in openssh format' do
345
+ expect_recipe {
346
+ public_key "#{repo_path}/blah.pub" do
347
+ source_key IO.read("#{repo_path}/blah")
348
+ source_key_pass_phrase 'hello'
349
+ end
350
+ }.to have_updated "public_key[#{repo_path}/blah.pub]", :create
351
+ expect(IO.read("#{repo_path}/blah.pub")).to start_with('ssh-rsa ')
352
+ expect("#{repo_path}/blah.pub").to be_public_key_for "#{repo_path}/blah", 'hello'
353
+ end
354
+ end
355
+ end
356
+
357
+ context 'with a recipe with a private_key and public_key_path' do
358
+ it 'the private_key and public_key are created' do
359
+ expect_recipe {
360
+ private_key "#{repo_path}/blah" do
361
+ public_key_path "#{repo_path}/blah.pub"
362
+ end
363
+ }.to have_updated "private_key[#{repo_path}/blah]", :create
364
+ expect(IO.read("#{repo_path}/blah")).to start_with('-----BEGIN')
365
+ expect(OpenSSL::PKey.read(IO.read("#{repo_path}/blah"))).to be_kind_of(OpenSSL::PKey::RSA)
366
+ expect(IO.read("#{repo_path}/blah.pub")).to start_with('ssh-rsa ')
367
+ expect("#{repo_path}/blah.pub").to be_public_key_for("#{repo_path}/blah")
368
+ end
369
+ end
370
+
371
+ context 'with a recipe with a private_key and public_key_path and public_key_format' do
372
+ it 'the private_key and public_key are created' do
373
+ expect_recipe {
374
+ private_key "#{repo_path}/blah" do
375
+ public_key_path "#{repo_path}/blah.pub.der"
376
+ public_key_format :der
377
+ end
378
+ }.to have_updated "private_key[#{repo_path}/blah]", :create
379
+ expect(IO.read("#{repo_path}/blah")).to start_with('-----BEGIN')
380
+ expect(OpenSSL::PKey.read(IO.read("#{repo_path}/blah"))).to be_kind_of(OpenSSL::PKey::RSA)
381
+ expect(IO.read("#{repo_path}/blah.pub.der")).not_to start_with('ssh-rsa ')
382
+ expect("#{repo_path}/blah.pub.der").to be_public_key_for("#{repo_path}/blah")
383
+ end
384
+ end
385
+
386
+ context 'with a recipe with a private_key with path :none' do
387
+ it 'the private_key is created' do
388
+ got_private_key = nil
389
+ expect_recipe {
390
+ private_key 'in_memory' do
391
+ path :none
392
+ after { |resource, private_key| got_private_key = private_key }
393
+ end
394
+ }.to have_updated "private_key[in_memory]", :create
395
+ expect(got_private_key).to be_kind_of(OpenSSL::PKey::RSA)
396
+ end
397
+ end
398
+
399
+ end