cred_hubble 0.0.1.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/.rspec +2 -0
- data/.rubocop.yml +8 -0
- data/.travis.yml +5 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +65 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/cred_hubble.gemspec +31 -0
- data/lib/cred_hubble/client.rb +38 -0
- data/lib/cred_hubble/exceptions/error.rb +5 -0
- data/lib/cred_hubble/http/client.rb +59 -0
- data/lib/cred_hubble/http/errors.rb +25 -0
- data/lib/cred_hubble/resources/base_resource.rb +22 -0
- data/lib/cred_hubble/resources/health.rb +9 -0
- data/lib/cred_hubble/resources/immutable_resource.rb +10 -0
- data/lib/cred_hubble/resources/info.rb +29 -0
- data/lib/cred_hubble/version.rb +3 -0
- data/lib/cred_hubble.rb +5 -0
- data/spec/cred_hubble/client_spec.rb +52 -0
- data/spec/cred_hubble/http/client_spec.rb +128 -0
- data/spec/cred_hubble/resources/health_spec.rb +24 -0
- data/spec/cred_hubble/resources/info_spec.rb +70 -0
- data/spec/cred_hubble_spec.rb +7 -0
- data/spec/spec_helper.rb +19 -0
- data/spec/support/shared_examples/resource_examples.rb +15 -0
- metadata +192 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4aa942e3ce3bb4edbd7b3324c07e288ad90d5bca
|
4
|
+
data.tar.gz: ad29b2209eab77575ac361754ddf214965194d04
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6479f99426131ce1fbbf03b0ed2411d480039a8e9836a6d225785bf8727fce0a29d61ab0914b6f9a39ebd1ceb22fe4b68ef995872fd6248c92da9a7035ae06a7
|
7
|
+
data.tar.gz: 02d1c42a6dda653f6b6a4f84ad16654bce77eb3b280b90f683b6daef86873e47fb409332f31de5ad83b9758dfea776938e5932597666c0760b0f1226ce9519ef
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2017 Tim Downey
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
# CredHubble :telescope: :full_moon_with_face:
|
2
|
+
|
3
|
+
Unofficial and **incomplete** Ruby client for storing and fetching credentials from a [Cloud Foundry CredHub](https://github.com/cloudfoundry-incubator/credhub) credential storage service.
|
4
|
+
|
5
|
+
It only supports the unauthenticated `/info` and `/health` endpoints for now, but eventually this library will let your Ruby app fetch secrets (e.g. database creds, Rails session secrets, AWS access keys, etc.) from CredHub at runtime, meaning you'll no longer need to store them in plaintext config files or in your app's environment.
|
6
|
+
|
7
|
+
That's the dream at least.
|
8
|
+
|
9
|
+
Right now this is just something I'm working on for fun since it's been a while since I've gotten to write a Ruby HTTP client. :grin:
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Add this line to your application's Gemfile:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
gem 'cred_hubble'
|
17
|
+
```
|
18
|
+
|
19
|
+
And then execute:
|
20
|
+
|
21
|
+
$ bundle
|
22
|
+
|
23
|
+
Or install it yourself as:
|
24
|
+
|
25
|
+
$ gem install cred_hubble
|
26
|
+
|
27
|
+
## Usage
|
28
|
+
|
29
|
+
This gem currently only support the CredHub endpoints that allow unauthenticated access:
|
30
|
+
|
31
|
+
* `/info`
|
32
|
+
* `/health`
|
33
|
+
|
34
|
+
To try out these endpoints, just do the following in your favorite Ruby console:
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
> credhub_url = 'https://credhub.your-cloud-foundry.com:8844'
|
38
|
+
> credhub_client = CredHubble::Client.new(credhub_url)
|
39
|
+
> info = credhub_client.info
|
40
|
+
=> #<CredHubble::Resources::Info:0x00007fb36497a490 ...
|
41
|
+
> info.auth_server.url
|
42
|
+
=> "https://uaa.service.cf.internal:8443"
|
43
|
+
> health = credhub_client.health
|
44
|
+
=> #<CredHubble::Resources::Health:0x00007fb3648f0218 ...
|
45
|
+
> health.status
|
46
|
+
=> "UP"
|
47
|
+
```
|
48
|
+
|
49
|
+
A future update to the gem will allow you hit authenticated endpoints using either a UAA token or mutual TLS for authentication.
|
50
|
+
|
51
|
+
This is still very much a work in progress.
|
52
|
+
|
53
|
+
## Development
|
54
|
+
|
55
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
56
|
+
|
57
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
58
|
+
|
59
|
+
## Contributing
|
60
|
+
|
61
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/tcdowney/cred_hubble.
|
62
|
+
|
63
|
+
## License
|
64
|
+
|
65
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'cred_hubble'
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require 'irb'
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/cred_hubble.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'cred_hubble/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'cred_hubble'
|
8
|
+
spec.version = CredHubble::VERSION
|
9
|
+
spec.authors = ['Tim Downey']
|
10
|
+
spec.email = ['tim@downey.io']
|
11
|
+
|
12
|
+
spec.summary = 'Unofficial Ruby Client for interacting with the ' \
|
13
|
+
'Cloud Foundry CredHub credential store'
|
14
|
+
spec.homepage = 'https://github.com/tcdowney/cred_hubble'
|
15
|
+
spec.license = 'MIT'
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0")
|
18
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
|
+
|
21
|
+
spec.require_paths = ['lib']
|
22
|
+
|
23
|
+
spec.add_runtime_dependency 'faraday', ['>= 0.13', '< 1.0']
|
24
|
+
spec.add_runtime_dependency 'virtus', ['>= 1.0', '< 2.0']
|
25
|
+
|
26
|
+
spec.add_development_dependency 'bundler', '~> 1.15'
|
27
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
28
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
29
|
+
spec.add_development_dependency 'rubocop'
|
30
|
+
spec.add_development_dependency 'webmock', '~> 3.0'
|
31
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'cred_hubble/resources/info'
|
2
|
+
require 'cred_hubble/resources/health'
|
3
|
+
require 'cred_hubble/http/client'
|
4
|
+
|
5
|
+
module CredHubble
|
6
|
+
class Client
|
7
|
+
def initialize(credhub_url)
|
8
|
+
@credhub_url = credhub_url
|
9
|
+
@verify_ssl = true
|
10
|
+
end
|
11
|
+
|
12
|
+
def info
|
13
|
+
response = http_client.get('/info').body
|
14
|
+
CredHubble::Resources::Info.from_json(response)
|
15
|
+
end
|
16
|
+
|
17
|
+
def health
|
18
|
+
response = http_client.get('/health').body
|
19
|
+
CredHubble::Resources::Health.from_json(response)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
attr_reader :credhub_url, :verify_ssl
|
25
|
+
|
26
|
+
def http_client
|
27
|
+
CredHubble::Http::Client.new(credhub_url, verify_ssl: verify_ssl)
|
28
|
+
end
|
29
|
+
|
30
|
+
# TODO: Remove ability to disable ssl verification
|
31
|
+
# Only leaving this in to simplify initial development
|
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!'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'cred_hubble/http/errors'
|
2
|
+
require 'faraday'
|
3
|
+
|
4
|
+
module CredHubble
|
5
|
+
module Http
|
6
|
+
class Client
|
7
|
+
DEFAULT_HEADERS = { 'Content-Type' => 'application/json' }.freeze
|
8
|
+
|
9
|
+
def initialize(url, verify_ssl: true)
|
10
|
+
@url = url
|
11
|
+
@verify_ssl = verify_ssl
|
12
|
+
end
|
13
|
+
|
14
|
+
def get(path)
|
15
|
+
with_error_handling do
|
16
|
+
connection.get(path)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
attr_reader :url, :verify_ssl
|
23
|
+
|
24
|
+
def connection
|
25
|
+
Faraday.new(url: url, headers: DEFAULT_HEADERS, ssl: { verify: verify_ssl }) do |faraday|
|
26
|
+
faraday.request :url_encoded
|
27
|
+
faraday.adapter Faraday.default_adapter
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def with_error_handling(&_block)
|
32
|
+
response = yield
|
33
|
+
|
34
|
+
return response if [200, 201, 202, 204].include?(response.status)
|
35
|
+
|
36
|
+
raise_error_from_response(response)
|
37
|
+
rescue Faraday::SSLError => e
|
38
|
+
raise CredHubble::Http::SSLError, e
|
39
|
+
end
|
40
|
+
|
41
|
+
def raise_error_from_response(response)
|
42
|
+
case response.status
|
43
|
+
when 400
|
44
|
+
raise BadRequestError.from_response(response)
|
45
|
+
when 401
|
46
|
+
raise UnauthorizedError.from_response(response)
|
47
|
+
when 403
|
48
|
+
raise ForbiddenError.from_response(response)
|
49
|
+
when 404
|
50
|
+
raise NotFoundError.from_response(response)
|
51
|
+
when 500
|
52
|
+
raise InternalServerError.from_response(response)
|
53
|
+
else
|
54
|
+
raise UnknownError.from_response(response)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module CredHubble
|
2
|
+
module Http
|
3
|
+
class Error < CredHubble::Exceptions::Error
|
4
|
+
def self.from_response(response)
|
5
|
+
message = "status: #{response.status}, body: #{response.body}"
|
6
|
+
new(message)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class BadRequestError < Error
|
11
|
+
end
|
12
|
+
class UnauthorizedError < Error
|
13
|
+
end
|
14
|
+
class ForbiddenError < Error
|
15
|
+
end
|
16
|
+
class NotFoundError < Error
|
17
|
+
end
|
18
|
+
class InternalServerError < Error
|
19
|
+
end
|
20
|
+
class UnknownError < Error
|
21
|
+
end
|
22
|
+
class SSLError < Error
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'cred_hubble/exceptions/error'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module CredHubble
|
5
|
+
module Resources
|
6
|
+
class JsonParseError < CredHubble::Exceptions::Error; end
|
7
|
+
|
8
|
+
class BaseResource
|
9
|
+
def self.from_json(json)
|
10
|
+
new(parse_json(json))
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.parse_json(raw_json)
|
14
|
+
JSON.parse(raw_json)
|
15
|
+
rescue JSON::ParserError => e
|
16
|
+
raise CredHubble::Resources::JsonParseError, e.message
|
17
|
+
end
|
18
|
+
|
19
|
+
private_class_method :parse_json
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'cred_hubble/resources/immutable_resource'
|
2
|
+
|
3
|
+
module CredHubble
|
4
|
+
module Resources
|
5
|
+
class AuthServerInfo < ImmutableResource
|
6
|
+
attribute :url, String
|
7
|
+
end
|
8
|
+
|
9
|
+
class AppInfo < ImmutableResource
|
10
|
+
attribute :name, String
|
11
|
+
attribute :version, String
|
12
|
+
end
|
13
|
+
|
14
|
+
class Info < ImmutableResource
|
15
|
+
attribute :auth_server, AuthServerInfo, default: AuthServerInfo.new
|
16
|
+
attribute :app, AppInfo, default: AppInfo.new
|
17
|
+
|
18
|
+
def self.from_json(raw_json)
|
19
|
+
parsed_json = parse_json(raw_json)
|
20
|
+
|
21
|
+
if parsed_json['auth-server']
|
22
|
+
parsed_json[:auth_server] = parsed_json.delete('auth-server')
|
23
|
+
end
|
24
|
+
|
25
|
+
new(parsed_json)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/cred_hubble.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe CredHubble::Client do
|
4
|
+
let(:mock_http_client) { instance_double(CredHubble::Http::Client) }
|
5
|
+
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) }
|
8
|
+
|
9
|
+
before do
|
10
|
+
allow(subject).to receive(:http_client).and_return(mock_http_client)
|
11
|
+
allow(mock_http_client).to receive(:get).and_return(mock_response)
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '#info' do
|
15
|
+
let(:response_body) do
|
16
|
+
'{
|
17
|
+
"auth-server": {
|
18
|
+
"url":"https://uaa.service.cf.internal:8443"
|
19
|
+
},
|
20
|
+
"app": {
|
21
|
+
"name":"CredHub",
|
22
|
+
"version":"1.2.0"
|
23
|
+
}
|
24
|
+
}'
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'makes a request to the /info endpoint' do
|
28
|
+
subject.info
|
29
|
+
expect(mock_http_client).to have_received(:get).with('/info')
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'returns an Info resource' do
|
33
|
+
info = subject.info
|
34
|
+
expect(info.auth_server.url).to eq('https://uaa.service.cf.internal:8443')
|
35
|
+
expect(info.app.version).to eq('1.2.0')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe '#health' do
|
40
|
+
let(:response_body) { '{"status": "UP"}' }
|
41
|
+
|
42
|
+
it 'makes a request to the /health endpoint' do
|
43
|
+
subject.health
|
44
|
+
expect(mock_http_client).to have_received(:get).with('/health')
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'returns a Health resource' do
|
48
|
+
health = subject.health
|
49
|
+
expect(health.status).to eq('UP')
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe CredHubble::Http::Client do
|
4
|
+
let(:url) { 'https://example.com:8845' }
|
5
|
+
subject { CredHubble::Http::Client.new(url) }
|
6
|
+
|
7
|
+
describe '#get' do
|
8
|
+
let(:path) { '/info' }
|
9
|
+
let(:status) { 200 }
|
10
|
+
let(:response_body) do
|
11
|
+
'{
|
12
|
+
"auth-server": {
|
13
|
+
"url":"https:/some-uaa-auth-server.com:8443"
|
14
|
+
},
|
15
|
+
"app": {
|
16
|
+
"name":"CredHub 3000",
|
17
|
+
"version":"0.0.1"
|
18
|
+
}
|
19
|
+
}'
|
20
|
+
end
|
21
|
+
|
22
|
+
before do
|
23
|
+
stub_request(:get, "#{url}#{path}").to_return(status: status, body: response_body)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'makes a GET request to the requested url and path' do
|
27
|
+
response = subject.get(path)
|
28
|
+
expect(response).to be_a(Faraday::Response)
|
29
|
+
expect(response.body).to eq(response_body)
|
30
|
+
expect(response.status).to eq(status)
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'when a Faraday::SSLError occurrs' do
|
34
|
+
let(:error) { Faraday::SSLError.new('SSL_connect returned=1 errno=0 state=error: certificate verify failed') }
|
35
|
+
let(:fake_connection) { instance_double(Faraday::Connection) }
|
36
|
+
|
37
|
+
before do
|
38
|
+
allow(subject).to receive(:connection).and_return(fake_connection)
|
39
|
+
allow(fake_connection).to receive(:get).and_raise(error)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'raises a CredHubble::Exceptions::SSLError' do
|
43
|
+
expect { subject.get(path) }.to raise_error(CredHubble::Http::SSLError)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'when the response status is 400' do
|
48
|
+
let(:response_body) { 'Bad request' }
|
49
|
+
let(:status) { 400 }
|
50
|
+
|
51
|
+
it 'raises a CredHubble::Http::BadRequestError' do
|
52
|
+
expect { subject.get(path) }
|
53
|
+
.to raise_error(CredHubble::Http::BadRequestError, "status: #{status}, body: #{response_body}")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'when the response status is 401' do
|
58
|
+
let(:response_body) { 'Unauthorized' }
|
59
|
+
let(:status) { 401 }
|
60
|
+
|
61
|
+
it 'raises a CredHubble::Http::UnauthorizedError' do
|
62
|
+
expect { subject.get(path) }
|
63
|
+
.to raise_error(CredHubble::Http::UnauthorizedError, "status: #{status}, body: #{response_body}")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'when the response status is 403' do
|
68
|
+
let(:response_body) { 'Forbidden' }
|
69
|
+
let(:status) { 403 }
|
70
|
+
|
71
|
+
it 'raises a CredHubble::Http::ForbiddenError' do
|
72
|
+
expect { subject.get(path) }
|
73
|
+
.to raise_error(CredHubble::Http::ForbiddenError, "status: #{status}, body: #{response_body}")
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context 'when the response status is 404' do
|
78
|
+
let(:response_body) { 'Not found' }
|
79
|
+
let(:status) { 404 }
|
80
|
+
|
81
|
+
it 'raises a CredHubble::Http::NotFoundError' do
|
82
|
+
expect { subject.get(path) }
|
83
|
+
.to raise_error(CredHubble::Http::NotFoundError, "status: #{status}, body: #{response_body}")
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context 'when the response status is 500' do
|
88
|
+
let(:response_body) { 'Internal Server Error' }
|
89
|
+
let(:status) { 500 }
|
90
|
+
|
91
|
+
it 'raises a CredHubble::Http::InternalServerError' do
|
92
|
+
expect { subject.get(path) }
|
93
|
+
.to raise_error(CredHubble::Http::InternalServerError, "status: #{status}, body: #{response_body}")
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context 'when the response status is not otherwise handled' do
|
98
|
+
let(:response_body) { "I'm a teapot" }
|
99
|
+
let(:status) { 418 }
|
100
|
+
|
101
|
+
it 'raises a CredHubble::Http::InternalServerError' do
|
102
|
+
expect { subject.get(path) }
|
103
|
+
.to raise_error(CredHubble::Http::UnknownError, "status: #{status}, body: #{response_body}")
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe 'SSL verification' do
|
109
|
+
context 'when verify_ssl is not specified' do
|
110
|
+
subject { CredHubble::Http::Client.new(url) }
|
111
|
+
|
112
|
+
it 'has ssl verification enabled by default' do
|
113
|
+
connection = subject.send(:connection)
|
114
|
+
expect(connection.ssl.verify).to eq(true)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# TODO: Remove ability to disable ssl verification
|
119
|
+
context 'when verify_ssl is set to false' do
|
120
|
+
subject { CredHubble::Http::Client.new(url, verify_ssl: false) }
|
121
|
+
|
122
|
+
it 'has ssl verification disabled' do
|
123
|
+
connection = subject.send(:connection)
|
124
|
+
expect(connection.ssl.verify).to eq(false)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe CredHubble::Resources::Health do
|
4
|
+
describe '.from_json' do
|
5
|
+
subject { CredHubble::Resources::Health }
|
6
|
+
|
7
|
+
context 'when the JSON includes the required attributes' do
|
8
|
+
let(:json_response) { '{"status": "UP"}' }
|
9
|
+
|
10
|
+
it 'instantiates a new Health object with the correct values' do
|
11
|
+
health = subject.from_json(json_response)
|
12
|
+
expect(health.status).to eq('UP')
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
it_behaves_like 'a JSON deserializing resource'
|
17
|
+
end
|
18
|
+
|
19
|
+
describe 'immutability' do
|
20
|
+
subject { CredHubble::Resources::Health.new(status: 'UP') }
|
21
|
+
|
22
|
+
it_behaves_like 'an immutable resource', :status
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe CredHubble::Resources::Info do
|
4
|
+
describe '.from_json' do
|
5
|
+
subject { CredHubble::Resources::Info }
|
6
|
+
|
7
|
+
context 'when the JSON includes the required attributes' do
|
8
|
+
let(:json_response) do
|
9
|
+
'{
|
10
|
+
"auth-server": {
|
11
|
+
"url":"https://uaa.service.cf.internal:8443"
|
12
|
+
},
|
13
|
+
"app": {
|
14
|
+
"name":"CredHub",
|
15
|
+
"version":"1.2.0"
|
16
|
+
}
|
17
|
+
}'
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'instantiates a new Info object with the correct values' do
|
21
|
+
info = subject.from_json(json_response)
|
22
|
+
expect(info.auth_server.url).to eq('https://uaa.service.cf.internal:8443')
|
23
|
+
expect(info.app.name).to eq('CredHub')
|
24
|
+
expect(info.app.version).to eq('1.2.0')
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'when the JSON includes extra attributes' do
|
28
|
+
let(:json_response) do
|
29
|
+
'{
|
30
|
+
"auth-server": {
|
31
|
+
"url":"https://uaa.service.cf.internal:8443"
|
32
|
+
},
|
33
|
+
"app": {
|
34
|
+
"name":"CredHub",
|
35
|
+
"version":"1.2.0",
|
36
|
+
"extra": "extra!"
|
37
|
+
}
|
38
|
+
}'
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'instantiates a new Info object and ignores the extra fields' do
|
42
|
+
info = subject.from_json(json_response)
|
43
|
+
expect(info.auth_server.url).to eq('https://uaa.service.cf.internal:8443')
|
44
|
+
expect(info.app.name).to eq('CredHub')
|
45
|
+
expect(info.app.version).to eq('1.2.0')
|
46
|
+
expect(info.app).to_not respond_to(:extra)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context 'when the JSON is missing attributes' do
|
52
|
+
let(:json_response) { '{}' }
|
53
|
+
|
54
|
+
it 'instantiates a new Info object and returns nil for the missing fields' do
|
55
|
+
info = subject.from_json(json_response)
|
56
|
+
expect(info.auth_server.url).to be_nil
|
57
|
+
expect(info.app.name).to be_nil
|
58
|
+
expect(info.app.version).to be_nil
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
it_behaves_like 'a JSON deserializing resource'
|
63
|
+
end
|
64
|
+
|
65
|
+
describe 'immutability' do
|
66
|
+
subject { CredHubble::Resources::Info.new(app: { name: 'CredHub', version: '1.0' }) }
|
67
|
+
|
68
|
+
it_behaves_like 'an immutable resource', :app
|
69
|
+
end
|
70
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'webmock/rspec'
|
5
|
+
require 'cred_hubble'
|
6
|
+
|
7
|
+
Dir[File.expand_path('../support/**/*.rb', __FILE__)].each { |f| require f }
|
8
|
+
|
9
|
+
RSpec.configure do |config|
|
10
|
+
# Enable flags like --only-failures and --next-failure
|
11
|
+
config.example_status_persistence_file_path = '.rspec_status'
|
12
|
+
|
13
|
+
# Disable RSpec exposing methods globally on `Module` and `main`
|
14
|
+
config.disable_monkey_patching!
|
15
|
+
|
16
|
+
config.expect_with :rspec do |c|
|
17
|
+
c.syntax = :expect
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
RSpec.shared_examples 'an immutable resource' do |attribute|
|
2
|
+
it 'will not allow attributes to be updated on the subject' do
|
3
|
+
expect { subject.public_send("#{attribute}=", {}) }.to raise_error(NoMethodError, /#{Regexp.quote(attribute)}/)
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
RSpec.shared_examples 'a JSON deserializing resource' do
|
8
|
+
context 'when provided invalid JSON' do
|
9
|
+
let(:invalid_json_response) { 'not valid json' }
|
10
|
+
|
11
|
+
it 'raises a JSON parse error' do
|
12
|
+
expect { subject.from_json(invalid_json_response) }.to raise_error(CredHubble::Resources::JsonParseError)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
metadata
ADDED
@@ -0,0 +1,192 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cred_hubble
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1.pre
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tim Downey
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-09-25 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: faraday
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.13'
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '1.0'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0.13'
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '1.0'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: virtus
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '1.0'
|
40
|
+
- - "<"
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '2.0'
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '1.0'
|
50
|
+
- - "<"
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '2.0'
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: bundler
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - "~>"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '1.15'
|
60
|
+
type: :development
|
61
|
+
prerelease: false
|
62
|
+
version_requirements: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - "~>"
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '1.15'
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
name: rake
|
69
|
+
requirement: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - "~>"
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '10.0'
|
74
|
+
type: :development
|
75
|
+
prerelease: false
|
76
|
+
version_requirements: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - "~>"
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '10.0'
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: rspec
|
83
|
+
requirement: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - "~>"
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '3.0'
|
88
|
+
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - "~>"
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '3.0'
|
95
|
+
- !ruby/object:Gem::Dependency
|
96
|
+
name: rubocop
|
97
|
+
requirement: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '0'
|
109
|
+
- !ruby/object:Gem::Dependency
|
110
|
+
name: webmock
|
111
|
+
requirement: !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - "~>"
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '3.0'
|
116
|
+
type: :development
|
117
|
+
prerelease: false
|
118
|
+
version_requirements: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - "~>"
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '3.0'
|
123
|
+
description:
|
124
|
+
email:
|
125
|
+
- tim@downey.io
|
126
|
+
executables:
|
127
|
+
- console
|
128
|
+
- setup
|
129
|
+
extensions: []
|
130
|
+
extra_rdoc_files: []
|
131
|
+
files:
|
132
|
+
- ".gitignore"
|
133
|
+
- ".rspec"
|
134
|
+
- ".rubocop.yml"
|
135
|
+
- ".travis.yml"
|
136
|
+
- Gemfile
|
137
|
+
- LICENSE.txt
|
138
|
+
- README.md
|
139
|
+
- Rakefile
|
140
|
+
- bin/console
|
141
|
+
- bin/setup
|
142
|
+
- cred_hubble.gemspec
|
143
|
+
- lib/cred_hubble.rb
|
144
|
+
- lib/cred_hubble/client.rb
|
145
|
+
- lib/cred_hubble/exceptions/error.rb
|
146
|
+
- lib/cred_hubble/http/client.rb
|
147
|
+
- lib/cred_hubble/http/errors.rb
|
148
|
+
- lib/cred_hubble/resources/base_resource.rb
|
149
|
+
- lib/cred_hubble/resources/health.rb
|
150
|
+
- lib/cred_hubble/resources/immutable_resource.rb
|
151
|
+
- lib/cred_hubble/resources/info.rb
|
152
|
+
- lib/cred_hubble/version.rb
|
153
|
+
- spec/cred_hubble/client_spec.rb
|
154
|
+
- spec/cred_hubble/http/client_spec.rb
|
155
|
+
- spec/cred_hubble/resources/health_spec.rb
|
156
|
+
- spec/cred_hubble/resources/info_spec.rb
|
157
|
+
- spec/cred_hubble_spec.rb
|
158
|
+
- spec/spec_helper.rb
|
159
|
+
- spec/support/shared_examples/resource_examples.rb
|
160
|
+
homepage: https://github.com/tcdowney/cred_hubble
|
161
|
+
licenses:
|
162
|
+
- MIT
|
163
|
+
metadata: {}
|
164
|
+
post_install_message:
|
165
|
+
rdoc_options: []
|
166
|
+
require_paths:
|
167
|
+
- lib
|
168
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
169
|
+
requirements:
|
170
|
+
- - ">="
|
171
|
+
- !ruby/object:Gem::Version
|
172
|
+
version: '0'
|
173
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
174
|
+
requirements:
|
175
|
+
- - ">"
|
176
|
+
- !ruby/object:Gem::Version
|
177
|
+
version: 1.3.1
|
178
|
+
requirements: []
|
179
|
+
rubyforge_project:
|
180
|
+
rubygems_version: 2.6.13
|
181
|
+
signing_key:
|
182
|
+
specification_version: 4
|
183
|
+
summary: Unofficial Ruby Client for interacting with the Cloud Foundry CredHub credential
|
184
|
+
store
|
185
|
+
test_files:
|
186
|
+
- spec/cred_hubble/client_spec.rb
|
187
|
+
- spec/cred_hubble/http/client_spec.rb
|
188
|
+
- spec/cred_hubble/resources/health_spec.rb
|
189
|
+
- spec/cred_hubble/resources/info_spec.rb
|
190
|
+
- spec/cred_hubble_spec.rb
|
191
|
+
- spec/spec_helper.rb
|
192
|
+
- spec/support/shared_examples/resource_examples.rb
|