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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +7 -1
- data/.travis.yml +3 -1
- data/README.md +353 -13
- data/cred_hubble.gemspec +3 -0
- data/lib/cred_hubble.rb +3 -2
- data/lib/cred_hubble/client.rb +119 -13
- data/lib/cred_hubble/http/client.rb +39 -4
- data/lib/cred_hubble/resources/certificate_credential.rb +25 -0
- data/lib/cred_hubble/resources/credential.rb +32 -0
- data/lib/cred_hubble/resources/credential_collection.rb +21 -0
- data/lib/cred_hubble/resources/credential_factory.rb +41 -0
- data/lib/cred_hubble/resources/immutable_resource.rb +2 -2
- data/lib/cred_hubble/resources/json_credential.rb +13 -0
- data/lib/cred_hubble/resources/password_credential.rb +13 -0
- data/lib/cred_hubble/resources/permission.rb +10 -0
- data/lib/cred_hubble/resources/permission_collection.rb +21 -0
- data/lib/cred_hubble/resources/resource.rb +10 -0
- data/lib/cred_hubble/resources/resources.rb +15 -0
- data/lib/cred_hubble/resources/{base_resource.rb → rest_resource.rb} +6 -2
- data/lib/cred_hubble/resources/rsa_credential.rb +24 -0
- data/lib/cred_hubble/resources/ssh_credential.rb +39 -0
- data/lib/cred_hubble/resources/user_credential.rb +39 -0
- data/lib/cred_hubble/resources/value_credential.rb +13 -0
- data/lib/cred_hubble/version.rb +1 -1
- data/spec/cred_hubble/client_spec.rb +487 -3
- data/spec/cred_hubble/http/client_spec.rb +347 -53
- data/spec/cred_hubble/resources/certificate_credential_spec.rb +49 -0
- data/spec/cred_hubble/resources/credential_collection_spec.rb +59 -0
- data/spec/cred_hubble/resources/credential_factory_spec.rb +154 -0
- data/spec/cred_hubble/resources/credential_spec.rb +10 -0
- data/spec/cred_hubble/resources/json_credential_spec.rb +52 -0
- data/spec/cred_hubble/resources/password_credential_spec.rb +41 -0
- data/spec/cred_hubble/resources/permission_collection_spec.rb +87 -0
- data/spec/cred_hubble/resources/permission_spec.rb +36 -0
- data/spec/cred_hubble/resources/rsa_credential_spec.rb +46 -0
- data/spec/cred_hubble/resources/ssh_credential_spec.rb +73 -0
- data/spec/cred_hubble/resources/user_credential_spec.rb +72 -0
- data/spec/cred_hubble/resources/value_credential_spec.rb +42 -0
- data/spec/support/shared_examples/resource_examples.rb +49 -0
- 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
|
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
|
data/lib/cred_hubble/version.rb
CHANGED
@@ -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(:
|
7
|
-
|
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(
|
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¤t=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
|