conjur-api 4.6.1 → 4.7.1
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.
- data/lib/conjur-api/version.rb +1 -1
- data/lib/conjur/annotations.rb +78 -0
- data/lib/conjur/api.rb +13 -0
- data/lib/conjur/api/resources.rb +4 -1
- data/lib/conjur/resource.rb +16 -2
- data/spec/api/resources_spec.rb +2 -2
- data/spec/lib/annotations_spec.rb +102 -0
- data/spec/lib/api_spec.rb +9 -0
- data/spec/lib/resource_spec.rb +10 -0
- data/spec/spec_helper.rb +1 -0
- metadata +6 -3
data/lib/conjur-api/version.rb
CHANGED
@@ -0,0 +1,78 @@
|
|
1
|
+
module Conjur
|
2
|
+
# An Annotations instance acts like a Hash: you can fetch an annotation
|
3
|
+
# with '[]' and update with '[]=', 'each' it, and 'merge!' to do bulk updates
|
4
|
+
# (although merge! is not more efficient than setting each pair with '[]=').
|
5
|
+
class Annotations
|
6
|
+
include Enumerable
|
7
|
+
|
8
|
+
# @api private
|
9
|
+
def initialize resource
|
10
|
+
@resource = resource
|
11
|
+
end
|
12
|
+
|
13
|
+
# Get the value of the annotation with the given name
|
14
|
+
# @param [String,Symbol] name the annotation name, indifferent to whether it's
|
15
|
+
# a String or Symbol.
|
16
|
+
def [] name
|
17
|
+
annotations_hash[name.to_sym]
|
18
|
+
end
|
19
|
+
|
20
|
+
# Set an annotation value
|
21
|
+
# @param [String, Symbol] name the annotation name
|
22
|
+
# @param [String] value the annotation value
|
23
|
+
def []= name, value
|
24
|
+
update_annotation name, value
|
25
|
+
value
|
26
|
+
end
|
27
|
+
|
28
|
+
# Enumerate all annotations, yielding key,value pairs.
|
29
|
+
# @return [Conjur::Annotations] self
|
30
|
+
def each &blk
|
31
|
+
annotations_hash.each &blk
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
# Set annotations from key,value pairs in +hash+
|
36
|
+
# @param [#each] hash
|
37
|
+
# @return [Conjur::Annotations] self
|
38
|
+
def merge! hash
|
39
|
+
hash.each{|k,v| self[k] = v }
|
40
|
+
self
|
41
|
+
end
|
42
|
+
|
43
|
+
# Return a proper hash containing a +copy+ of ourself. Note that
|
44
|
+
# updates to this hash have no effect on the actual annotations.
|
45
|
+
# @return [Hash]
|
46
|
+
def to_h
|
47
|
+
annotations_hash.dup
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_s
|
51
|
+
annotations_hash.to_s
|
52
|
+
end
|
53
|
+
|
54
|
+
def inspect
|
55
|
+
"<Annotations for #{@resource.resourceid}: #{to_s}>"
|
56
|
+
end
|
57
|
+
|
58
|
+
protected
|
59
|
+
|
60
|
+
def update_annotation name, value
|
61
|
+
@annotations_hash = nil
|
62
|
+
path = [@resource.account,'annotations', @resource.kind, @resource.identifier].join '/'
|
63
|
+
RestClient::Resource.new(Conjur::Authz::API.host, @resource.options)[path].put name: name, value: value
|
64
|
+
end
|
65
|
+
|
66
|
+
def annotations_hash
|
67
|
+
@annotations_hash ||= fetch_annotations
|
68
|
+
end
|
69
|
+
|
70
|
+
def fetch_annotations
|
71
|
+
{}.tap do |hash|
|
72
|
+
JSON.parse(@resource.get)['annotations'].each do |annotation|
|
73
|
+
hash[annotation['name'].to_sym] = annotation['value']
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
data/lib/conjur/api.rb
CHANGED
@@ -51,6 +51,19 @@ class RestClient::Resource
|
|
51
51
|
{}
|
52
52
|
end
|
53
53
|
|
54
|
+
def conjur_api
|
55
|
+
Conjur::API.new_from_token token
|
56
|
+
end
|
57
|
+
|
58
|
+
def token
|
59
|
+
authorization = options[:headers][:authorization]
|
60
|
+
if authorization && authorization.to_s[/^Token token="(.*)"/]
|
61
|
+
JSON.parse(Base64.decode64($1))
|
62
|
+
else
|
63
|
+
raise AuthorizationError.new("Authorization missing")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
54
67
|
def username
|
55
68
|
options[:user] || options[:username]
|
56
69
|
end
|
data/lib/conjur/api/resources.rb
CHANGED
@@ -35,7 +35,10 @@ module Conjur
|
|
35
35
|
# Return all visible resources.
|
36
36
|
# In opts you should pass an account to filter by, and optionally a kind.
|
37
37
|
def resources opts = {}
|
38
|
-
|
38
|
+
opts = { host: Conjur::Authz::API.host, credentials: credentials }.merge opts
|
39
|
+
opts[:account] ||= Conjur.account
|
40
|
+
|
41
|
+
Resource.all(opts).map do |result|
|
39
42
|
resource(result['id']).tap do |r|
|
40
43
|
r.attributes = result
|
41
44
|
end
|
data/lib/conjur/resource.rb
CHANGED
@@ -18,6 +18,8 @@
|
|
18
18
|
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
19
19
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
20
20
|
#
|
21
|
+
require 'conjur/annotations'
|
22
|
+
|
21
23
|
module Conjur
|
22
24
|
class Resource < RestClient::Resource
|
23
25
|
include Exists
|
@@ -106,6 +108,12 @@ module Conjur
|
|
106
108
|
rescue RestClient::ResourceNotFound
|
107
109
|
false
|
108
110
|
end
|
111
|
+
|
112
|
+
# Return a Conjur::Annotations instance to read and manipulate our annotations.
|
113
|
+
def annotations
|
114
|
+
@annotations ||= Conjur::Annotations.new(self)
|
115
|
+
end
|
116
|
+
alias tags annotations
|
109
117
|
|
110
118
|
# Returns all resources (optionally qualified by kind)
|
111
119
|
# visible to the user with given credentials.
|
@@ -113,16 +121,22 @@ module Conjur
|
|
113
121
|
# - host - authz url,
|
114
122
|
# - credentials,
|
115
123
|
# - account,
|
116
|
-
# - kind (optional)
|
124
|
+
# - kind (optional),
|
125
|
+
# - search (optional),
|
126
|
+
# - limit (optional),
|
127
|
+
# - offset (optional).
|
117
128
|
def self.all opts = {}
|
118
129
|
host, credentials, account, kind = opts.values_at(*[:host, :credentials, :account, :kind])
|
119
130
|
fail ArgumentError, "host and account are required" unless [host, account].all?
|
120
131
|
|
121
132
|
credentials ||= {}
|
122
133
|
|
123
|
-
path = "#{account}/resources"
|
134
|
+
path = "#{account}/resources"
|
124
135
|
path += "/#{kind}" if kind
|
136
|
+
query = opts.slice(:acting_as, :limit, :offset, :search)
|
137
|
+
path += "?#{query.to_query}" unless query.empty?
|
125
138
|
resource = RestClient::Resource.new(host, credentials)[path]
|
139
|
+
|
126
140
|
JSON.parse resource.get
|
127
141
|
end
|
128
142
|
|
data/spec/api/resources_spec.rb
CHANGED
@@ -33,13 +33,13 @@ describe Conjur::API, api: :dummy do
|
|
33
33
|
}
|
34
34
|
it "lists all resources" do
|
35
35
|
expect(Conjur::Resource).to receive(:all)
|
36
|
-
.with(host: authz_host, credentials: api.credentials).and_return(resources)
|
36
|
+
.with(host: authz_host, account: account, credentials: api.credentials).and_return(resources)
|
37
37
|
|
38
38
|
expect(api.resources.map(&:url)).to eql(ids.map { |id| api.resource(id).url })
|
39
39
|
end
|
40
40
|
it "can filter by kind" do
|
41
41
|
expect(Conjur::Resource).to receive(:all)
|
42
|
-
.with(host: authz_host, credentials: api.credentials, kind: :chunky).and_return(resources)
|
42
|
+
.with(host: authz_host, account: account, credentials: api.credentials, kind: :chunky).and_return(resources)
|
43
43
|
|
44
44
|
expect(api.resources(kind: :chunky).map(&:url)).to eql(ids.map { |id| api.resource(id).url })
|
45
45
|
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Conjur::Annotations do
|
4
|
+
let(:identifier){ 'the-resource-id' }
|
5
|
+
let(:kind){ 'some-kind' }
|
6
|
+
let(:account){ 'the-account' }
|
7
|
+
let(:resourceid){ [account, kind, identifier].join ':'}
|
8
|
+
let(:options){ { } }
|
9
|
+
let(:raw_annotations){ [{'name' => 'name', 'value' => 'bar'},
|
10
|
+
{'name' => 'comment', 'value' => 'some comment'}] }
|
11
|
+
let(:resource_hash){ { 'annotations' => raw_annotations } }
|
12
|
+
let(:resource){
|
13
|
+
double('resource', account: account,
|
14
|
+
kind: kind, identifier: identifier,
|
15
|
+
options: options, resourceid: resourceid,
|
16
|
+
get: resource_hash.to_json)
|
17
|
+
}
|
18
|
+
let(:annotations){ Conjur::Annotations.new(resource) }
|
19
|
+
|
20
|
+
subject{ annotations }
|
21
|
+
|
22
|
+
|
23
|
+
let(:url){ "#{Conjur::Authz::API.host}/#{account}/annotations/#{kind}/#{identifier}" }
|
24
|
+
|
25
|
+
def expect_put_request url, payload
|
26
|
+
RestClient::Request.should_receive(:execute).with(
|
27
|
+
method: :put,
|
28
|
+
headers: {},
|
29
|
+
url: url,
|
30
|
+
payload: payload
|
31
|
+
)
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '[]' do
|
35
|
+
it "returns annotations" do
|
36
|
+
subject[:name].should == 'bar'
|
37
|
+
subject[:comment].should == 'some comment'
|
38
|
+
subject['comment'].should == subject[:comment]
|
39
|
+
end
|
40
|
+
|
41
|
+
it "caches the get result" do
|
42
|
+
resource.should_receive(:get).exactly(1).times.and_return(resource_hash.to_json)
|
43
|
+
subject[:name]
|
44
|
+
subject[:name]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe '#each' do
|
49
|
+
it "yields each annotation pair" do
|
50
|
+
pairs = []
|
51
|
+
subject.each{|k,v| pairs << [k,v]}
|
52
|
+
pairs.should == [[:name, 'bar'], [:comment, 'some comment']]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
it "is Enumerable" do
|
57
|
+
subject.should be_a(Enumerable)
|
58
|
+
end
|
59
|
+
|
60
|
+
describe '#to_h' do
|
61
|
+
it "returns the correct hash" do
|
62
|
+
subject.to_h.should == {name: 'bar', comment: 'some comment'}
|
63
|
+
end
|
64
|
+
it "does not propagate modifications to the returned hash" do
|
65
|
+
RestClient::Request.should_not_receive(:execute)
|
66
|
+
subject.to_h[:name] = 'new name'
|
67
|
+
subject[:name].should == subject.to_h[:name]
|
68
|
+
subject[:name].should == "bar"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "#merge!" do
|
73
|
+
let(:hash){ {blah: 'blahbah', zelda: 'link'} }
|
74
|
+
|
75
|
+
it "makes a put request for each pair" do
|
76
|
+
hash.each do |k,v|
|
77
|
+
expect_put_request(url, name: k, value: v)
|
78
|
+
end
|
79
|
+
subject.merge! hash
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe '[]=' do
|
84
|
+
|
85
|
+
it "makes a put request" do
|
86
|
+
expect_put_request url, name: :blah, value: 'boo'
|
87
|
+
subject[:blah] = 'boo'
|
88
|
+
end
|
89
|
+
|
90
|
+
it "forces a fresh request for the annotations" do
|
91
|
+
expect_put_request(url, name: :foo, value: 'bar')
|
92
|
+
resource.should_receive(:get).exactly(2).times.and_return(resource_hash.to_json)
|
93
|
+
# One get request
|
94
|
+
subject[:name].should == 'bar'
|
95
|
+
# Update
|
96
|
+
subject[:foo] = 'bar'
|
97
|
+
# Second get request
|
98
|
+
subject[:name].should == 'bar'
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
data/spec/lib/api_spec.rb
CHANGED
@@ -214,6 +214,15 @@ describe Conjur::API do
|
|
214
214
|
api.credentials.should == { headers: { authorization: "Token token=\"#{Base64.strict_encode64(token.to_json)}\"" }, username: login }
|
215
215
|
end
|
216
216
|
end
|
217
|
+
context "from logged-in RestClient::Resource" do
|
218
|
+
let(:token_encoded) { Base64.strict_encode64(token.to_json) }
|
219
|
+
let(:resource) { RestClient::Resource.new("http://example.com", { headers: { authorization: "Token token=\"#{token_encoded}\"" } })}
|
220
|
+
it "can construct a new API instance" do
|
221
|
+
api = resource.conjur_api
|
222
|
+
api.credentials[:headers][:authorization].should == "Token token=\"#{token_encoded}\""
|
223
|
+
api.credentials[:username].should == "bob"
|
224
|
+
end
|
225
|
+
end
|
217
226
|
end
|
218
227
|
|
219
228
|
describe "#role_from_username", logged_in: true do
|
data/spec/lib/resource_spec.rb
CHANGED
@@ -148,6 +148,16 @@ describe Conjur::Resource, api: :dummy, logging: :temp do
|
|
148
148
|
expect(Conjur::Resource.all host: authz_host, account: account, kind: :chunky)
|
149
149
|
.to eql(%w(foo bar))
|
150
150
|
end
|
151
|
+
|
152
|
+
it "passes search, limit, and offset params" do
|
153
|
+
RestClient::Request.should_receive(:execute).with(
|
154
|
+
method: :get,
|
155
|
+
# Note that to_query sorts the keys
|
156
|
+
url: "http://authz.example.com/the-account/resources?limit=5&offset=6&search=something",
|
157
|
+
headers: {}
|
158
|
+
).and_return '["foo", "bar"]'
|
159
|
+
Conjur::Resource.all(host: authz_host, account: account, search: 'something', limit:5, offset:6).should == %w(foo bar)
|
160
|
+
end
|
151
161
|
|
152
162
|
it "uses the given authz url" do
|
153
163
|
RestClient::Request.should_receive(:execute).with(
|
data/spec/spec_helper.rb
CHANGED
@@ -105,6 +105,7 @@ shared_context api: :dummy do
|
|
105
105
|
Conjur::Core::API.stub host: core_host
|
106
106
|
Conjur::Core::API.stub conjur_account: account
|
107
107
|
Conjur::Audit::API.stub host:audit_host
|
108
|
+
Conjur.configuration.set :account, account
|
108
109
|
api.stub credentials: credentials
|
109
110
|
end
|
110
111
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: conjur-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.7.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2014-
|
13
|
+
date: 2014-03-14 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rest-client
|
@@ -214,6 +214,7 @@ files:
|
|
214
214
|
- lib/conjur/acts_as_resource.rb
|
215
215
|
- lib/conjur/acts_as_role.rb
|
216
216
|
- lib/conjur/acts_as_user.rb
|
217
|
+
- lib/conjur/annotations.rb
|
217
218
|
- lib/conjur/api.rb
|
218
219
|
- lib/conjur/api/audit.rb
|
219
220
|
- lib/conjur/api/authn.rb
|
@@ -262,6 +263,7 @@ files:
|
|
262
263
|
- spec/api/users_spec.rb
|
263
264
|
- spec/api/variables_spec.rb
|
264
265
|
- spec/cas_rest_client.rb
|
266
|
+
- spec/lib/annotations_spec.rb
|
265
267
|
- spec/lib/api_spec.rb
|
266
268
|
- spec/lib/asset_spec.rb
|
267
269
|
- spec/lib/audit_spec.rb
|
@@ -304,7 +306,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
304
306
|
version: '0'
|
305
307
|
segments:
|
306
308
|
- 0
|
307
|
-
hash:
|
309
|
+
hash: 1666526476905320839
|
308
310
|
requirements: []
|
309
311
|
rubyforge_project:
|
310
312
|
rubygems_version: 1.8.25
|
@@ -325,6 +327,7 @@ test_files:
|
|
325
327
|
- spec/api/users_spec.rb
|
326
328
|
- spec/api/variables_spec.rb
|
327
329
|
- spec/cas_rest_client.rb
|
330
|
+
- spec/lib/annotations_spec.rb
|
328
331
|
- spec/lib/api_spec.rb
|
329
332
|
- spec/lib/asset_spec.rb
|
330
333
|
- spec/lib/audit_spec.rb
|