conjur-api 4.10.1 → 4.10.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8082f753ddebe272f08498fb3e144dcd5477cc57
4
- data.tar.gz: 1de7d39d363c091712b8d73add7cf7d87b952ce1
3
+ metadata.gz: 430af90880bc80ca4db9982fc99c0d670f17aa6f
4
+ data.tar.gz: 67be43db258ef8acfbae41801534aa615675da0a
5
5
  SHA512:
6
- metadata.gz: 28727a8a68e30751fc2234329ceee61857d02fc6fbb41d8f51e1997523b66b21146d740f2af6577160a4d8aebc2f4026994a03fb20542750bb299a251deb80d1
7
- data.tar.gz: 93e98f2269bd14ac60e4e3cd7ff8b6453aca5b0f7e4c2cc77da8e2e5736ed035a2712c460874f2ec72f467fd844ccbf9a41ec9b1db9d141bfda4476dd470a5a5
6
+ metadata.gz: 727e9688efb27f47f99c2e06ee02ef96cbfae03bda9ce177bd31200a8d52577c410166ba08de06b4cb11546c6c109fe52bd7a68804d14e34026e3700b7860e88
7
+ data.tar.gz: c94276c5d61ac5571f2da98b7d472cf56db274d396cffda3da34dff190f1fcd1b7804e693d472737472066263eab36ed58d7f4723b2519bc6fc7fab4dee900a0
data/CHANGELOG.md ADDED
@@ -0,0 +1,10 @@
1
+ # v.4.10.2
2
+ * Authn token is refetched before the expiration
3
+ * Support for configuration `sticky` option is discarded
4
+ * Resource#exists? refactored -- no overloading, code from exists.rb used
5
+ * Tests use Rspec v3 and reset configuration between test cases
6
+
7
+
8
+ # v.4.10.1
9
+ * Resource#exists? returns true if access to resource is forbidden
10
+ * Thread-local configuration for working with different endpoints
data/Gemfile CHANGED
@@ -4,7 +4,3 @@ source 'https://rubygems.org'
4
4
 
5
5
  # Specify your gem's dependencies in conjur-api.gemspec
6
6
  gemspec
7
-
8
- group :test do
9
- gem 'fuubar'
10
- end
data/conjur-api.gemspec CHANGED
@@ -21,14 +21,16 @@ Gem::Specification.new do |gem|
21
21
 
22
22
  gem.add_dependency 'rest-client', '= 1.6.7' # with newer versions adding certificates to OpenSSL does not work
23
23
  gem.add_dependency 'activesupport'
24
+ gem.add_dependency 'wrong'
24
25
 
25
26
  gem.add_development_dependency 'rake'
26
27
  gem.add_development_dependency 'spork'
27
- gem.add_development_dependency 'rspec', '>= 2.14', '< 3.0'
28
+ gem.add_development_dependency 'rspec', '~> 3'
28
29
  gem.add_development_dependency 'webmock'
29
30
  gem.add_development_dependency 'ci_reporter_rspec'
30
31
  gem.add_development_dependency 'simplecov'
31
32
  gem.add_development_dependency 'io-grab'
32
33
  gem.add_development_dependency 'yard'
33
34
  gem.add_development_dependency 'redcarpet'
35
+ gem.add_development_dependency 'timecop'
34
36
  end
@@ -20,6 +20,6 @@
20
20
  #
21
21
  module Conjur
22
22
  class API
23
- VERSION = "4.10.1"
23
+ VERSION = "4.10.2"
24
24
  end
25
25
  end
data/lib/conjur/base.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (C) 2013 Conjur Inc
2
+ # Copyright (C) 2013-2014 Conjur Inc
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy of
5
5
  # this software and associated documentation files (the "Software"), to deal in
@@ -21,6 +21,7 @@
21
21
  require 'rest-client'
22
22
  require 'json'
23
23
  require 'base64'
24
+ require 'wrong'
24
25
 
25
26
  require 'conjur/exists'
26
27
  require 'conjur/has_attributes'
@@ -38,7 +39,8 @@ module Conjur
38
39
  include LogSource
39
40
  include StandardMethods
40
41
  include Cast
41
-
42
+ include Wrong
43
+
42
44
  class << self
43
45
  # Parse a role id into [ account, 'roles', kind, id ]
44
46
  def parse_role_id(id)
@@ -107,9 +109,14 @@ module Conjur
107
109
  def host
108
110
  self.class.host
109
111
  end
110
-
112
+
111
113
  def token
114
+ @token = nil unless token_valid?
115
+
112
116
  @token ||= Conjur::API.authenticate(@username, @api_key)
117
+
118
+ assert { token_valid? }
119
+ return @token
113
120
  end
114
121
 
115
122
  # Authenticate the username and api_key to obtain a request token.
@@ -117,5 +124,15 @@ module Conjur
117
124
  def credentials
118
125
  { headers: { authorization: "Token token=\"#{Base64.strict_encode64 token.to_json}\"" }, username: username }
119
126
  end
127
+
128
+ private
129
+
130
+ def token_valid?
131
+ return false unless @token
132
+
133
+ # Actual token expiration is 8 minutes, but why cut it so close
134
+ expiration = 5.minutes
135
+ Time.now - Time.parse(@token['timestamp']) < expiration
136
+ end
120
137
  end
121
- end
138
+ end
@@ -68,8 +68,6 @@ module Conjur
68
68
  # @option options [Proc, *] :default Default value or proc to provide it
69
69
  # @option options [Boolean] :required (false) when true, raise an exception if the option is
70
70
  # not set
71
- # @option options [Boolean] :sticky (true) when false, default proc will be called every time,
72
- # otherwise the proc's result will be cached
73
71
  # @option options [Proc, #to_proc] :convert proc-ish to convert environment
74
72
  # values to appropriate types
75
73
  # @param [Proc] def_proc block to provide default values
@@ -77,7 +75,6 @@ module Conjur
77
75
  def add_option name, options = {}, &def_proc
78
76
  accepted_options << name
79
77
  allow_env = options[:env].nil? || options[:env]
80
- sticky = options.member?(:sticky) ? options[:sticky] : true
81
78
  env_var = options[:env] || "CONJUR_#{name.to_s.upcase}"
82
79
  def_val = options[:default]
83
80
  opt_name = name
@@ -108,9 +105,7 @@ module Conjur
108
105
  elsif allow_env && ENV.member?(env_var)
109
106
  instance_exec(ENV[env_var], &convert)
110
107
  else
111
- value = instance_eval(&def_proc)
112
- supplied[name] = value if sticky
113
- value
108
+ instance_eval(&def_proc)
114
109
  end
115
110
  end
116
111
  alias_method("#{name}?", name) if options[:boolean]
@@ -24,6 +24,7 @@ module Conjur
24
24
  class Resource < RestClient::Resource
25
25
  include HasAttributes
26
26
  include PathBased
27
+ include Exists
27
28
 
28
29
  def identifier
29
30
  match_path(3..-1)
@@ -52,17 +53,6 @@ module Conjur
52
53
  self.put(options)
53
54
  end
54
55
 
55
- def exists?(options = {})
56
- begin
57
- self.head(options)
58
- true
59
- rescue RestClient::Forbidden
60
- true
61
- rescue RestClient::ResourceNotFound
62
- false
63
- end
64
- end
65
-
66
56
  # Lists roles that have a specified permission on the resource.
67
57
  def permitted_roles(permission, options = {})
68
58
  JSON.parse RestClient::Resource.new(Conjur::Authz::API.host, self.options)["#{account}/roles/allowed_to/#{permission}/#{path_escape kind}/#{path_escape identifier}"].get(options)
@@ -7,18 +7,18 @@ describe Conjur::API do
7
7
  let(:password) { 'sikret' }
8
8
 
9
9
  before do
10
- Conjur::Authn::API.stub host: host
10
+ allow(Conjur::Authn::API).to receive_messages host: host
11
11
  end
12
12
 
13
13
  describe "::login" do
14
14
  it "gets /users/login" do
15
- RestClient::Request.should_receive(:execute).with(
15
+ expect(RestClient::Request).to receive(:execute).with(
16
16
  method: :get, url: "http://authn.example.com/users/login",
17
17
  user: user,
18
18
  password: password,
19
19
  headers: {}
20
20
  ).and_return(response = double)
21
- Conjur::API::login(user, password).should == response
21
+ expect(Conjur::API::login(user, password)).to eq(response)
22
22
  end
23
23
  end
24
24
 
@@ -28,30 +28,30 @@ describe Conjur::API do
28
28
 
29
29
  it "uses CasRestClient to authenticate" do
30
30
  stub_const 'CasRestClient', MockCasRestClient.new(double("response", body: response))
31
- Conjur::API.login_cas(user, password, cas_uri).should == response
32
- CasRestClient.options.should == {
31
+ expect(Conjur::API.login_cas(user, password, cas_uri)).to eq(response)
32
+ expect(CasRestClient.options).to eq({
33
33
  username: user,
34
34
  password: password,
35
35
  uri: "http://cas.example.com/v1/tickets",
36
36
  use_cookies: false
37
- }
38
- CasRestClient.url.should == "http://authn.example.com/users/login"
37
+ })
38
+ expect(CasRestClient.url).to eq("http://authn.example.com/users/login")
39
39
  end
40
40
  end
41
41
 
42
42
  describe "::authenticate" do
43
43
  it "posts the password and dejsons the result" do
44
- RestClient::Request.should_receive(:execute).with(
44
+ expect(RestClient::Request).to receive(:execute).with(
45
45
  method: :post, url: "http://authn.example.com/users/#{user}/authenticate",
46
46
  payload: password, headers: { content_type: 'text/plain' }
47
47
  ).and_return '{ "response": "foo"}'
48
- Conjur::API.authenticate(user, password).should == { 'response' => 'foo' }
48
+ expect(Conjur::API.authenticate(user, password)).to eq({ 'response' => 'foo' })
49
49
  end
50
50
  end
51
51
 
52
52
  describe "::update_password" do
53
53
  it "logs in and puts the new password" do
54
- RestClient::Request.should_receive(:execute).with(
54
+ expect(RestClient::Request).to receive(:execute).with(
55
55
  method: :put,
56
56
  url: "http://authn.example.com/users/password",
57
57
  user: user,
@@ -59,7 +59,7 @@ describe Conjur::API do
59
59
  payload: 'new-password',
60
60
  headers: { }
61
61
  ).and_return :response
62
- Conjur::API.update_password(user, password, 'new-password').should == :response
62
+ expect(Conjur::API.update_password(user, password, 'new-password')).to eq(:response)
63
63
  end
64
64
  end
65
65
  end
@@ -6,12 +6,12 @@ describe Conjur::API, api: :dummy do
6
6
  it "uses Net::HTTP to get something" do
7
7
  response = double "response",
8
8
  code: '200', body: 'foobar'
9
- response.stub(:[]).with('Content-Type').and_return 'text/whatever'
9
+ allow(response).to receive(:[]).with('Content-Type').and_return 'text/whatever'
10
10
 
11
11
  url = URI.parse "http://example.com"
12
- Net::HTTP.stub(:get_response).with(url).and_return response
12
+ allow(Net::HTTP).to receive(:get_response).with(url).and_return response
13
13
 
14
- Conjur::API.enroll_host("http://example.com").should == ['text/whatever', 'foobar']
14
+ expect(Conjur::API.enroll_host("http://example.com")).to eq(['text/whatever', 'foobar'])
15
15
  end
16
16
  end
17
17
 
@@ -7,7 +7,7 @@ describe Conjur::Layer do
7
7
  describe "#add_host" do
8
8
  it "casts Host to roleid" do
9
9
  host = double(:host)
10
- host.should_receive(:roleid).and_return "the-hostid"
10
+ expect(host).to receive(:roleid).and_return "the-hostid"
11
11
  stub_request(:post, "http://example.com/layers/my%2Flayername/hosts").with(hostid: "the-hostid")
12
12
 
13
13
  subject.add_host host
@@ -27,12 +27,12 @@ describe Conjur::API, api: :dummy do
27
27
  end
28
28
 
29
29
  before do
30
- Conjur::API.stub(pubkeys_asset_host: pubkeys_url)
30
+ allow(Conjur::API).to receive_messages(pubkeys_asset_host: pubkeys_url)
31
31
  end
32
32
 
33
33
  describe "#public_keys" do
34
34
  it "GETs /:username" do
35
- RestClient::Request.should_receive(:execute).with(
35
+ expect(RestClient::Request).to receive(:execute).with(
36
36
  url: pubkeys_url_for("bob"),
37
37
  method: :get,
38
38
  headers: credentials[:headers],
@@ -43,7 +43,7 @@ describe Conjur::API, api: :dummy do
43
43
 
44
44
  describe "#add_public_key" do
45
45
  it "POSTs /:username with the data" do
46
- RestClient::Request.should_receive(:execute).with(
46
+ expect(RestClient::Request).to receive(:execute).with(
47
47
  url: pubkeys_url_for("bob"),
48
48
  method: :post,
49
49
  headers: credentials[:headers],
@@ -55,7 +55,7 @@ describe Conjur::API, api: :dummy do
55
55
 
56
56
  describe "#delete_public_key" do
57
57
  it "DELETEs /:username/:keyname" do
58
- RestClient::Request.should_receive(:execute).with(
58
+ expect(RestClient::Request).to receive(:execute).with(
59
59
  url: pubkeys_url_for("bob", "bob-key"),
60
60
  method: :delete,
61
61
  headers: credentials[:headers]
@@ -3,21 +3,21 @@ require 'spec_helper'
3
3
  describe Conjur::API, api: :dummy do
4
4
  describe '#create_resource' do
5
5
  it "passes to resource#create" do
6
- api.stub(:resource).with(:id).and_return(resource = double)
7
- resource.should_receive :create
6
+ allow(api).to receive(:resource).with(:id).and_return(resource = double)
7
+ expect(resource).to receive :create
8
8
 
9
- api.create_resource(:id).should == resource
9
+ expect(api.create_resource(:id)).to eq(resource)
10
10
  end
11
11
  end
12
12
 
13
13
  describe '#resource' do
14
14
  it "builds a path and creates a resource from it" do
15
15
  res = api.resource "some-account:a-kind:the-id"
16
- res.url.should == "#{authz_host}/some-account/resources/a-kind/the-id"
16
+ expect(res.url).to eq("#{authz_host}/some-account/resources/a-kind/the-id")
17
17
  end
18
18
  it "accepts an account-less resource" do
19
19
  res = api.resource "a-kind:the-id"
20
- res.url.should == "#{authz_host}/#{account}/resources/a-kind/the-id"
20
+ expect(res.url).to eq("#{authz_host}/#{account}/resources/a-kind/the-id")
21
21
  end
22
22
  it "rejects an underspecified resource" do
23
23
  expect { api.resource "the-id" }.to raise_error(/at least two tokens in the-id/)
@@ -4,7 +4,7 @@ describe Conjur::API, api: :dummy do
4
4
  describe '#role_name_from_username' do
5
5
  subject { api }
6
6
  before {
7
- api.stub(:username) { username }
7
+ allow(api).to receive(:username) { username }
8
8
  }
9
9
  context "username is" do
10
10
  [
@@ -15,7 +15,11 @@ describe Conjur::API, api: :dummy do
15
15
  ].each do |p|
16
16
  context "'#{p[0]}'" do
17
17
  let(:username) { p[0] }
18
- its("role_name_from_username") { should == p[1] }
18
+
19
+ describe '#role_name_from_username' do
20
+ subject { super().role_name_from_username }
21
+ it { is_expected.to eq(p[1]) }
22
+ end
19
23
  end
20
24
  end
21
25
  end
@@ -11,7 +11,7 @@ describe Conjur::API, api: :dummy do
11
11
  describe 'user#update' do
12
12
  let(:userid) { "alice@wonderland" }
13
13
  it "PUTs to /users/:id?uidnumber=:uidnumber" do
14
- RestClient::Request.should_receive(:execute).with(
14
+ expect(RestClient::Request).to receive(:execute).with(
15
15
  method: :put,
16
16
  url: "#{core_host}/users/#{api.fully_escape(userid)}",
17
17
  headers: credentials[:headers],
@@ -28,7 +28,7 @@ describe Conjur::API, api: :dummy do
28
28
  let(:search_result) { ["someuser"].to_json }
29
29
 
30
30
  it "GETs /users/search with appropriate options, and returns parsed JSON response" do
31
- RestClient::Request.should_receive(:execute).with(
31
+ expect(RestClient::Request).to receive(:execute).with(
32
32
  method: :get,
33
33
  url: "#{core_host}/users/search?uidnumber=12345",
34
34
  headers: credentials[:headers]
@@ -36,9 +36,9 @@ describe Conjur::API, api: :dummy do
36
36
 
37
37
  parsed = double()
38
38
 
39
- JSON.should_receive(:parse).with(search_result).and_return(parsed)
39
+ expect(JSON).to receive(:parse).with(search_result).and_return(parsed)
40
40
 
41
- api.find_users(search_parameters).should == parsed
41
+ expect(api.find_users(search_parameters)).to eq(parsed)
42
42
  end
43
43
  end
44
44
 
@@ -25,11 +25,11 @@ describe Conjur::API, api: :dummy do
25
25
  shared_context "Stubbed API" do
26
26
  let (:expected_url) { "#{core_host}/variables/values?vars=#{varlist.map {|v| api.fully_escape(v) }.join(",")}" }
27
27
  before {
28
- RestClient::Request.should_receive(:execute).with(
28
+ expect(RestClient::Request).to receive(:execute).with(
29
29
  method: :get,
30
30
  url: expected_url,
31
31
  headers: credentials[:headers]
32
- ).and_return {
32
+ ) {
33
33
  if defined? return_error
34
34
  raise return_error
35
35
  else
@@ -46,8 +46,8 @@ describe Conjur::API, api: :dummy do
46
46
  let (:return_code) { '200' }
47
47
  let (:return_body) { '{"var/1":"val1","var/2":"val2","var/3":"val3"}' }
48
48
  it "returns Hash of values built from the response" do
49
- api.should_not_receive(:variable)
50
- invoke.should == { "var/1"=>"val1", "var/2"=>"val2", "var/3"=>"val3" }
49
+ expect(api).not_to receive(:variable)
50
+ expect(invoke).to eq({ "var/1"=>"val1", "var/2"=>"val2", "var/3"=>"val3" })
51
51
  end
52
52
  end
53
53
 
@@ -55,15 +55,15 @@ describe Conjur::API, api: :dummy do
55
55
  include_context "Stubbed API"
56
56
  let (:return_error) { RestClient::ResourceNotFound }
57
57
  before {
58
- api.should_receive(:variable).with("var/1").and_return(double(value:"val1_obtained_separately"))
59
- api.should_receive(:variable).with("var/2").and_return(double(value:"val2_obtained_separately"))
60
- api.should_receive(:variable).with("var/3").and_return(double(value:"val3_obtained_separately"))
58
+ expect(api).to receive(:variable).with("var/1").and_return(double(value:"val1_obtained_separately"))
59
+ expect(api).to receive(:variable).with("var/2").and_return(double(value:"val2_obtained_separately"))
60
+ expect(api).to receive(:variable).with("var/3").and_return(double(value:"val3_obtained_separately"))
61
61
  }
62
62
  it 'tries variables one by one and returns Hash of values' do
63
- invoke.should == { "var/1"=>"val1_obtained_separately",
63
+ expect(invoke).to eq({ "var/1"=>"val1_obtained_separately",
64
64
  "var/2"=>"val2_obtained_separately",
65
65
  "var/3"=>"val3_obtained_separately"
66
- }
66
+ })
67
67
  end
68
68
  end
69
69
 
@@ -71,7 +71,7 @@ describe Conjur::API, api: :dummy do
71
71
  include_context "Stubbed API"
72
72
  let (:return_error) { RestClient::Forbidden }
73
73
  it 're-raises error without checking particular variables' do
74
- api.should_not_receive(:variable)
74
+ expect(api).not_to receive(:variable)
75
75
  expect { invoke }.to raise_error(return_error)
76
76
  end
77
77
  end
@@ -23,7 +23,7 @@ describe Conjur::Annotations do
23
23
  let(:url){ "#{Conjur::Authz::API.host}/#{account}/annotations/#{kind}/#{identifier}" }
24
24
 
25
25
  def expect_put_request url, payload
26
- RestClient::Request.should_receive(:execute).with(
26
+ expect(RestClient::Request).to receive(:execute).with(
27
27
  method: :put,
28
28
  headers: {},
29
29
  url: url,
@@ -33,13 +33,13 @@ describe Conjur::Annotations do
33
33
 
34
34
  describe '[]' do
35
35
  it "returns annotations" do
36
- subject[:name].should == 'bar'
37
- subject[:comment].should == 'some comment'
38
- subject['comment'].should == subject[:comment]
36
+ expect(subject[:name]).to eq('bar')
37
+ expect(subject[:comment]).to eq('some comment')
38
+ expect(subject['comment']).to eq(subject[:comment])
39
39
  end
40
40
 
41
41
  it "caches the get result" do
42
- resource.should_receive(:attributes).exactly(1).times.and_return(attributes)
42
+ expect(resource).to receive(:attributes).exactly(1).times.and_return(attributes)
43
43
  subject[:name]
44
44
  subject[:name]
45
45
  end
@@ -49,23 +49,23 @@ describe Conjur::Annotations do
49
49
  it "yields each annotation pair" do
50
50
  pairs = []
51
51
  subject.each{|k,v| pairs << [k,v]}
52
- pairs.should == [[:name, 'bar'], [:comment, 'some comment']]
52
+ expect(pairs).to eq([[:name, 'bar'], [:comment, 'some comment']])
53
53
  end
54
54
  end
55
55
 
56
56
  it "is Enumerable" do
57
- subject.should be_a(Enumerable)
57
+ expect(subject).to be_a(Enumerable)
58
58
  end
59
59
 
60
60
  describe '#to_h' do
61
61
  it "returns the correct hash" do
62
- subject.to_h.should == {name: 'bar', comment: 'some comment'}
62
+ expect(subject.to_h).to eq({name: 'bar', comment: 'some comment'})
63
63
  end
64
64
  it "does not propagate modifications to the returned hash" do
65
- RestClient::Request.should_not_receive(:execute)
65
+ expect(RestClient::Request).not_to receive(:execute)
66
66
  subject.to_h[:name] = 'new name'
67
- subject[:name].should == subject.to_h[:name]
68
- subject[:name].should == "bar"
67
+ expect(subject[:name]).to eq(subject.to_h[:name])
68
+ expect(subject[:name]).to eq("bar")
69
69
  end
70
70
  end
71
71
 
@@ -76,7 +76,7 @@ describe Conjur::Annotations do
76
76
  hash.each do |k,v|
77
77
  expect_put_request(url, name: k, value: v)
78
78
  end
79
- resource.should_receive(:invalidate).exactly(hash.count).times.and_yield
79
+ expect(resource).to receive(:invalidate).exactly(hash.count).times.and_yield
80
80
  subject.merge! hash
81
81
  end
82
82
  end
@@ -85,20 +85,20 @@ describe Conjur::Annotations do
85
85
 
86
86
  it "makes a put request" do
87
87
  expect_put_request url, name: :blah, value: 'boo'
88
- resource.should_receive(:invalidate).and_yield
88
+ expect(resource).to receive(:invalidate).and_yield
89
89
  subject[:blah] = 'boo'
90
90
  end
91
91
 
92
92
  it "forces a fresh request for the annotations" do
93
93
  expect_put_request(url, name: :foo, value: 'bar')
94
- resource.should_receive(:attributes).exactly(2).times.and_return(attributes)
95
- resource.should_receive(:invalidate).and_yield
94
+ expect(resource).to receive(:attributes).exactly(2).times.and_return(attributes)
95
+ expect(resource).to receive(:invalidate).and_yield
96
96
  # One get request
97
- subject[:name].should == 'bar'
97
+ expect(subject[:name]).to eq('bar')
98
98
  # Update
99
99
  subject[:foo] = 'bar'
100
100
  # Second get request
101
- subject[:name].should == 'bar'
101
+ expect(subject[:name]).to eq('bar')
102
102
  end
103
103
  end
104
104