cred_hubble 0.0.1.pre → 0.1.0.pre

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.
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