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