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