cred_hubble 0.0.1.pre → 0.1.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +7 -1
  4. data/.travis.yml +3 -1
  5. data/README.md +353 -13
  6. data/cred_hubble.gemspec +3 -0
  7. data/lib/cred_hubble.rb +3 -2
  8. data/lib/cred_hubble/client.rb +119 -13
  9. data/lib/cred_hubble/http/client.rb +39 -4
  10. data/lib/cred_hubble/resources/certificate_credential.rb +25 -0
  11. data/lib/cred_hubble/resources/credential.rb +32 -0
  12. data/lib/cred_hubble/resources/credential_collection.rb +21 -0
  13. data/lib/cred_hubble/resources/credential_factory.rb +41 -0
  14. data/lib/cred_hubble/resources/immutable_resource.rb +2 -2
  15. data/lib/cred_hubble/resources/json_credential.rb +13 -0
  16. data/lib/cred_hubble/resources/password_credential.rb +13 -0
  17. data/lib/cred_hubble/resources/permission.rb +10 -0
  18. data/lib/cred_hubble/resources/permission_collection.rb +21 -0
  19. data/lib/cred_hubble/resources/resource.rb +10 -0
  20. data/lib/cred_hubble/resources/resources.rb +15 -0
  21. data/lib/cred_hubble/resources/{base_resource.rb → rest_resource.rb} +6 -2
  22. data/lib/cred_hubble/resources/rsa_credential.rb +24 -0
  23. data/lib/cred_hubble/resources/ssh_credential.rb +39 -0
  24. data/lib/cred_hubble/resources/user_credential.rb +39 -0
  25. data/lib/cred_hubble/resources/value_credential.rb +13 -0
  26. data/lib/cred_hubble/version.rb +1 -1
  27. data/spec/cred_hubble/client_spec.rb +487 -3
  28. data/spec/cred_hubble/http/client_spec.rb +347 -53
  29. data/spec/cred_hubble/resources/certificate_credential_spec.rb +49 -0
  30. data/spec/cred_hubble/resources/credential_collection_spec.rb +59 -0
  31. data/spec/cred_hubble/resources/credential_factory_spec.rb +154 -0
  32. data/spec/cred_hubble/resources/credential_spec.rb +10 -0
  33. data/spec/cred_hubble/resources/json_credential_spec.rb +52 -0
  34. data/spec/cred_hubble/resources/password_credential_spec.rb +41 -0
  35. data/spec/cred_hubble/resources/permission_collection_spec.rb +87 -0
  36. data/spec/cred_hubble/resources/permission_spec.rb +36 -0
  37. data/spec/cred_hubble/resources/rsa_credential_spec.rb +46 -0
  38. data/spec/cred_hubble/resources/ssh_credential_spec.rb +73 -0
  39. data/spec/cred_hubble/resources/user_credential_spec.rb +72 -0
  40. data/spec/cred_hubble/resources/value_credential_spec.rb +42 -0
  41. data/spec/support/shared_examples/resource_examples.rb +49 -0
  42. metadata +57 -5
@@ -1,21 +1,25 @@
1
1
  require 'cred_hubble/exceptions/error'
2
2
  require 'json'
3
+ require 'virtus'
3
4
 
4
5
  module CredHubble
5
6
  module Resources
6
7
  class JsonParseError < CredHubble::Exceptions::Error; end
7
8
 
8
- class BaseResource
9
+ class RestResource
9
10
  def self.from_json(json)
10
11
  new(parse_json(json))
11
12
  end
12
13
 
14
+ def to_json(options = {})
15
+ attributes.to_json(options)
16
+ end
17
+
13
18
  def self.parse_json(raw_json)
14
19
  JSON.parse(raw_json)
15
20
  rescue JSON::ParserError => e
16
21
  raise CredHubble::Resources::JsonParseError, e.message
17
22
  end
18
-
19
23
  private_class_method :parse_json
20
24
  end
21
25
  end
@@ -0,0 +1,24 @@
1
+ require 'cred_hubble/resources/credential'
2
+
3
+ module CredHubble
4
+ module Resources
5
+ class RsaValue
6
+ include Virtus.model
7
+
8
+ attribute :public_key, String
9
+ attribute :private_key, String
10
+
11
+ def to_json(options = {})
12
+ attributes.to_json(options)
13
+ end
14
+ end
15
+
16
+ class RsaCredential < Credential
17
+ attribute :value, RsaValue
18
+
19
+ def type
20
+ Credential::RSA_TYPE
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,39 @@
1
+ require 'cred_hubble/resources/credential'
2
+
3
+ module CredHubble
4
+ module Resources
5
+ class SshValue
6
+ include Virtus.model
7
+
8
+ attribute :public_key, String
9
+ attribute :private_key, String
10
+ attribute :public_key_fingerprint, String
11
+
12
+ def to_json(options = {})
13
+ attributes.to_json(options)
14
+ end
15
+
16
+ def attributes_for_put
17
+ attributes.delete_if { |k, _| immutable_attributes.include?(k) }
18
+ end
19
+
20
+ private
21
+
22
+ def immutable_attributes
23
+ [:public_key_fingerprint]
24
+ end
25
+ end
26
+
27
+ class SshCredential < Credential
28
+ attribute :value, SshValue
29
+
30
+ def type
31
+ Credential::SSH_TYPE
32
+ end
33
+
34
+ def attributes_for_put
35
+ super.merge(value: value && value.attributes_for_put)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,39 @@
1
+ require 'cred_hubble/resources/credential'
2
+
3
+ module CredHubble
4
+ module Resources
5
+ class UserValue
6
+ include Virtus.model
7
+
8
+ attribute :username, String
9
+ attribute :password, String
10
+ attribute :password_hash, String
11
+
12
+ def to_json(options = {})
13
+ attributes.to_json(options)
14
+ end
15
+
16
+ def attributes_for_put
17
+ attributes.delete_if { |k, _| immutable_attributes.include?(k) }
18
+ end
19
+
20
+ private
21
+
22
+ def immutable_attributes
23
+ [:password_hash]
24
+ end
25
+ end
26
+
27
+ class UserCredential < Credential
28
+ attribute :value, UserValue
29
+
30
+ def type
31
+ Credential::USER_TYPE
32
+ end
33
+
34
+ def attributes_for_put
35
+ super.merge(value: value && value.attributes_for_put)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,13 @@
1
+ require 'cred_hubble/resources/credential'
2
+
3
+ module CredHubble
4
+ module Resources
5
+ class ValueCredential < Credential
6
+ attribute :value, String
7
+
8
+ def type
9
+ Credential::VALUE_TYPE
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,3 +1,3 @@
1
1
  module CredHubble
2
- VERSION = '0.0.1.pre'.freeze
2
+ VERSION = '0.1.0.pre'.freeze
3
3
  end
@@ -1,14 +1,102 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  RSpec.describe CredHubble::Client do
4
+ let(:response_body) { '{}' }
5
+ let(:response_status) { 200 }
4
6
  let(:mock_http_client) { instance_double(CredHubble::Http::Client) }
7
+ let(:mock_response) do
8
+ instance_double(Faraday::Response, status: response_status, body: response_body, success?: true)
9
+ end
10
+
5
11
  let(:credhub_url) { 'https://credhub.cloudfoundry.com:8845' }
6
- let(:mock_response) { instance_double(Faraday::Response, body: response_body) }
7
- subject { CredHubble::Client.new(credhub_url) }
12
+ let(:credhub_host) { 'credhub.cloudfoundry.com' }
13
+ let(:credhub_port) { '8845' }
14
+ let(:ca_path) { '/custom/certs/ca.crt' }
15
+ subject { CredHubble::Client.new(host: credhub_host, port: credhub_port) }
8
16
 
9
17
  before do
10
- allow(subject).to receive(:http_client).and_return(mock_http_client)
18
+ allow(CredHubble::Http::Client).to receive(:new).and_return(mock_http_client)
11
19
  allow(mock_http_client).to receive(:get).and_return(mock_response)
20
+ allow(mock_http_client).to receive(:put).and_return(mock_response)
21
+ allow(mock_http_client).to receive(:post).and_return(mock_response)
22
+ allow(mock_http_client).to receive(:delete).and_return(mock_response)
23
+ end
24
+
25
+ describe '.new_from_token_auth' do
26
+ let(:token) { 'example-token-string' }
27
+
28
+ it 'instantiates an instance of the client with an oAuth2 bearer token' do
29
+ client = CredHubble::Client.new_from_token_auth(
30
+ host: credhub_host,
31
+ port: credhub_port,
32
+ auth_header_token: token
33
+ )
34
+ expect(client.send(:credhub_url)).to eq(credhub_url)
35
+ expect(client.send(:auth_header_token)).to eq(token)
36
+ end
37
+
38
+ it 'allows the user to optionally supply a file path for the CredHub CA cert' do
39
+ client = CredHubble::Client.new_from_token_auth(
40
+ host: credhub_host,
41
+ port: credhub_port,
42
+ auth_header_token: token,
43
+ ca_path: ca_path
44
+ )
45
+
46
+ expect(client.send(:credhub_url)).to eq(credhub_url)
47
+ expect(client.send(:auth_header_token)).to eq(token)
48
+ expect(client.send(:ca_path)).to eq(ca_path)
49
+ end
50
+ end
51
+
52
+ describe '.new_from_mtls_auth' do
53
+ let(:client_cert_path) { '/mutual/tls/certs/example-cert.crt' }
54
+ let(:client_key_path) { '/mutual/tls/keys/rsa.pem' }
55
+ let(:mock_cert_file) { instance_double(File) }
56
+ let(:mock_key_file) { instance_double(File) }
57
+ let(:mock_cert) { instance_double(OpenSSL::X509::Certificate) }
58
+ let(:mock_key) { instance_double(OpenSSL::PKey::RSA) }
59
+
60
+ before do
61
+ allow(File).to receive(:read).and_call_original
62
+ allow(File).to receive(:read).with(client_cert_path).and_return(mock_cert_file)
63
+ allow(File).to receive(:read).with(client_key_path).and_return(mock_key_file)
64
+
65
+ allow(OpenSSL::X509::Certificate).to receive(:new).with(mock_cert_file).and_return(mock_cert)
66
+ allow(OpenSSL::PKey::RSA).to receive(:new).with(mock_key_file).and_return(mock_key)
67
+ end
68
+
69
+ it 'instantiates an instance of the client with a client cert and client key' do
70
+ client = CredHubble::Client.new_from_mtls_auth(
71
+ host: credhub_host,
72
+ port: credhub_port,
73
+ client_cert_path: client_cert_path,
74
+ client_key_path: client_key_path
75
+ )
76
+
77
+ expect(client.send(:credhub_url)).to eq(credhub_url)
78
+ expect(client.send(:client_cert_path)).to eq(client_cert_path)
79
+ expect(client.send(:client_key_path)).to eq(client_key_path)
80
+ expect(client.send(:client_cert)).to eq(mock_cert)
81
+ expect(client.send(:client_key)).to eq(mock_key)
82
+ end
83
+
84
+ it 'allows the user to optionally supply a file path for the CredHub CA cert' do
85
+ client = CredHubble::Client.new_from_mtls_auth(
86
+ host: credhub_host,
87
+ port: credhub_port,
88
+ ca_path: ca_path,
89
+ client_cert_path: client_cert_path,
90
+ client_key_path: client_key_path
91
+ )
92
+
93
+ expect(client.send(:credhub_url)).to eq(credhub_url)
94
+ expect(client.send(:ca_path)).to eq(ca_path)
95
+ expect(client.send(:client_cert_path)).to eq(client_cert_path)
96
+ expect(client.send(:client_key_path)).to eq(client_key_path)
97
+ expect(client.send(:client_cert)).to eq(mock_cert)
98
+ expect(client.send(:client_key)).to eq(mock_key)
99
+ end
12
100
  end
13
101
 
14
102
  describe '#info' do
@@ -49,4 +137,400 @@ RSpec.describe CredHubble::Client do
49
137
  expect(health.status).to eq('UP')
50
138
  end
51
139
  end
140
+
141
+ describe '#credential_by_id' do
142
+ let(:response_body) do
143
+ '{
144
+ "id": "15811465-8538-460d-9682-5514d44439fd",
145
+ "name": "/load-balancer-tls-cert",
146
+ "type": "certificate",
147
+ "value": {
148
+ "ca": "-----BEGIN CERTIFICATE-----\n... CA CERT ...\n-----END CERTIFICATE-----",
149
+ "certificate": "-----BEGIN CERTIFICATE-----\n... CERTIFICATE ...\n-----END CERTIFICATE-----",
150
+ "private_key": "-----BEGIN RSA PRIVATE KEY-----\n... RSA PRIVATE KEY ...\n-----END RSA PRIVATE KEY-----"
151
+ },
152
+ "version_created_at": "1990-01-05T01:01:01Z"
153
+ }'
154
+ end
155
+
156
+ it 'makes a request to the /api/v1/data endpoint for the given credential id' do
157
+ subject.credential_by_id('cdbb371a-cc03-4a6f-aa21-c6461d66ed96')
158
+ expect(mock_http_client).to have_received(:get).with('/api/v1/data/cdbb371a-cc03-4a6f-aa21-c6461d66ed96')
159
+ end
160
+
161
+ it 'returns a Credential resource' do
162
+ credential = subject.credential_by_id('cdbb371a-cc03-4a6f-aa21-c6461d66ed96')
163
+ expect(credential).to be_a(CredHubble::Resources::CertificateCredential)
164
+ expect(credential.name).to eq('/load-balancer-tls-cert')
165
+ expect(credential.version_created_at).to eq('1990-01-05T01:01:01Z')
166
+ end
167
+ end
168
+
169
+ describe '#credentials_by_name' do
170
+ let(:response_body) do
171
+ '{
172
+ "data":[
173
+ {
174
+ "type":"password",
175
+ "version_created_at":"2017-10-03T04:12:21Z",
176
+ "id":"5298e0e4-c3f5-4c73-a156-9ffce4c137f5",
177
+ "name":"/sunday-clothes-creds",
178
+ "value":"Put on your Sunday clothes there\'s lots of world out there"
179
+ },
180
+ {
181
+ "type":"password",
182
+ "version_created_at":"2017-10-03T04:12:19Z",
183
+ "id":"6980ec59-c7e6-449a-b525-298648cfe6a7",
184
+ "name":"/sunday-clothes-creds",
185
+ "value":"Get out the brilliantine and dime cigars"
186
+ },
187
+ {
188
+ "type":"password",
189
+ "version_created_at":"2017-10-02T01:56:54Z",
190
+ "id":"3e709d6e-585c-4526-ac0d-fe99316f2255",
191
+ "name":"/sunday-clothes-creds",
192
+ "value":"We\'re gonna find adventure in the evening air"
193
+ }
194
+ ]
195
+ }'
196
+ end
197
+
198
+ it 'makes a request to the /api/v1/data endpoint with the name as a query parameter' do
199
+ subject.credentials_by_name('/sunday-clothes-creds')
200
+ expect(mock_http_client).to have_received(:get).with('/api/v1/data?name=%2Fsunday-clothes-creds')
201
+ end
202
+
203
+ it 'includes optional current and version parameters when provided' do
204
+ subject.credentials_by_name('/sunday-clothes-creds', current: false, versions: 100)
205
+ expect(mock_http_client).to have_received(:get)
206
+ .with('/api/v1/data?name=%2Fsunday-clothes-creds&current=false&versions=100')
207
+ end
208
+
209
+ it 'returns a CredentialCollection' do
210
+ credentials = subject.credentials_by_name('/sunday-clothes-creds')
211
+ expect(credentials).to all(be_a(CredHubble::Resources::PasswordCredential))
212
+ expect(credentials.map(&:id)).to match_array(
213
+ %w[
214
+ 5298e0e4-c3f5-4c73-a156-9ffce4c137f5
215
+ 6980ec59-c7e6-449a-b525-298648cfe6a7
216
+ 3e709d6e-585c-4526-ac0d-fe99316f2255
217
+ ]
218
+ )
219
+ end
220
+ end
221
+
222
+ describe '#permissions_by_credential_name' do
223
+ let(:response_body) do
224
+ '{
225
+ "credential_name": "/uaa-client-creds",
226
+ "permissions":[
227
+ {
228
+ "actor": "mtls-app:5532f504-bb27-43e1-94e9-bad794238f17",
229
+ "operations": [
230
+ "read",
231
+ "write",
232
+ "delete",
233
+ "read_acl",
234
+ "write_acl"
235
+ ]
236
+ },
237
+ {
238
+ "actor": "uaa-user:b2449249-5b51-4893-ab76-648763653c38",
239
+ "operations": [
240
+ "read",
241
+ "write",
242
+ "delete",
243
+ "read_acl",
244
+ "write_acl"
245
+ ]
246
+ }
247
+ ]
248
+ }'
249
+ end
250
+
251
+ it 'makes a request to the /api/v1/permissions endpoint with the credential_name as a query parameter' do
252
+ subject.permissions_by_credential_name('/uaa-client-creds')
253
+ expect(mock_http_client).to have_received(:get).with('/api/v1/permissions?credential_name=%2Fuaa-client-creds')
254
+ end
255
+
256
+ it 'returns a PermissionCollection' do
257
+ permissions = subject.permissions_by_credential_name('/uaa-client-creds')
258
+ expect(permissions).to all(be_a(CredHubble::Resources::Permission))
259
+ expect(permissions.map(&:actor)).to match_array(
260
+ %w[
261
+ mtls-app:5532f504-bb27-43e1-94e9-bad794238f17
262
+ uaa-user:b2449249-5b51-4893-ab76-648763653c38
263
+ ]
264
+ )
265
+ end
266
+ end
267
+
268
+ describe '#put_credential' do
269
+ let(:new_credential) do
270
+ CredHubble::Resources::CertificateCredential.new(
271
+ name: '/load-balancer-tls-cert',
272
+ value: {
273
+ ca: "-----BEGIN CERTIFICATE-----\n... CA CERT ...\n-----END CERTIFICATE-----",
274
+ certificate: "-----BEGIN CERTIFICATE-----\n... CERTIFICATE ...\n-----END CERTIFICATE-----",
275
+ private_key: "-----BEGIN RSA PRIVATE KEY-----\n... RSA PRIVATE KEY ...\n-----END RSA PRIVATE KEY-----"
276
+ }
277
+ )
278
+ end
279
+ let(:response_body) do
280
+ '{
281
+ "id": "15811465-8538-460d-9682-5514d44439fd",
282
+ "name": "/load-balancer-tls-cert",
283
+ "type": "certificate",
284
+ "value": {
285
+ "ca": "-----BEGIN CERTIFICATE-----\n... CA CERT ...\n-----END CERTIFICATE-----",
286
+ "certificate": "-----BEGIN CERTIFICATE-----\n... CERTIFICATE ...\n-----END CERTIFICATE-----",
287
+ "private_key": "-----BEGIN RSA PRIVATE KEY-----\n... RSA PRIVATE KEY ...\n-----END RSA PRIVATE KEY-----"
288
+ },
289
+ "version_created_at": "1990-01-05T01:01:01Z"
290
+ }'
291
+ end
292
+
293
+ it 'makes a PUT request to the /api/v1/data endpoint with the serialized credential' do
294
+ subject.put_credential(new_credential)
295
+ expect(mock_http_client).to have_received(:put).with('/api/v1/data', new_credential.attributes_for_put.to_json)
296
+ end
297
+
298
+ it 'accepts an optional overwrite parameter' do
299
+ subject.put_credential(new_credential, overwrite: true)
300
+ expect(mock_http_client)
301
+ .to have_received(:put).with('/api/v1/data', new_credential.attributes_for_put.merge(overwrite: true).to_json)
302
+ end
303
+
304
+ describe 'additional_permissions parameter' do
305
+ let(:permission_one) do
306
+ CredHubble::Resources::Permission.new(
307
+ actor: 'uaa-user:18f64563-bcfe-4c88-bf73-05c9ad3654c8',
308
+ operations: %w[write delete]
309
+ )
310
+ end
311
+ let(:permission_two) do
312
+ CredHubble::Resources::Permission.new(
313
+ actor: 'uaa-user:82f8ff1a-fcf8-4221-8d6b-0a1d579b6e47',
314
+ operations: %w[write read]
315
+ )
316
+ end
317
+ let(:expected_request_body) do
318
+ JSON.parse('{
319
+ "name": "/load-balancer-tls-cert",
320
+ "type": "certificate",
321
+ "value": {
322
+ "ca": "-----BEGIN CERTIFICATE-----\n... CA CERT ...\n-----END CERTIFICATE-----",
323
+ "certificate": "-----BEGIN CERTIFICATE-----\n... CERTIFICATE ...\n-----END CERTIFICATE-----",
324
+ "private_key": "-----BEGIN RSA PRIVATE KEY-----\n... RSA PRIVATE KEY ...\n-----END RSA PRIVATE KEY-----"
325
+ },
326
+ "additional_permissions": [
327
+ {
328
+ "actor": "uaa-user:18f64563-bcfe-4c88-bf73-05c9ad3654c8",
329
+ "operations": [
330
+ "write",
331
+ "delete"
332
+ ]
333
+ },
334
+ {
335
+ "actor": "uaa-user:82f8ff1a-fcf8-4221-8d6b-0a1d579b6e47",
336
+ "operations": [
337
+ "write",
338
+ "read"
339
+ ]
340
+ }
341
+ ]
342
+ }').to_json
343
+ end
344
+
345
+ it 'works with a PermissionCollection' do
346
+ permissions = CredHubble::Resources::PermissionCollection.new(permissions: [permission_one, permission_two])
347
+ subject.put_credential(new_credential, additional_permissions: permissions)
348
+ expect(mock_http_client).to have_received(:put)
349
+ .with('/api/v1/data', expected_request_body)
350
+ end
351
+
352
+ it 'works with a simple array of Permission objects' do
353
+ permissions = [permission_one, permission_two]
354
+ subject.put_credential(new_credential, additional_permissions: permissions)
355
+ expect(mock_http_client).to have_received(:put)
356
+ .with('/api/v1/data', expected_request_body)
357
+ end
358
+ end
359
+
360
+ it 'returns a Credential resource' do
361
+ credential = subject.put_credential(new_credential)
362
+ expect(credential).to be_a(CredHubble::Resources::CertificateCredential)
363
+ expect(credential.name).to eq('/load-balancer-tls-cert')
364
+ expect(credential.version_created_at).to eq('1990-01-05T01:01:01Z')
365
+ end
366
+ end
367
+
368
+ describe '#interpolate_credentials' do
369
+ let(:vcap_services_json) do
370
+ '{
371
+ "grid-config":[
372
+ {
373
+ "credentials":{
374
+ "credhub-ref":"/grid-config/users/kflynn"
375
+ },
376
+ "label":"grid-config",
377
+ "name":"config-server",
378
+ "plan":"digital-frontier",
379
+ "provider":null,
380
+ "syslog_drain_url":null,
381
+ "tags":[
382
+ "configuration",
383
+ "biodigital-jazz"
384
+ ],
385
+ "volume_mounts":[]
386
+ }
387
+ ],
388
+ "encomSQL":[
389
+ {
390
+ "credentials":{
391
+ "credhub-ref":"/encomSQL/db/users/63f7b900-982f-4f20-9213-6d270c3c58ea"
392
+ },
393
+ "label":"encom-db",
394
+ "name":"encom-enterprise-db",
395
+ "plan":"enterprise",
396
+ "provider":null,
397
+ "syslog_drain_url":null,
398
+ "tags":[
399
+ "database",
400
+ "sql"
401
+ ],
402
+ "volume_mounts":[]
403
+ }
404
+ ]
405
+ }'
406
+ end
407
+ let(:response_body) do
408
+ '{
409
+ "grid-config":[
410
+ {
411
+ "credentials":{
412
+ "username":"kflynn",
413
+ "password":"FlynnLives"
414
+ },
415
+ "label":"grid-config",
416
+ "name":"config-server",
417
+ "plan":"digital-frontier",
418
+ "provider":null,
419
+ "syslog_drain_url":null,
420
+ "tags":[
421
+ "configuration",
422
+ "biodigital-jazz"
423
+ ],
424
+ "volume_mounts":[]
425
+ }
426
+ ],
427
+ "encomSQL":[
428
+ {
429
+ "credentials":{
430
+ "username":"grid-db-user",
431
+ "password":"p4ssw0rd"
432
+ },
433
+ "label":"encom-db",
434
+ "name":"encom-enterprise-db",
435
+ "plan":"enterprise",
436
+ "provider":null,
437
+ "syslog_drain_url":null,
438
+ "tags":[
439
+ "database",
440
+ "sql"
441
+ ],
442
+ "volume_mounts":[]
443
+ }
444
+ ]
445
+ }'
446
+ end
447
+
448
+ it 'makes a POST request to the /api/v1/interpolate endpoint with the provided json' do
449
+ subject.interpolate_credentials(vcap_services_json)
450
+ expect(mock_http_client).to have_received(:post).with('/api/v1/interpolate', vcap_services_json)
451
+ end
452
+
453
+ it 'returns JSON with credhub-ref credentials populated' do
454
+ expect(subject.interpolate_credentials(vcap_services_json)).to eq(response_body)
455
+ end
456
+ end
457
+
458
+ describe '#delete_credential_by_name' do
459
+ let(:response_body) { '' }
460
+ let(:response_status) { 204 }
461
+
462
+ it 'makes a DELETE request to the /api/v1/data endpoint with the name as a query parameter' do
463
+ subject.delete_credential_by_name('/outdated-credential')
464
+ expect(mock_http_client).to have_received(:delete).with('/api/v1/data?name=%2Foutdated-credential')
465
+ end
466
+
467
+ it 'returns true if the delete request was a success' do
468
+ expect(subject.delete_credential_by_name('/outdated-credential')).to be true
469
+ end
470
+ end
471
+
472
+ describe '#add_permissions' do
473
+ let(:permission_collection) { CredHubble::Resources::PermissionCollection.from_json(response_body) }
474
+ let(:response_body) do
475
+ '{
476
+ "credential_name": "/uaa-client-creds",
477
+ "permissions":[
478
+ {
479
+ "actor": "mtls-app:5532f504-bb27-43e1-94e9-bad794238f17",
480
+ "operations": [
481
+ "read",
482
+ "write",
483
+ "delete",
484
+ "read_acl",
485
+ "write_acl"
486
+ ]
487
+ },
488
+ {
489
+ "actor": "uaa-user:b2449249-5b51-4893-ab76-648763653c38",
490
+ "operations": [
491
+ "read",
492
+ "write",
493
+ "delete",
494
+ "read_acl",
495
+ "write_acl"
496
+ ]
497
+ }
498
+ ]
499
+ }'
500
+ end
501
+
502
+ it 'makes a POST request to /api/v1/permissions with a serialized PermissionCollection' do
503
+ subject.add_permissions(permission_collection)
504
+ expect(mock_http_client).to have_received(:post).with('/api/v1/permissions', permission_collection.to_json)
505
+ end
506
+
507
+ it 'returns a PermissionCollection' do
508
+ permissions = subject.add_permissions(permission_collection)
509
+ expect(permissions).to all(be_a(CredHubble::Resources::Permission))
510
+ expect(permissions.map(&:actor)).to match_array(
511
+ %w[
512
+ mtls-app:5532f504-bb27-43e1-94e9-bad794238f17
513
+ uaa-user:b2449249-5b51-4893-ab76-648763653c38
514
+ ]
515
+ )
516
+ end
517
+ end
518
+
519
+ describe '#delete_permissions' do
520
+ let(:response_body) { '' }
521
+ let(:response_status) { 204 }
522
+
523
+ it 'makes a DELETE request to the /api/v1/data endpoint with the name as a query parameter' do
524
+ subject.delete_permissions('/some-credential', 'mtls-app:f3a7e791-4c61-4502-8a8c-cd8a4595641c')
525
+ expect(mock_http_client).to have_received(:delete).with(
526
+ '/api/v1/permissions?credential_name=%2Fsome-credential&actor=mtls-app%3Af3a7e791-4c61-4502-8a8c-cd8a4595641c'
527
+ )
528
+ end
529
+
530
+ it 'returns true if the delete request was a success' do
531
+ expect(
532
+ subject.delete_permissions('/some-credential', 'mtls-app:f3a7e791-4c61-4502-8a8c-cd8a4595641c')
533
+ ).to be true
534
+ end
535
+ end
52
536
  end