conjur-api 2.4.0 → 2.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/LICENSE +1 -1
- data/Rakefile +3 -1
- data/conjur-api.gemspec +3 -1
- data/lib/conjur-api/version.rb +1 -1
- data/lib/conjur/has_id.rb +1 -1
- data/lib/conjur/log.rb +6 -26
- data/lib/conjur/resource.rb +10 -1
- data/manual/asset/about.markdown +12 -0
- data/manual/asset/members.add.markdown +52 -0
- data/manual/asset/show.markdown +50 -0
- data/manual/group/about.markdown +6 -0
- data/manual/group/create.markdown +20 -0
- data/manual/host/about.markdown +23 -0
- data/manual/host/create.markdown +34 -0
- data/manual/host/enroll.markdown +21 -0
- data/manual/resource/about.markdown +11 -0
- data/manual/resource/create.markdown +29 -0
- data/manual/resource/deny.markdown +23 -0
- data/manual/resource/permit.markdown +35 -0
- data/manual/role/about.markdown +10 -0
- data/manual/role/members.markdown +40 -0
- data/manual/role/memberships.markdown +26 -0
- data/spec/api/authn_spec.rb +49 -0
- data/spec/api/groups_spec.rb +24 -0
- data/spec/api/hosts_spec.rb +29 -0
- data/spec/api/resources_spec.rb +19 -0
- data/spec/api/secrets_spec.rb +16 -0
- data/spec/api/users_spec.rb +16 -0
- data/spec/api/variables_spec.rb +14 -0
- data/spec/cas_rest_client.rb +17 -0
- data/spec/io_helper.rb +18 -0
- data/spec/lib/build_from_response_spec.rb +49 -0
- data/spec/lib/host_spec.rb +12 -8
- data/spec/lib/log_source_spec.rb +13 -0
- data/spec/lib/log_spec.rb +42 -0
- data/spec/lib/resource_spec.rb +98 -5
- data/spec/lib/role_grant_spec.rb +12 -0
- data/spec/lib/role_spec.rb +83 -3
- data/spec/lib/standard_methods_spec.rb +66 -0
- data/spec/lib/user_spec.rb +2 -1
- data/spec/spec_helper.rb +27 -0
- data/spec/standard_methods_helper.rb +30 -0
- data/spec/variable_spec.rb +41 -0
- metadata +71 -8
- data/.rvmrc +0 -1
@@ -0,0 +1,10 @@
|
|
1
|
+
Role
|
2
|
+
====
|
3
|
+
|
4
|
+
A role is a target to which permissions are assigned. Permitting an action on a resource by a role enables the role to perform
|
5
|
+
the specified action.
|
6
|
+
|
7
|
+
In addition, roles can be "granted to" other roles. When role "A" is granted to role "B", role "B" gains the ability to perform
|
8
|
+
all the actions permitted to "A". In addition, a role can be granted with "grant option". When role "A" is granted to role "B" with
|
9
|
+
grant option, role "B" can in turn grant role "A" to other roles.
|
10
|
+
|
@@ -0,0 +1,40 @@
|
|
1
|
+
Role#members
|
2
|
+
============
|
3
|
+
|
4
|
+
Lists the roles that have been the recipient of a role grant. The creator of the role is always a role member.
|
5
|
+
|
6
|
+
If role "A" is created by user "U" and then granted to roles "B" and "C", then the members of role "A" are [ "U", "B", "C" ].
|
7
|
+
|
8
|
+
Examples
|
9
|
+
--------
|
10
|
+
|
11
|
+
### Command Line
|
12
|
+
|
13
|
+
#### Add a role member and list the members
|
14
|
+
|
15
|
+
```bash
|
16
|
+
$ conjur role:create test:`conjur id:create`
|
17
|
+
Created https://authz-v3-conjur.herokuapp.com/sandbox/roles/test/2y1300
|
18
|
+
$ conjur role:members test:2y1300
|
19
|
+
[
|
20
|
+
"sandbox:user:kgilpin"
|
21
|
+
]
|
22
|
+
$ conjur host:create
|
23
|
+
{
|
24
|
+
"id": "w43699",
|
25
|
+
<snip>
|
26
|
+
}
|
27
|
+
$ conjur role:grant_to test:2y1300 host:w43699
|
28
|
+
Role granted
|
29
|
+
$ conjur role:members test:2y1300
|
30
|
+
[
|
31
|
+
"sandbox:user:kgilpin",
|
32
|
+
"sandbox:host:w43699"
|
33
|
+
]
|
34
|
+
```
|
35
|
+
|
36
|
+
#### The role argument is optional and defaults to the current role
|
37
|
+
|
38
|
+
```bash
|
39
|
+
$ conjur role:members
|
40
|
+
```
|
@@ -0,0 +1,26 @@
|
|
1
|
+
Role#memberships
|
2
|
+
================
|
3
|
+
|
4
|
+
List the roles that a role has been granted, transitively.
|
5
|
+
|
6
|
+
If role "A" is granted to role "B" which is granted to role "C", then the memberships of role "C" are [ "C", "B", "A" ].
|
7
|
+
|
8
|
+
Examples
|
9
|
+
--------
|
10
|
+
|
11
|
+
### Command Line
|
12
|
+
|
13
|
+
```bash
|
14
|
+
$ ns=`conjur id:create`
|
15
|
+
$ conjur role:create test:$ns/A
|
16
|
+
$ conjur role:create test:$ns/B
|
17
|
+
$ conjur role:create test:$ns/C
|
18
|
+
$ conjur role:grant_to test:$ns/A test:$ns/B
|
19
|
+
$ conjur role:grant_to test:$ns/B test:$ns/C
|
20
|
+
$ conjur role:memberships test:$ns/C
|
21
|
+
[
|
22
|
+
"sandbox:test:dy7mg0/C",
|
23
|
+
"sandbox:test:dy7mg0/B",
|
24
|
+
"sandbox:test:dy7mg0/A"
|
25
|
+
]
|
26
|
+
```
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'cas_rest_client'
|
3
|
+
|
4
|
+
describe Conjur::API do
|
5
|
+
let(:host) { 'http://authn.example.com' }
|
6
|
+
let(:user) { 'kmitnick' }
|
7
|
+
let(:password) { 'sikret' }
|
8
|
+
|
9
|
+
before do
|
10
|
+
Conjur::Authn::API.stub host: host
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "::login" do
|
14
|
+
it "gets /users/login" do
|
15
|
+
RestClient::Request.should_receive(:execute).with(
|
16
|
+
method: :get, url: "http://authn.example.com/users/login", user: user,
|
17
|
+
password: password, headers: {}
|
18
|
+
).and_return(response = double)
|
19
|
+
Conjur::API::login(user, password).should == response
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "::login_cas" do
|
24
|
+
let(:response) { "response body" }
|
25
|
+
let(:cas_uri) { 'http://cas.example.com' }
|
26
|
+
|
27
|
+
it "uses CasRestClient to authenticate" do
|
28
|
+
stub_const 'CasRestClient', MockCasRestClient.new(double("response", body: response))
|
29
|
+
Conjur::API.login_cas(user, password, cas_uri).should == response
|
30
|
+
CasRestClient.options.should == {
|
31
|
+
username: user,
|
32
|
+
password: password,
|
33
|
+
uri: "http://cas.example.com/v1/tickets",
|
34
|
+
use_cookies: false
|
35
|
+
}
|
36
|
+
CasRestClient.url.should == "http://authn.example.com/users/login"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "::authenticate" do
|
41
|
+
it "posts the password and dejsons the result" do
|
42
|
+
RestClient::Request.should_receive(:execute).with(
|
43
|
+
method: :post, url: "http://authn.example.com/users/#{user}/authenticate",
|
44
|
+
payload: password, headers: { content_type: 'text/plain' }
|
45
|
+
).and_return '{ "response": "foo"}'
|
46
|
+
Conjur::API.authenticate(user, password).should == { 'response' => 'foo' }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'standard_methods_helper'
|
3
|
+
|
4
|
+
describe Conjur::API, api: :dummy do
|
5
|
+
subject { api }
|
6
|
+
|
7
|
+
describe '#groups' do
|
8
|
+
it_should_behave_like 'standard_list with', :group, :options do
|
9
|
+
let(:invoke) { subject.groups :options }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#create_group' do
|
14
|
+
it_should_behave_like 'standard_create with', :group, :id, :options do
|
15
|
+
let(:invoke) { subject.create_group :id, :options }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '#group' do
|
20
|
+
it_should_behave_like 'standard_show with', :group, :id do
|
21
|
+
let(:invoke) { subject.group :id }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'standard_methods_helper'
|
3
|
+
|
4
|
+
describe Conjur::API, api: :dummy do
|
5
|
+
describe '::enroll_host' do
|
6
|
+
it "uses Net::HTTP to get something" do
|
7
|
+
response = double "response",
|
8
|
+
code: '200', body: 'foobar'
|
9
|
+
response.stub(:[]).with('Content-Type').and_return 'text/whatever'
|
10
|
+
|
11
|
+
url = URI.parse "http://example.com"
|
12
|
+
Net::HTTP.stub(:get_response).with(url).and_return response
|
13
|
+
|
14
|
+
Conjur::API.enroll_host("http://example.com").should == ['text/whatever', 'foobar']
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#create_host' do
|
19
|
+
it_should_behave_like "standard_create with", :host, nil, :options do
|
20
|
+
let(:invoke) { subject.create_host :options }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#host' do
|
25
|
+
it_should_behave_like "standard_show with", :host, :id do
|
26
|
+
let(:invoke) { subject.host :id }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Conjur::API, api: :dummy do
|
4
|
+
describe '#create_resource' do
|
5
|
+
it "passes to resource#create" do
|
6
|
+
api.stub(:resource).with(:id).and_return(resource = double)
|
7
|
+
resource.should_receive :create
|
8
|
+
|
9
|
+
api.create_resource(:id).should == resource
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#resource' do
|
14
|
+
it "builds a path and creates a resource from it" do
|
15
|
+
res = api.resource "some-account:a-kind:the-id"
|
16
|
+
res.url.should == "#{authz_host}/some-account/resources/a-kind/the-id"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'standard_methods_helper'
|
3
|
+
|
4
|
+
describe Conjur::API, api: :dummy do
|
5
|
+
describe '#create_secret' do
|
6
|
+
it_should_behave_like 'standard_create with', :secret, nil, value: 'val' do
|
7
|
+
let(:invoke) { api.create_secret 'val' }
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '#secret' do
|
12
|
+
it_should_behave_like 'standard_show with', :secret, :id do
|
13
|
+
let(:invoke) { api.secret :id }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'standard_methods_helper'
|
3
|
+
|
4
|
+
describe Conjur::API, api: :dummy do
|
5
|
+
describe '#create_user' do
|
6
|
+
it_should_behave_like 'standard_create with', :user, nil, login: 'login', other: true do
|
7
|
+
let(:invoke) { api.create_user 'login', other: true }
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '#user' do
|
12
|
+
it_should_behave_like 'standard_show with', :user, :login do
|
13
|
+
let(:invoke) { api.user :login }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'standard_methods_helper'
|
3
|
+
|
4
|
+
describe Conjur::API, api: :dummy do
|
5
|
+
describe '#create_variable' do
|
6
|
+
let(:invoke) { api.create_variable :type, :kind, other: true }
|
7
|
+
it_should_behave_like 'standard_create with', :variable, nil, mime_type: :type, kind: :kind, other: true
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '#variable' do
|
11
|
+
let(:invoke) { api.variable :id }
|
12
|
+
it_should_behave_like 'standard_show with', :variable, :id
|
13
|
+
end
|
14
|
+
end
|
data/spec/io_helper.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Conjur::BuildFromResponse do
|
4
|
+
describe "::build_from_response", logging: :temp do
|
5
|
+
let(:location) { "http://example.com" }
|
6
|
+
let(:attrs) {{ 'some' => 'foo', 'other' => 'bar' }}
|
7
|
+
let(:response) do
|
8
|
+
double "response", headers: { location: location }, body: attrs.to_json
|
9
|
+
end
|
10
|
+
subject { double "class", name: 'some' }
|
11
|
+
let(:constructed) { double "object" }
|
12
|
+
let(:credentials) { "whatever" }
|
13
|
+
|
14
|
+
before do
|
15
|
+
subject.extend Conjur::BuildFromResponse
|
16
|
+
subject.should_receive(:new).with(location, credentials).and_return constructed
|
17
|
+
constructed.should_receive(:attributes=).with attrs
|
18
|
+
|
19
|
+
constructed.extend Conjur::LogSource
|
20
|
+
constructed.stub username: 'whatever'
|
21
|
+
end
|
22
|
+
|
23
|
+
it "passes the location credentials and attributes" do
|
24
|
+
subject.build_from_response response, credentials
|
25
|
+
end
|
26
|
+
|
27
|
+
context "with a resource(-ish) class" do
|
28
|
+
before do
|
29
|
+
constructed.stub resource_kind: 'chunky', resource_id: 'bacon'
|
30
|
+
end
|
31
|
+
|
32
|
+
it "logs creation correctly" do
|
33
|
+
subject.build_from_response response, credentials
|
34
|
+
log.should =~ /Created chunky bacon/
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context "with a id(-ish) class" do
|
39
|
+
before do
|
40
|
+
constructed.stub id: 'bacon'
|
41
|
+
end
|
42
|
+
|
43
|
+
it "logs creation correctly" do
|
44
|
+
subject.build_from_response response, credentials
|
45
|
+
log.should =~ /Created some bacon/
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/spec/lib/host_spec.rb
CHANGED
@@ -1,14 +1,18 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Conjur::Host do
|
4
|
-
|
5
|
-
let(:api_key) { 'the-api-key' }
|
6
|
-
let(:credentials) { { user: login, password: api_key } }
|
7
|
-
let(:account) { 'test-account' }
|
3
|
+
describe Conjur::Host, api: :dummy do
|
4
|
+
subject { Conjur::Host.new 'http://example.com/hosts/my/hostname', nil }
|
8
5
|
|
9
|
-
|
6
|
+
its(:resource) { should be }
|
7
|
+
its(:login) { should == 'host/my/hostname' }
|
10
8
|
|
11
|
-
|
9
|
+
let(:api_key) { 'theapikey' }
|
10
|
+
before { subject.attributes = { 'api_key' => api_key } }
|
11
|
+
its(:api_key) { should == api_key }
|
12
12
|
|
13
|
-
|
13
|
+
it "fetches enrollment_url" do
|
14
|
+
stub_request(:head, "http://example.com/hosts/my/hostname/enrollment_url").
|
15
|
+
to_return(:status => 200, :headers => {location: 'foo'})
|
16
|
+
subject.enrollment_url.should == 'foo'
|
17
|
+
end
|
14
18
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'io_helper'
|
3
|
+
require 'tempfile'
|
4
|
+
|
5
|
+
describe Conjur do
|
6
|
+
describe '::log=' do
|
7
|
+
before { @old_log = Conjur.log }
|
8
|
+
let(:log) { double 'log' }
|
9
|
+
it "creates the log with given type and makes it available" do
|
10
|
+
Conjur.stub(:create_log).with(:param).and_return log
|
11
|
+
Conjur::log = :param
|
12
|
+
Conjur::log.should == log
|
13
|
+
end
|
14
|
+
after { Conjur.class_variable_set :@@log, @old_log }
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '::create_log' do
|
18
|
+
let(:log) { Conjur::create_log param }
|
19
|
+
context "with 'stdout'" do
|
20
|
+
let(:param) { 'stdout' }
|
21
|
+
it "creates something which writes to STDOUT" do
|
22
|
+
STDOUT.grab { log << "foo" }.should == 'foo'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context "with 'stderr'" do
|
27
|
+
let(:param) { 'stderr' }
|
28
|
+
it "creates something which writes to STDERR" do
|
29
|
+
STDERR.grab { log << "foo" }.should == 'foo'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context "with a filename" do
|
34
|
+
let(:tempfile) { Tempfile.new 'spec' }
|
35
|
+
let(:param) { tempfile.path }
|
36
|
+
it "creates something which writes to the file" do
|
37
|
+
log << "foo"
|
38
|
+
tempfile.read.should == "foo"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/spec/lib/resource_spec.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Conjur::Resource do
|
3
|
+
describe Conjur::Resource, api: :dummy, logging: :temp do
|
4
4
|
let(:account) { "the-account" }
|
5
5
|
let(:uuid) { "ddd1f59a-494d-48fb-b045-0374c4a6eef9" }
|
6
|
-
|
6
|
+
|
7
7
|
context "identifier" do
|
8
8
|
include Conjur::Escape
|
9
9
|
let(:resource) { Conjur::Resource.new("#{Conjur::Authz::API.host}/#{account}/resources/#{kind}/#{path_escape identifier}") }
|
10
|
-
|
10
|
+
|
11
11
|
context "Object with an #id" do
|
12
12
|
let(:kind) { "host" }
|
13
13
|
let(:identifier) do
|
@@ -17,7 +17,7 @@ describe Conjur::Resource do
|
|
17
17
|
resource.identifier.should == "foobar"
|
18
18
|
end
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
[ [ "foo", "bar/baz" ], [ "f:o", "bar" ], [ "@f", "bar.baz" ], [ "@f", "bar baz" ], [ "@f", "@:bar/baz" ] ].each do |p|
|
22
22
|
context "of /#{p[0]}/#{p[1]}" do
|
23
23
|
let(:kind) { p[0] }
|
@@ -33,4 +33,97 @@ describe Conjur::Resource do
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
|
+
let(:uri) { "#{authz_host}/some-account/resources/the-kind/resource-id" }
|
38
|
+
subject { Conjur::Resource.new uri }
|
39
|
+
|
40
|
+
describe '#create' do
|
41
|
+
it "simply puts" do
|
42
|
+
RestClient::Request.should_receive(:execute).with(
|
43
|
+
method: :put,
|
44
|
+
url: uri,
|
45
|
+
payload: {},
|
46
|
+
headers: {}
|
47
|
+
).and_return "new resource"
|
48
|
+
subject.create.should == "new resource"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe '#permitted_roles' do
|
53
|
+
it 'gets the list from /roles/allowed_to' do
|
54
|
+
RestClient::Request.should_receive(:execute).with(
|
55
|
+
method: :get,
|
56
|
+
url: "http://authz.example.com/some-account/roles/allowed_to/nuke/the-kind/resource-id",
|
57
|
+
headers: {}
|
58
|
+
).and_return '["foo", "bar"]'
|
59
|
+
|
60
|
+
subject.permitted_roles("nuke").should == ['foo', 'bar']
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe '#give_to' do
|
65
|
+
it "puts the owner field" do
|
66
|
+
RestClient::Request.should_receive(:execute).with(
|
67
|
+
method: :put,
|
68
|
+
url: uri,
|
69
|
+
payload: {owner: 'new-owner' },
|
70
|
+
headers: {}
|
71
|
+
)
|
72
|
+
|
73
|
+
subject.give_to 'new-owner'
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe '#delete' do
|
78
|
+
it 'simply deletes' do
|
79
|
+
RestClient::Request.should_receive(:execute).with(
|
80
|
+
method: :delete,
|
81
|
+
url: uri,
|
82
|
+
headers: {}
|
83
|
+
)
|
84
|
+
|
85
|
+
subject.delete
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe '#permit' do
|
90
|
+
it 'posts permit for every privilege' do
|
91
|
+
privileges = [:nuke, :fry]
|
92
|
+
privileges.each do |p|
|
93
|
+
RestClient::Request.should_receive(:execute).with(
|
94
|
+
method: :post,
|
95
|
+
url: uri + "/?permit&privilege=#{p}&role=dr-strangelove",
|
96
|
+
headers: {},
|
97
|
+
payload: {}
|
98
|
+
)
|
99
|
+
end
|
100
|
+
subject.permit privileges, "dr-strangelove"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe '#deny' do
|
105
|
+
it 'posts deny for every privilege' do
|
106
|
+
privileges = [:nuke, :fry]
|
107
|
+
privileges.each do |p|
|
108
|
+
RestClient::Request.should_receive(:execute).with(
|
109
|
+
method: :post,
|
110
|
+
url: uri + "/?deny&privilege=#{p}&role=james-bond",
|
111
|
+
headers: {},
|
112
|
+
payload: {}
|
113
|
+
)
|
114
|
+
end
|
115
|
+
subject.deny privileges, "james-bond"
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe '#permitted?' do
|
120
|
+
it 'gets the ?permitted? action' do
|
121
|
+
RestClient::Request.should_receive(:execute).with(
|
122
|
+
method: :get,
|
123
|
+
url: uri + "/?check&privilege=fry",
|
124
|
+
headers: {}
|
125
|
+
)
|
126
|
+
subject.permitted? 'fry'
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|