conjur-api 4.10.1 → 4.10.2

Sign up to get free protection for your applications and to get access to all the features.
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