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
data/lib/cred_hubble.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'cred_hubble/version'
|
2
2
|
require 'cred_hubble/exceptions/error'
|
3
|
-
require 'cred_hubble/resources/
|
4
|
-
require 'cred_hubble/resources/
|
3
|
+
require 'cred_hubble/resources/resources'
|
4
|
+
require 'cred_hubble/resources/credential_factory'
|
5
|
+
|
5
6
|
require 'cred_hubble/client'
|
data/lib/cred_hubble/client.rb
CHANGED
@@ -1,12 +1,39 @@
|
|
1
|
-
require '
|
2
|
-
require 'cred_hubble/resources/
|
1
|
+
require 'addressable'
|
2
|
+
require 'cred_hubble/resources/resources'
|
3
3
|
require 'cred_hubble/http/client'
|
4
|
+
require 'openssl'
|
4
5
|
|
6
|
+
# rubocop:disable ClassLength
|
5
7
|
module CredHubble
|
6
8
|
class Client
|
7
|
-
def initialize(
|
8
|
-
|
9
|
-
|
9
|
+
def initialize(host:, port: 8844, auth_header_token: nil, ca_path: nil,
|
10
|
+
client_cert_path: nil, client_key_path: nil)
|
11
|
+
|
12
|
+
@host = host
|
13
|
+
@port = port
|
14
|
+
@auth_header_token = auth_header_token
|
15
|
+
@ca_path = ca_path
|
16
|
+
@client_cert_path = client_cert_path
|
17
|
+
@client_key_path = client_key_path
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.new_from_token_auth(host:, port: 8844, auth_header_token:, ca_path: nil)
|
21
|
+
new(
|
22
|
+
auth_header_token: auth_header_token,
|
23
|
+
ca_path: ca_path,
|
24
|
+
host: host,
|
25
|
+
port: port
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.new_from_mtls_auth(host:, port: 8844, client_cert_path:, client_key_path:, ca_path: nil)
|
30
|
+
new(
|
31
|
+
client_cert_path: client_cert_path,
|
32
|
+
client_key_path: client_key_path,
|
33
|
+
host: host,
|
34
|
+
ca_path: ca_path,
|
35
|
+
port: port
|
36
|
+
)
|
10
37
|
end
|
11
38
|
|
12
39
|
def info
|
@@ -19,20 +46,99 @@ module CredHubble
|
|
19
46
|
CredHubble::Resources::Health.from_json(response)
|
20
47
|
end
|
21
48
|
|
49
|
+
def credential_by_id(credential_id)
|
50
|
+
response = http_client.get("/api/v1/data/#{credential_id}").body
|
51
|
+
CredHubble::Resources::CredentialFactory.from_json(response)
|
52
|
+
end
|
53
|
+
|
54
|
+
def credentials_by_name(name, current: nil, versions: nil)
|
55
|
+
template = Addressable::Template.new('/api/v1/data{?query*}')
|
56
|
+
|
57
|
+
query_args = { name: name, current: current, versions: versions }.reject { |_, v| v.nil? }
|
58
|
+
path = template.expand(query: query_args).to_s
|
59
|
+
|
60
|
+
response = http_client.get(path).body
|
61
|
+
CredHubble::Resources::CredentialCollection.from_json(response)
|
62
|
+
end
|
63
|
+
|
64
|
+
def permissions_by_credential_name(credential_name)
|
65
|
+
template = Addressable::Template.new('/api/v1/permissions{?query*}')
|
66
|
+
|
67
|
+
query_args = { credential_name: credential_name }
|
68
|
+
path = template.expand(query: query_args).to_s
|
69
|
+
|
70
|
+
response = http_client.get(path).body
|
71
|
+
CredHubble::Resources::PermissionCollection.from_json(response)
|
72
|
+
end
|
73
|
+
|
74
|
+
def put_credential(credential, overwrite: nil, additional_permissions: [])
|
75
|
+
credential_body = credential.attributes_for_put
|
76
|
+
credential_body[:overwrite] = !!overwrite unless overwrite.nil?
|
77
|
+
|
78
|
+
unless additional_permissions.empty?
|
79
|
+
credential_body[:additional_permissions] = additional_permissions.map(&:attributes)
|
80
|
+
end
|
81
|
+
|
82
|
+
response = http_client.put('/api/v1/data', credential_body.to_json).body
|
83
|
+
CredHubble::Resources::CredentialFactory.from_json(response)
|
84
|
+
end
|
85
|
+
|
86
|
+
def interpolate_credentials(vcap_services_json)
|
87
|
+
http_client.post('/api/v1/interpolate', vcap_services_json).body
|
88
|
+
end
|
89
|
+
|
90
|
+
def delete_credential_by_name(name)
|
91
|
+
template = Addressable::Template.new('/api/v1/data{?query*}')
|
92
|
+
|
93
|
+
query_args = { name: name }
|
94
|
+
path = template.expand(query: query_args).to_s
|
95
|
+
|
96
|
+
http_client.delete(path).success?
|
97
|
+
end
|
98
|
+
|
99
|
+
def add_permissions(permission_collection)
|
100
|
+
response = http_client.post('/api/v1/permissions', permission_collection.to_json).body
|
101
|
+
CredHubble::Resources::PermissionCollection.from_json(response)
|
102
|
+
end
|
103
|
+
|
104
|
+
def delete_permissions(credential_name, actor)
|
105
|
+
template = Addressable::Template.new('/api/v1/permissions{?query*}')
|
106
|
+
|
107
|
+
query_args = { credential_name: credential_name, actor: actor }
|
108
|
+
path = template.expand(query: query_args).to_s
|
109
|
+
|
110
|
+
http_client.delete(path).success?
|
111
|
+
end
|
112
|
+
|
22
113
|
private
|
23
114
|
|
24
|
-
attr_reader :
|
115
|
+
attr_reader :auth_header_token, :client_cert_path, :client_key_path, :ca_path, :host, :port
|
25
116
|
|
26
117
|
def http_client
|
27
|
-
CredHubble::Http::Client.new(
|
118
|
+
CredHubble::Http::Client.new(
|
119
|
+
credhub_url,
|
120
|
+
auth_header_token: auth_header_token,
|
121
|
+
ca_path: ca_path,
|
122
|
+
client_cert: client_cert,
|
123
|
+
client_key: client_key
|
124
|
+
)
|
125
|
+
end
|
126
|
+
|
127
|
+
def client_cert
|
128
|
+
return unless client_cert_path
|
129
|
+
|
130
|
+
OpenSSL::X509::Certificate.new(File.read(client_cert_path))
|
131
|
+
end
|
132
|
+
|
133
|
+
def client_key
|
134
|
+
return unless client_key_path
|
135
|
+
|
136
|
+
OpenSSL::PKey::RSA.new(File.read(client_key_path))
|
28
137
|
end
|
29
138
|
|
30
|
-
|
31
|
-
|
32
|
-
# Will be removed before the 0.0.1 release since non-SSL + CredHub is not a good combo
|
33
|
-
def unsafe_mode!
|
34
|
-
@verify_ssl = false
|
35
|
-
puts 'WARNING: SSL verification disabled!'
|
139
|
+
def credhub_url
|
140
|
+
Addressable::URI.new(scheme: 'https', host: host, port: port).to_s
|
36
141
|
end
|
37
142
|
end
|
38
143
|
end
|
144
|
+
# rubocop:enable ClassLength
|
@@ -6,9 +6,12 @@ module CredHubble
|
|
6
6
|
class Client
|
7
7
|
DEFAULT_HEADERS = { 'Content-Type' => 'application/json' }.freeze
|
8
8
|
|
9
|
-
def initialize(url,
|
9
|
+
def initialize(url, auth_header_token: nil, ca_path: nil, client_cert: nil, client_key: nil)
|
10
10
|
@url = url
|
11
|
-
@
|
11
|
+
@auth_header_token = auth_header_token
|
12
|
+
@ca_path = ca_path
|
13
|
+
@client_cert = client_cert
|
14
|
+
@client_key = client_key
|
12
15
|
end
|
13
16
|
|
14
17
|
def get(path)
|
@@ -17,17 +20,49 @@ module CredHubble
|
|
17
20
|
end
|
18
21
|
end
|
19
22
|
|
23
|
+
def post(path, body)
|
24
|
+
with_error_handling do
|
25
|
+
connection.post(path, body)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def put(path, body)
|
30
|
+
with_error_handling do
|
31
|
+
connection.put(path, body)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def delete(path)
|
36
|
+
with_error_handling do
|
37
|
+
connection.delete(path)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
20
41
|
private
|
21
42
|
|
22
|
-
attr_reader :
|
43
|
+
attr_reader :auth_header_token, :client_cert, :client_key, :ca_path, :url
|
23
44
|
|
24
45
|
def connection
|
25
|
-
Faraday.new(url: url, headers:
|
46
|
+
Faraday.new(url: url, headers: request_headers, ssl: ssl_config) do |faraday|
|
26
47
|
faraday.request :url_encoded
|
27
48
|
faraday.adapter Faraday.default_adapter
|
28
49
|
end
|
29
50
|
end
|
30
51
|
|
52
|
+
def request_headers
|
53
|
+
headers = DEFAULT_HEADERS
|
54
|
+
return headers unless auth_header_token
|
55
|
+
|
56
|
+
headers.merge('Authorization' => "bearer #{auth_header_token}")
|
57
|
+
end
|
58
|
+
|
59
|
+
def ssl_config
|
60
|
+
additional_config = { ca_file: ca_path, client_cert: client_cert, client_key: client_key }
|
61
|
+
additional_config.reject! { |_, v| v.nil? }
|
62
|
+
|
63
|
+
{ verify: true }.merge(additional_config)
|
64
|
+
end
|
65
|
+
|
31
66
|
def with_error_handling(&_block)
|
32
67
|
response = yield
|
33
68
|
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'cred_hubble/resources/credential'
|
2
|
+
|
3
|
+
module CredHubble
|
4
|
+
module Resources
|
5
|
+
class CertificateValue
|
6
|
+
include Virtus.model
|
7
|
+
|
8
|
+
attribute :ca, String
|
9
|
+
attribute :certificate, String
|
10
|
+
attribute :private_key, String
|
11
|
+
|
12
|
+
def to_json(options = {})
|
13
|
+
attributes.to_json(options)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class CertificateCredential < Credential
|
18
|
+
attribute :value, CertificateValue
|
19
|
+
|
20
|
+
def type
|
21
|
+
Credential::CERTIFICATE_TYPE
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'cred_hubble/resources/resource'
|
2
|
+
|
3
|
+
module CredHubble
|
4
|
+
module Resources
|
5
|
+
class Credential < Resource
|
6
|
+
TYPES = [
|
7
|
+
VALUE_TYPE = 'value'.freeze,
|
8
|
+
JSON_TYPE = 'json'.freeze,
|
9
|
+
PASSWORD_TYPE = 'password'.freeze,
|
10
|
+
USER_TYPE = 'user'.freeze,
|
11
|
+
CERTIFICATE_TYPE = 'certificate'.freeze,
|
12
|
+
RSA_TYPE = 'rsa'.freeze,
|
13
|
+
SSH_TYPE = 'ssh'.freeze
|
14
|
+
].freeze
|
15
|
+
|
16
|
+
attribute :id, String
|
17
|
+
attribute :name, String
|
18
|
+
attribute :type, String
|
19
|
+
attribute :version_created_at, String
|
20
|
+
|
21
|
+
def attributes_for_put
|
22
|
+
attributes.delete_if { |k, _| immutable_attributes.include?(k) }
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def immutable_attributes
|
28
|
+
%i[id version_created_at]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'cred_hubble/resources/rest_resource'
|
2
|
+
require 'cred_hubble/resources/credential_factory'
|
3
|
+
|
4
|
+
module CredHubble
|
5
|
+
module Resources
|
6
|
+
class CredentialCollection < Resource
|
7
|
+
include Enumerable
|
8
|
+
|
9
|
+
def initialize(value_hash)
|
10
|
+
credentials_array = value_hash['data']
|
11
|
+
@data = credentials_array.map { |credential_data| CredentialFactory.credential_from_data(credential_data) }
|
12
|
+
end
|
13
|
+
|
14
|
+
def each(&block)
|
15
|
+
data.each(&block)
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_reader :data
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'cred_hubble/resources/rest_resource'
|
2
|
+
require 'cred_hubble/resources/credential'
|
3
|
+
require 'cred_hubble/resources/value_credential'
|
4
|
+
require 'cred_hubble/resources/json_credential'
|
5
|
+
require 'cred_hubble/resources/password_credential'
|
6
|
+
require 'cred_hubble/resources/user_credential'
|
7
|
+
require 'cred_hubble/resources/certificate_credential'
|
8
|
+
require 'cred_hubble/resources/rsa_credential'
|
9
|
+
require 'cred_hubble/resources/ssh_credential'
|
10
|
+
|
11
|
+
module CredHubble
|
12
|
+
module Resources
|
13
|
+
class CredentialFactory < RestResource
|
14
|
+
def self.from_json(raw_json)
|
15
|
+
parsed_json = parse_json(raw_json)
|
16
|
+
credential_from_data(parsed_json)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.credential_from_data(credential_data)
|
20
|
+
case credential_data['type']
|
21
|
+
when Credential::VALUE_TYPE
|
22
|
+
ValueCredential.new(credential_data)
|
23
|
+
when Credential::JSON_TYPE
|
24
|
+
JsonCredential.new(credential_data)
|
25
|
+
when Credential::PASSWORD_TYPE
|
26
|
+
PasswordCredential.new(credential_data)
|
27
|
+
when Credential::USER_TYPE
|
28
|
+
UserCredential.new(credential_data)
|
29
|
+
when Credential::CERTIFICATE_TYPE
|
30
|
+
CertificateCredential.new(credential_data)
|
31
|
+
when Credential::RSA_TYPE
|
32
|
+
RsaCredential.new(credential_data)
|
33
|
+
when Credential::SSH_TYPE
|
34
|
+
SshCredential.new(credential_data)
|
35
|
+
else
|
36
|
+
Credential.new(credential_data)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -1,9 +1,9 @@
|
|
1
|
-
require 'cred_hubble/resources/
|
1
|
+
require 'cred_hubble/resources/rest_resource'
|
2
2
|
require 'virtus'
|
3
3
|
|
4
4
|
module CredHubble
|
5
5
|
module Resources
|
6
|
-
class ImmutableResource <
|
6
|
+
class ImmutableResource < RestResource
|
7
7
|
include ::Virtus.value_object
|
8
8
|
end
|
9
9
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'cred_hubble/resources/rest_resource'
|
2
|
+
require 'cred_hubble/resources/permission'
|
3
|
+
|
4
|
+
module CredHubble
|
5
|
+
module Resources
|
6
|
+
class PermissionCollection < Resource
|
7
|
+
include Enumerable
|
8
|
+
|
9
|
+
attribute :credential_name, String
|
10
|
+
attribute :permissions, Array[Permission]
|
11
|
+
|
12
|
+
def each(&block)
|
13
|
+
permissions.each(&block)
|
14
|
+
end
|
15
|
+
|
16
|
+
def empty?
|
17
|
+
permissions.empty?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'cred_hubble/resources/info'
|
2
|
+
require 'cred_hubble/resources/health'
|
3
|
+
|
4
|
+
require 'cred_hubble/resources/credential'
|
5
|
+
require 'cred_hubble/resources/credential_collection'
|
6
|
+
require 'cred_hubble/resources/value_credential'
|
7
|
+
require 'cred_hubble/resources/json_credential'
|
8
|
+
require 'cred_hubble/resources/password_credential'
|
9
|
+
require 'cred_hubble/resources/user_credential'
|
10
|
+
require 'cred_hubble/resources/certificate_credential'
|
11
|
+
require 'cred_hubble/resources/rsa_credential'
|
12
|
+
require 'cred_hubble/resources/ssh_credential'
|
13
|
+
|
14
|
+
require 'cred_hubble/resources/permission'
|
15
|
+
require 'cred_hubble/resources/permission_collection'
|