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 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
@@ -0,0 +1,13 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ /.idea/
11
+
12
+ # rspec failure tracking
13
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.rubocop.yml ADDED
@@ -0,0 +1,8 @@
1
+ Documentation:
2
+ Enabled: false
3
+ Metrics/BlockLength:
4
+ Enabled: false
5
+ Metrics/LineLength:
6
+ Max: 120
7
+ Metrics/MethodLength:
8
+ Max: 30
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.4.2
5
+ before_install: gem install bundler -v 1.15.4
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in cred_hubble.gemspec
6
+ gemspec
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
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
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
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -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,5 @@
1
+ module CredHubble
2
+ module Exceptions
3
+ class Error < StandardError; end
4
+ end
5
+ 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,9 @@
1
+ require 'cred_hubble/resources/immutable_resource'
2
+
3
+ module CredHubble
4
+ module Resources
5
+ class Health < ImmutableResource
6
+ attribute :status, String
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,10 @@
1
+ require 'cred_hubble/resources/base_resource'
2
+ require 'virtus'
3
+
4
+ module CredHubble
5
+ module Resources
6
+ class ImmutableResource < BaseResource
7
+ include ::Virtus.value_object
8
+ end
9
+ end
10
+ 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
@@ -0,0 +1,3 @@
1
+ module CredHubble
2
+ VERSION = '0.0.1.pre'.freeze
3
+ end
@@ -0,0 +1,5 @@
1
+ require 'cred_hubble/version'
2
+ require 'cred_hubble/exceptions/error'
3
+ require 'cred_hubble/resources/info'
4
+ require 'cred_hubble/resources/health'
5
+ require 'cred_hubble/client'
@@ -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
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe CredHubble do
4
+ it 'has a version number' do
5
+ expect(CredHubble::VERSION).not_to be nil
6
+ end
7
+ end
@@ -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