conjur-cli 4.1.1 → 4.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.githooks/pre_commit/run_specs.rb +23 -0
- data/.gitignore +1 -1
- data/Gemfile +0 -1
- data/conjur.gemspec +1 -0
- data/features/dsl_context.feature +36 -0
- data/features/dsl_host_create.feature +11 -0
- data/features/dsl_ownership.feature +30 -0
- data/features/dsl_permission.feature +45 -0
- data/features/dsl_resource_create.feature +23 -0
- data/features/dsl_role_create.feature +11 -0
- data/features/dsl_user_create.feature +23 -0
- data/features/step_definitions/dsl_steps.rb +46 -0
- data/features/support/env.rb +1 -0
- data/features/support/hooks.rb +117 -0
- data/lib/conjur/cli.rb +17 -17
- data/lib/conjur/command.rb +2 -26
- data/lib/conjur/command/assets.rb +3 -12
- data/lib/conjur/command/audit.rb +64 -0
- data/lib/conjur/command/groups.rb +3 -4
- data/lib/conjur/command/script.rb +63 -0
- data/lib/conjur/config.rb +23 -0
- data/lib/conjur/dsl/runner.rb +197 -0
- data/lib/conjur/identifier_manipulation.rb +29 -0
- data/lib/conjur/version.rb +1 -1
- data/spec/command/assets_spec.rb +13 -32
- data/spec/command/audit_spec.rb +100 -0
- data/spec/spec_helper.rb +9 -8
- metadata +43 -4
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'English'
|
2
|
+
|
3
|
+
module Overcommit::GitHook
|
4
|
+
# Try to avoid commiting code which breaks specs.
|
5
|
+
# Install the hook with `overcommit .` in the top directory.
|
6
|
+
class SpecsPass < HookSpecificCheck
|
7
|
+
include HookRegistry
|
8
|
+
file_types :rb
|
9
|
+
|
10
|
+
def run_check
|
11
|
+
unless in_path?('rspec')
|
12
|
+
return :warn, 'rspec not installed -- run `gem install rspec`'
|
13
|
+
end
|
14
|
+
|
15
|
+
output = `rspec 2>&1`
|
16
|
+
if $CHILD_STATUS.exitstatus == 0
|
17
|
+
return :good
|
18
|
+
else
|
19
|
+
return :bad, output
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/conjur.gemspec
CHANGED
@@ -0,0 +1,36 @@
|
|
1
|
+
@dsl
|
2
|
+
Feature: Saving and restoring context
|
3
|
+
|
4
|
+
Background:
|
5
|
+
|
6
|
+
Scenario: Environment and api keys are saved in the context
|
7
|
+
When I run script:
|
8
|
+
"""
|
9
|
+
namespace do
|
10
|
+
user "bob"
|
11
|
+
end
|
12
|
+
"""
|
13
|
+
Then the context should contain "env"
|
14
|
+
And the context should contain "namespace"
|
15
|
+
And the context should contain "stack"
|
16
|
+
And the context should contain "account"
|
17
|
+
And the context should contain "api_keys"
|
18
|
+
And the context "api_keys" should contain "1" item
|
19
|
+
|
20
|
+
Scenario: API keys are restored from the context
|
21
|
+
When I use script context:
|
22
|
+
"""
|
23
|
+
{
|
24
|
+
"namespace": "foobar",
|
25
|
+
"api_keys": [
|
26
|
+
"the-api-key"
|
27
|
+
]
|
28
|
+
}
|
29
|
+
"""
|
30
|
+
And I run script:
|
31
|
+
"""
|
32
|
+
namespace
|
33
|
+
"""
|
34
|
+
Then the context "namespace" should be "foobar"
|
35
|
+
And the context "api_keys" should contain "1" item
|
36
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
@dsl
|
2
|
+
Feature: Assigning ownership
|
3
|
+
|
4
|
+
Background:
|
5
|
+
|
6
|
+
Scenario: Create without ownership
|
7
|
+
When I run script:
|
8
|
+
"""
|
9
|
+
role "user", "bob"
|
10
|
+
"""
|
11
|
+
Then the "role" "cucumber:user:bob" should not have an owner
|
12
|
+
|
13
|
+
Scenario: Create with explicit ownership
|
14
|
+
When I run script:
|
15
|
+
"""
|
16
|
+
role "user", "bob", ownerid: "foobar"
|
17
|
+
"""
|
18
|
+
Then the "role" "cucumber:user:bob" should be owned by "foobar"
|
19
|
+
|
20
|
+
Scenario: Create with scoped ownership
|
21
|
+
When I run script:
|
22
|
+
"""
|
23
|
+
role "user", "bob" do
|
24
|
+
owns do
|
25
|
+
resource "food", "bacon"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
"""
|
29
|
+
Then the "resource" "cucumber:food:bacon" should be owned by "cucumber:user:bob"
|
30
|
+
|
@@ -0,0 +1,45 @@
|
|
1
|
+
@dsl
|
2
|
+
Feature: Manpipulating permissions
|
3
|
+
|
4
|
+
Background:
|
5
|
+
|
6
|
+
Scenario: Permit using Role#can
|
7
|
+
When I run script:
|
8
|
+
"""
|
9
|
+
bacon = resource "food", "bacon"
|
10
|
+
role "user", "bob" do
|
11
|
+
can "fry", bacon
|
12
|
+
end
|
13
|
+
"""
|
14
|
+
Then "cucumber:user:bob" can "fry" "cucumber:food:bacon"
|
15
|
+
|
16
|
+
Scenario: Permit using Role#can with grant option
|
17
|
+
When I run script:
|
18
|
+
"""
|
19
|
+
bacon = resource "food", "bacon"
|
20
|
+
role "user", "bob" do
|
21
|
+
can "fry", bacon, grant_option: true
|
22
|
+
end
|
23
|
+
"""
|
24
|
+
Then "cucumber:user:bob" can "fry" "cucumber:food:bacon" with grant option
|
25
|
+
|
26
|
+
Scenario: Permit using Resource#permit
|
27
|
+
When I run script:
|
28
|
+
"""
|
29
|
+
bob = role "user", "bob"
|
30
|
+
resource "food", "bacon" do
|
31
|
+
permit "fry", bob
|
32
|
+
end
|
33
|
+
"""
|
34
|
+
Then "cucumber:user:bob" can "fry" "cucumber:food:bacon"
|
35
|
+
|
36
|
+
Scenario: Permit using Resource#permit with grant option
|
37
|
+
When I run script:
|
38
|
+
"""
|
39
|
+
bob = role "user", "bob"
|
40
|
+
resource "food", "bacon" do
|
41
|
+
permit "fry", bob, grant_option: true
|
42
|
+
end
|
43
|
+
"""
|
44
|
+
Then "cucumber:user:bob" can "fry" "cucumber:food:bacon" with grant option
|
45
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
@dsl
|
2
|
+
Feature: Creating a resource
|
3
|
+
|
4
|
+
Background:
|
5
|
+
|
6
|
+
Scenario: Create with simple kind and id
|
7
|
+
When I run script:
|
8
|
+
"""
|
9
|
+
resource "food", "bacon"
|
10
|
+
"""
|
11
|
+
Then the model should contain "resource" "cucumber:food:bacon"
|
12
|
+
|
13
|
+
Scenario: Create with scope
|
14
|
+
When I run script:
|
15
|
+
"""
|
16
|
+
scope "test" do
|
17
|
+
resource "food", "bacon"
|
18
|
+
end
|
19
|
+
resource "food", "eggs"
|
20
|
+
"""
|
21
|
+
Then the model should contain "resource" "cucumber:food:test/bacon"
|
22
|
+
And the model should contain "resource" "cucumber:food:eggs"
|
23
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
@dsl
|
2
|
+
Feature: Creating a User
|
3
|
+
|
4
|
+
Background:
|
5
|
+
|
6
|
+
Scenario: Users don't incorporate the namespace as a path prefix
|
7
|
+
When I run script:
|
8
|
+
"""
|
9
|
+
namespace do
|
10
|
+
user "bob"
|
11
|
+
end
|
12
|
+
"""
|
13
|
+
Then the model should contain "user" "bob"
|
14
|
+
|
15
|
+
Scenario: Namespace can be used as a no-arg method
|
16
|
+
When I run script:
|
17
|
+
"""
|
18
|
+
namespace "foobar" do
|
19
|
+
user "#{namespace}-bob"
|
20
|
+
end
|
21
|
+
"""
|
22
|
+
Then the model should contain "user" "foobar-bob"
|
23
|
+
|
@@ -0,0 +1,46 @@
|
|
1
|
+
When(/^I use script context:$/) do |context|
|
2
|
+
@context = JSON.parse context
|
3
|
+
end
|
4
|
+
|
5
|
+
When(/^I run script:$/) do |script|
|
6
|
+
require 'conjur/dsl/runner'
|
7
|
+
@runner = Conjur::DSL::Runner.new(script)
|
8
|
+
@runner.context = @context if @context
|
9
|
+
@runner.execute
|
10
|
+
end
|
11
|
+
|
12
|
+
Then(/^the model should contain "(.*?)" "(.*?)"$/) do |kind, id|
|
13
|
+
@mock_api.thing(kind, id).should_not be_nil
|
14
|
+
end
|
15
|
+
|
16
|
+
Then(/^the "(.*?)" "(.*?)" should be owned by "(.*?)"$/) do |kind, id, owner|
|
17
|
+
step "the model should contain \"#{kind}\" \"#{id}\""
|
18
|
+
@mock_api.thing(kind, id).ownerid.should == owner
|
19
|
+
end
|
20
|
+
|
21
|
+
Then(/^the "(.*?)" "(.*?)" should not have an owner$/) do |kind, id|
|
22
|
+
step "the model should contain \"#{kind}\" \"#{id}\""
|
23
|
+
@mock_api.thing(kind, id).ownerid.should be_nil
|
24
|
+
end
|
25
|
+
|
26
|
+
Then(/^"(.*?)" can "(.*?)" "(.*?)"( with grant option)?$/) do |role, privilege, resource, grant_option|
|
27
|
+
resource = @mock_api.thing(:resource, resource)
|
28
|
+
permission = resource.permissions.find do |p|
|
29
|
+
p.privilege == privilege && p.role == role && p.grant_option == !grant_option.nil?
|
30
|
+
end
|
31
|
+
raise "#{role} cannot #{privilege} #{resource.id} with#{grant_option ? "" : "out"} grant_option" unless permission
|
32
|
+
end
|
33
|
+
|
34
|
+
Then(/^the context should contain "(.*?)"$/) do |key|
|
35
|
+
@runner.context.should have_key(key.to_s)
|
36
|
+
end
|
37
|
+
|
38
|
+
Then(/^the context "(.*?)" should be "(.*?)"$/) do |key, value|
|
39
|
+
@runner.context[key].should == value
|
40
|
+
end
|
41
|
+
|
42
|
+
Then(/^the context "(.*?)" should contain "(.*?)" item$/) do |key, key_count|
|
43
|
+
step "the context should contain \"#{key}\""
|
44
|
+
@runner.context[key].should have(key_count.to_i).items
|
45
|
+
end
|
46
|
+
|
data/features/support/env.rb
CHANGED
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
class MockAPI
|
4
|
+
attr_reader :things
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@things = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def thing(kind, id)
|
11
|
+
(@things[kind.to_sym] || []).find{|r| r.id == id}
|
12
|
+
end
|
13
|
+
|
14
|
+
def create_host(options = {})
|
15
|
+
id = options.delete(:id)
|
16
|
+
if id
|
17
|
+
host = thing(:host, id)
|
18
|
+
else
|
19
|
+
id = SecureRandom.uuid
|
20
|
+
end
|
21
|
+
host ||= create_thing(:host, id, options, role: true)
|
22
|
+
end
|
23
|
+
|
24
|
+
def create_user(id, options = {})
|
25
|
+
thing(:user, id) || create_thing(:user, id, options, role: true)
|
26
|
+
end
|
27
|
+
|
28
|
+
def create_variable(mime_type, kind)
|
29
|
+
create_thing(:user, SecureRandom.uuid, mime_type: mime_type, kind: kind)
|
30
|
+
end
|
31
|
+
|
32
|
+
def create_resource(id, options = {})
|
33
|
+
resource(id).tap do |resource|
|
34
|
+
resource.send(:"exists?=", true)
|
35
|
+
populate_options resource, options
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def create_role(id, options = {})
|
40
|
+
role(id).tap do |role|
|
41
|
+
role.send(:"exists?=", true)
|
42
|
+
populate_options role, options
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
[ :user, :host ].each do |kind|
|
47
|
+
define_method kind do |id|
|
48
|
+
thing(kind, id)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def role(id)
|
53
|
+
raise "Role id must be a string" unless id.is_a?(String)
|
54
|
+
thing(:role, id) || create_thing(:role, id, { exists?: false }, role: true)
|
55
|
+
end
|
56
|
+
|
57
|
+
def resource(id)
|
58
|
+
raise "Resource id must be a string" unless id.is_a?(String)
|
59
|
+
thing(:resource, id) || create_thing(:resource, id, exists?: false)
|
60
|
+
end
|
61
|
+
|
62
|
+
protected
|
63
|
+
|
64
|
+
def create_thing(kind, id, options, kind_options = {})
|
65
|
+
p kind, id, options, kind_options
|
66
|
+
|
67
|
+
thing = OpenStruct.new(kind: kind, id: id, exists?: true)
|
68
|
+
|
69
|
+
class << thing
|
70
|
+
def permit(privilege, role, options = {})
|
71
|
+
(self.permissions ||= []) << OpenStruct.new(privilege: privilege, role: role.id, grant_option: !!options[:grant_option])
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
if kind_options[:role]
|
76
|
+
thing.roleid = id
|
77
|
+
class << thing
|
78
|
+
def can(privilege, resource, options = {})
|
79
|
+
resource.permit privilege, self, options
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
populate_options(thing, options)
|
85
|
+
|
86
|
+
store_thing kind, thing
|
87
|
+
|
88
|
+
thing
|
89
|
+
end
|
90
|
+
|
91
|
+
def populate_options(thing, options)
|
92
|
+
options.each do |k,v|
|
93
|
+
thing.send("#{k}=", v)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def store_thing(kind, thing)
|
98
|
+
(things[kind] ||= []) << thing
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
Before("@dsl") do
|
103
|
+
puts "Using MockAPI"
|
104
|
+
puts "Using account 'cucumber'"
|
105
|
+
|
106
|
+
require 'conjur/api'
|
107
|
+
require 'conjur/config'
|
108
|
+
require 'conjur/dsl/runner'
|
109
|
+
|
110
|
+
Conjur.stub(:env).and_return "ci"
|
111
|
+
Conjur.stub(:stack).and_return "ci"
|
112
|
+
Conjur.stub(:account).and_return "cucumber"
|
113
|
+
|
114
|
+
Conjur::Core::API.stub(:conjur_account).and_return 'cucumber'
|
115
|
+
@mock_api ||= MockAPI.new
|
116
|
+
Conjur::DSL::Runner.any_instance.stub(:api).and_return @mock_api
|
117
|
+
end
|
data/lib/conjur/cli.rb
CHANGED
@@ -21,6 +21,7 @@
|
|
21
21
|
require 'gli'
|
22
22
|
require 'conjur/config'
|
23
23
|
require 'conjur/log'
|
24
|
+
require 'conjur/identifier_manipulation'
|
24
25
|
|
25
26
|
module Conjur
|
26
27
|
class CLI
|
@@ -28,34 +29,29 @@ module Conjur
|
|
28
29
|
|
29
30
|
class << self
|
30
31
|
def load_config
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
Conjur::Config.merge YAML.load(IO.read(f))
|
37
|
-
end
|
38
|
-
end
|
32
|
+
Conjur::Config.load
|
33
|
+
end
|
34
|
+
|
35
|
+
def apply_config
|
36
|
+
Conjur::Config.apply
|
39
37
|
end
|
40
38
|
end
|
41
39
|
|
42
40
|
load_config
|
43
41
|
|
44
42
|
Conjur::Config.plugins.each do |plugin|
|
45
|
-
|
43
|
+
begin
|
44
|
+
filename = "conjur-asset-#{plugin}"
|
45
|
+
require filename
|
46
|
+
rescue LoadError
|
47
|
+
warn "Could not load plugin '#{plugin}' specified in your config file.\nMake sure you have the #{filename}-api gem installed."
|
48
|
+
end
|
46
49
|
end
|
47
50
|
|
48
51
|
commands_from 'conjur/command'
|
49
52
|
|
50
53
|
pre do |global,command,options,args|
|
51
|
-
|
52
|
-
ENV['CONJUR_STACK'] = Config[:stack] if Config[:stack]
|
53
|
-
ENV['CONJUR_STACK'] ||= 'v4' if ENV['CONJUR_ENV'] == 'production'
|
54
|
-
ENV['CONJUR_ACCOUNT'] = Config[:account] or raise "Missing configuration setting: account. Please set it in ~/.conjurrc"
|
55
|
-
|
56
|
-
if Conjur.log
|
57
|
-
Conjur.log << "Using host #{Conjur::Authn::API.host}\n"
|
58
|
-
end
|
54
|
+
apply_config
|
59
55
|
|
60
56
|
require 'active_support/core_ext'
|
61
57
|
options.delete_if{|k,v| v.blank?}
|
@@ -85,6 +81,10 @@ module Conjur
|
|
85
81
|
$stderr.puts exception.response.body if exception.response
|
86
82
|
end
|
87
83
|
end
|
84
|
+
|
85
|
+
if Conjur.log
|
86
|
+
Conjur.log << "error: #{exception}\n#{exception.backtrace rescue 'NO BACKTRACE?'}"
|
87
|
+
end
|
88
88
|
true
|
89
89
|
end
|
90
90
|
end
|
data/lib/conjur/command.rb
CHANGED
@@ -20,6 +20,8 @@
|
|
20
20
|
#
|
21
21
|
module Conjur
|
22
22
|
class Command
|
23
|
+
extend IdentifierManipulation
|
24
|
+
|
23
25
|
@@api = nil
|
24
26
|
|
25
27
|
class << self
|
@@ -40,32 +42,6 @@ module Conjur
|
|
40
42
|
def api
|
41
43
|
@@api ||= Conjur::Authn.connect
|
42
44
|
end
|
43
|
-
|
44
|
-
# injects account into 2-tokens id
|
45
|
-
def full_resource_id id
|
46
|
-
parts = id.split(':') unless id.nil?
|
47
|
-
if id.blank? or parts.size < 2
|
48
|
-
raise "Expecting at least two tokens in #{id}"
|
49
|
-
end
|
50
|
-
if parts.size == 2
|
51
|
-
id = [conjur_account, parts].flatten.join(":")
|
52
|
-
end
|
53
|
-
id
|
54
|
-
end
|
55
|
-
|
56
|
-
# removes accounts from 3+-tokens id, extracts kind
|
57
|
-
def get_kind_and_id_from_args args, argname='id'
|
58
|
-
flat_id = require_arg(args, argname)
|
59
|
-
tokens=flat_id.split(':')
|
60
|
-
raise "At least 2 tokens expected in #{flat_id}" if tokens.size<2
|
61
|
-
tokens.shift if tokens.size>=3 # get rid of account
|
62
|
-
kind=tokens.shift.gsub('-','_')
|
63
|
-
[kind, tokens.join(':')]
|
64
|
-
end
|
65
|
-
|
66
|
-
def conjur_account
|
67
|
-
Conjur::Core::API.conjur_account
|
68
|
-
end
|
69
45
|
|
70
46
|
def acting_as_option(command)
|
71
47
|
command.arg_name 'Perform all actions as the specified Group'
|
@@ -93,11 +93,7 @@ class Conjur::Command::Assets < Conjur::Command
|
|
93
93
|
member = require_arg(args, 'member')
|
94
94
|
admin_option = !options.delete(:admin).nil?
|
95
95
|
|
96
|
-
|
97
|
-
tokens = [ asset.resource_kind, asset.resource_id, role_name ]
|
98
|
-
grant_role = [ asset.core_conjur_account, '@', tokens.join('/') ].join(':')
|
99
|
-
api.role(grant_role).grant_to member, admin_option
|
100
|
-
|
96
|
+
api.send(kind, id).add_member role_name, member, admin_option: admin_option
|
101
97
|
puts "Membership granted"
|
102
98
|
end
|
103
99
|
end
|
@@ -109,13 +105,8 @@ class Conjur::Command::Assets < Conjur::Command
|
|
109
105
|
kind, id = get_kind_and_id_from_args(args, 'id')
|
110
106
|
role_name = require_arg(args, 'role-name')
|
111
107
|
member = require_arg(args, 'member')
|
112
|
-
|
113
|
-
asset = api.send(kind, id)
|
114
|
-
tokens = [ asset.resource_kind, asset.resource_id, role_name ]
|
115
|
-
grant_role = [ asset.core_conjur_account, '@', tokens.join('/') ].join(':')
|
116
|
-
api.role(grant_role).revoke_from member
|
117
|
-
|
108
|
+
api.send(kind, id).remove_member role_name, member
|
118
109
|
puts "Membership revoked"
|
119
110
|
end
|
120
111
|
end
|
121
|
-
end
|
112
|
+
end
|
data/lib/conjur/command/audit.rb
CHANGED
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'conjur/command'
|
2
|
+
require 'active_support/ordered_hash'
|
3
|
+
|
4
|
+
class Conjur::Command
|
5
|
+
class Audit < self
|
6
|
+
self.prefix = 'audit'
|
7
|
+
|
8
|
+
class << self
|
9
|
+
private
|
10
|
+
def extract_int_option(source, name, dest=nil)
|
11
|
+
if val = source[name]
|
12
|
+
raise "Expected an integer for #{name}, but got #{val}" unless /\d+/ =~ val
|
13
|
+
val.to_i.tap{ |i| dest[name] = i if dest }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def extract_audit_options options
|
18
|
+
{}.tap do |opts|
|
19
|
+
[:limit, :offset].each do |name|
|
20
|
+
extract_int_option(options, name, opts)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def show_audit_events events
|
26
|
+
puts JSON.pretty_generate(events)
|
27
|
+
end
|
28
|
+
|
29
|
+
def audit_feed_command kind, &block
|
30
|
+
command kind do |c|
|
31
|
+
c.desc "Maximum number of events to fetch"
|
32
|
+
c.flag [:l, :limit]
|
33
|
+
|
34
|
+
c.desc "Offset of the first event to return"
|
35
|
+
c.flag [:o, :offset]
|
36
|
+
|
37
|
+
c.action do |global_options, options, args|
|
38
|
+
opts = extract_audit_options options
|
39
|
+
show_audit_events instance_exec(args, opts, &block)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
desc "Show audit events related to a role"
|
47
|
+
arg_name 'role?'
|
48
|
+
audit_feed_command :role do |args, options|
|
49
|
+
if id = args.shift
|
50
|
+
method_name, method_args = :audit_role, [full_resource_id(id), options]
|
51
|
+
else
|
52
|
+
method_name, method_args = :audit_current_role, [options]
|
53
|
+
end
|
54
|
+
api.send method_name, *method_args
|
55
|
+
end
|
56
|
+
|
57
|
+
desc "Show audit events related to a resource"
|
58
|
+
arg_name 'resource'
|
59
|
+
audit_feed_command :resource do |args, options|
|
60
|
+
id = full_resource_id(require_arg args, "resource")
|
61
|
+
api.audit_resource id, options
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -63,7 +63,8 @@ class Conjur::Command::Groups < Conjur::Command
|
|
63
63
|
opts = { admin_option: false }
|
64
64
|
message = "Adminship revoked"
|
65
65
|
end
|
66
|
-
|
66
|
+
|
67
|
+
group.add_member member, opts
|
67
68
|
puts message
|
68
69
|
end
|
69
70
|
end
|
@@ -75,9 +76,7 @@ class Conjur::Command::Groups < Conjur::Command
|
|
75
76
|
group = require_arg(args, 'group')
|
76
77
|
member = require_arg(args, 'member')
|
77
78
|
|
78
|
-
|
79
|
-
api.role(group.roleid).revoke_from member
|
80
|
-
|
79
|
+
api.group(group).remove_member member
|
81
80
|
puts "Membership revoked"
|
82
81
|
end
|
83
82
|
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (C) 2013 Conjur Inc
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
5
|
+
# this software and associated documentation files (the "Software"), to deal in
|
6
|
+
# the Software without restriction, including without limitation the rights to
|
7
|
+
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
8
|
+
# the Software, and to permit persons to whom the Software is furnished to do so,
|
9
|
+
# subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in all
|
12
|
+
# copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
16
|
+
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
17
|
+
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
18
|
+
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
19
|
+
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
20
|
+
#
|
21
|
+
require 'conjur/authn'
|
22
|
+
require 'conjur/command'
|
23
|
+
|
24
|
+
class Conjur::Command::Authn < Conjur::Command
|
25
|
+
self.prefix = :script
|
26
|
+
|
27
|
+
desc "Run a Conjur DSL script"
|
28
|
+
arg_name "script"
|
29
|
+
command :execute do |c|
|
30
|
+
acting_as_option(c)
|
31
|
+
|
32
|
+
c.desc "Load context from this config file; save it when finished"
|
33
|
+
c.arg_name "context"
|
34
|
+
c.flag [:c, :context]
|
35
|
+
|
36
|
+
c.action do |global_options,options,args|
|
37
|
+
filename = nil
|
38
|
+
if script = args.pop
|
39
|
+
filename = script
|
40
|
+
script = File.read(script)
|
41
|
+
else
|
42
|
+
script = STDIN.read
|
43
|
+
end
|
44
|
+
require 'conjur/dsl/runner'
|
45
|
+
runner = Conjur::DSL::Runner.new(script, filename)
|
46
|
+
if options[:context]
|
47
|
+
runner.context = begin
|
48
|
+
JSON.parse(File.read(options[:context]))
|
49
|
+
rescue Errno::ENOENT
|
50
|
+
{}
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
result = runner.execute
|
55
|
+
|
56
|
+
if options[:context]
|
57
|
+
File.write(options[:context], JSON.pretty_generate(runner.context))
|
58
|
+
end
|
59
|
+
|
60
|
+
puts JSON.pretty_generate(result)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/conjur/config.rb
CHANGED
@@ -23,6 +23,29 @@ module Conjur
|
|
23
23
|
@@attributes = {}
|
24
24
|
|
25
25
|
class << self
|
26
|
+
def load
|
27
|
+
require 'yaml'
|
28
|
+
[ File.join("/etc", "conjur.conf"), ( ENV['CONJURRC'] || File.join(ENV['HOME'], ".conjurrc") ) ].each do |f|
|
29
|
+
if File.exists?(f)
|
30
|
+
if Conjur.log
|
31
|
+
Conjur.log << "Loading #{f}\n"
|
32
|
+
end
|
33
|
+
Conjur::Config.merge YAML.load(IO.read(f))
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def apply
|
39
|
+
ENV['CONJUR_ENV'] = Config[:env] || "production"
|
40
|
+
ENV['CONJUR_STACK'] = Config[:stack] if Config[:stack]
|
41
|
+
ENV['CONJUR_STACK'] ||= 'v4' if ENV['CONJUR_ENV'] == 'production'
|
42
|
+
ENV['CONJUR_ACCOUNT'] = Config[:account] or raise "Missing configuration setting: account. Please set it in ~/.conjurrc"
|
43
|
+
|
44
|
+
if Conjur.log
|
45
|
+
Conjur.log << "Using host #{Conjur::Authn::API.host}\n"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
26
49
|
def inspect
|
27
50
|
@@attributes.inspect
|
28
51
|
end
|
@@ -0,0 +1,197 @@
|
|
1
|
+
require 'conjur/identifier_manipulation'
|
2
|
+
|
3
|
+
module Conjur
|
4
|
+
module DSL
|
5
|
+
# Entry point for the Conjur DSL.
|
6
|
+
#
|
7
|
+
# Methods are available in two categories: name scoping and asset building.
|
8
|
+
class Runner
|
9
|
+
include Conjur::IdentifierManipulation
|
10
|
+
|
11
|
+
attr_reader :script, :filename, :context
|
12
|
+
|
13
|
+
def initialize(script, filename = nil)
|
14
|
+
@context = {
|
15
|
+
"env" => Conjur.env,
|
16
|
+
"stack" => Conjur.stack,
|
17
|
+
"account" => Conjur.account,
|
18
|
+
"api_keys" => {}
|
19
|
+
}
|
20
|
+
@script = script
|
21
|
+
@filename = filename
|
22
|
+
@api = nil
|
23
|
+
@scopes = Array.new
|
24
|
+
@owners = Array.new
|
25
|
+
@objects = Array.new
|
26
|
+
end
|
27
|
+
|
28
|
+
def api
|
29
|
+
@api ||= connect
|
30
|
+
end
|
31
|
+
|
32
|
+
def context=(context)
|
33
|
+
@context.deep_merge! context
|
34
|
+
end
|
35
|
+
|
36
|
+
def api_keys
|
37
|
+
@context["api_keys"]
|
38
|
+
end
|
39
|
+
|
40
|
+
def current_object
|
41
|
+
!@objects.empty? ? @objects.last : nil
|
42
|
+
end
|
43
|
+
|
44
|
+
def current_scope
|
45
|
+
!@scopes.empty? ? @scopes.join('/') : nil
|
46
|
+
end
|
47
|
+
|
48
|
+
def scope name = nil, &block
|
49
|
+
if name != nil
|
50
|
+
do_scope name, &block
|
51
|
+
else
|
52
|
+
current_scope
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def namespace ns = nil, &block
|
57
|
+
if block_given?
|
58
|
+
ns ||= context["namespace"]
|
59
|
+
if ns.nil?
|
60
|
+
require 'conjur/api/variables'
|
61
|
+
ns = context["namespace"] = api.create_variable("text/plain", "namespace").id
|
62
|
+
end
|
63
|
+
do_scope ns, &block
|
64
|
+
context
|
65
|
+
else
|
66
|
+
@scopes[0]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
alias model namespace
|
71
|
+
|
72
|
+
def execute
|
73
|
+
args = [ script ]
|
74
|
+
args << filename if filename
|
75
|
+
instance_eval(*args)
|
76
|
+
end
|
77
|
+
|
78
|
+
def resource kind, id, options = {}, &block
|
79
|
+
id = full_resource_id([kind, qualify_id(id) ].join(':'))
|
80
|
+
find_or_create :resource, id, options, &block
|
81
|
+
end
|
82
|
+
|
83
|
+
def role kind, id, options = {}, &block
|
84
|
+
id = full_resource_id([ kind, qualify_id(id) ].join(':'))
|
85
|
+
find_or_create :role, id, options, &block
|
86
|
+
end
|
87
|
+
|
88
|
+
def create_variable id = nil, options = {}, &block
|
89
|
+
options[:id] = id if id
|
90
|
+
mime_type = options.delete(:mime_type)
|
91
|
+
kind = options.delete(:kind)
|
92
|
+
end
|
93
|
+
|
94
|
+
def owns
|
95
|
+
@owners.push current_object
|
96
|
+
begin
|
97
|
+
yield
|
98
|
+
ensure
|
99
|
+
@owners.pop
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
protected
|
104
|
+
|
105
|
+
def qualify_id id
|
106
|
+
if id[0] == "/"
|
107
|
+
id[1..-1]
|
108
|
+
else
|
109
|
+
[ current_scope, id ].compact.join('/')
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def method_missing(sym, *args, &block)
|
114
|
+
if create_compatible_args?(args) && api.respond_to?(sym)
|
115
|
+
id = args[0]
|
116
|
+
id = qualify_id(id) unless sym == :user
|
117
|
+
find_or_create sym, id, args[1] || {}, &block
|
118
|
+
elsif current_object && current_object.respond_to?(sym)
|
119
|
+
current_object.send(sym, *args, &block)
|
120
|
+
else
|
121
|
+
super
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def create_compatible_args?(args)
|
126
|
+
valid_prototypes = [
|
127
|
+
lambda { args.length == 1 },
|
128
|
+
lambda { args.length == 2 && args[1].is_a?(Hash) }
|
129
|
+
]
|
130
|
+
!valid_prototypes.find{|p| p.call}.nil?
|
131
|
+
end
|
132
|
+
|
133
|
+
def find_or_create(type, id, options, &block)
|
134
|
+
find_method = type.to_sym
|
135
|
+
create_method = "create_#{type}".to_sym
|
136
|
+
unless (obj = api.send(find_method, id)) && obj.exists?
|
137
|
+
options = expand_options(options)
|
138
|
+
obj = if create_method == :create_variable
|
139
|
+
options[:id] = id
|
140
|
+
api.send(create_method, options.delete(:mime_type), options.delete(:kind), options)
|
141
|
+
elsif [ 2, -2 ].member?(api.method(create_method).arity)
|
142
|
+
api.send(create_method, id, options)
|
143
|
+
else
|
144
|
+
options[:id] = id
|
145
|
+
api.send(create_method, options)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
do_object obj, &block
|
149
|
+
end
|
150
|
+
|
151
|
+
def do_object obj, &block
|
152
|
+
begin
|
153
|
+
api_keys[obj.resourceid] = obj.api_key
|
154
|
+
rescue
|
155
|
+
end
|
156
|
+
|
157
|
+
@objects.push obj
|
158
|
+
begin
|
159
|
+
yield obj if block_given?
|
160
|
+
obj
|
161
|
+
ensure
|
162
|
+
@objects.pop
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def do_scope name, &block
|
167
|
+
return unless block_given?
|
168
|
+
|
169
|
+
@scopes.push(name)
|
170
|
+
begin
|
171
|
+
yield
|
172
|
+
ensure
|
173
|
+
@scopes.pop
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def owner(options)
|
178
|
+
owner = options[:owner] || @owners.last
|
179
|
+
owner = owner.roleid if owner.respond_to?(:roleid)
|
180
|
+
owner
|
181
|
+
end
|
182
|
+
|
183
|
+
def expand_options(opts)
|
184
|
+
(opts || {}).tap do |options|
|
185
|
+
if owner = owner(options)
|
186
|
+
options[:ownerid] = owner
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def connect
|
192
|
+
require 'conjur/authn'
|
193
|
+
Conjur::Authn.connect
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Conjur
|
2
|
+
module IdentifierManipulation
|
3
|
+
# injects account into 2-tokens id
|
4
|
+
def full_resource_id id
|
5
|
+
parts = id.split(':') unless id.nil?
|
6
|
+
if id.blank? or parts.size < 2
|
7
|
+
raise "Expecting at least two tokens in #{id}"
|
8
|
+
end
|
9
|
+
if parts.size == 2
|
10
|
+
id = [conjur_account, parts].flatten.join(":")
|
11
|
+
end
|
12
|
+
id
|
13
|
+
end
|
14
|
+
|
15
|
+
# removes accounts from 3+-tokens id, extracts kind
|
16
|
+
def get_kind_and_id_from_args args, argname='id'
|
17
|
+
flat_id = require_arg(args, argname)
|
18
|
+
tokens=flat_id.split(':')
|
19
|
+
raise "At least 2 tokens expected in #{flat_id}" if tokens.size<2
|
20
|
+
tokens.shift if tokens.size>=3 # get rid of account
|
21
|
+
kind=tokens.shift.gsub('-','_')
|
22
|
+
[kind, tokens.join(':')]
|
23
|
+
end
|
24
|
+
|
25
|
+
def conjur_account
|
26
|
+
Conjur::Core::API.conjur_account
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/conjur/version.rb
CHANGED
data/spec/command/assets_spec.rb
CHANGED
@@ -81,55 +81,36 @@ describe Conjur::Command::Assets, logged_in: true do
|
|
81
81
|
end
|
82
82
|
end
|
83
83
|
|
84
|
-
shared_examples 'it obtains
|
84
|
+
shared_examples 'it obtains asset by kind and id' do
|
85
85
|
it "obtains asset instance as api.#{KIND}(#{ID})" do
|
86
86
|
api.should_receive(KIND.to_sym).with(ID)
|
87
87
|
invoke_silently
|
88
88
|
end
|
89
|
-
it "account=asset.core_conjur_account" do
|
90
|
-
asset.should_receive(:core_conjur_account)
|
91
|
-
invoke_silently
|
92
|
-
end
|
93
|
-
it "kind=asset.resource_kind" do
|
94
|
-
asset.should_receive(:resource_kind)
|
95
|
-
invoke_silently
|
96
|
-
end
|
97
|
-
it "id=asset.resource_id" do
|
98
|
-
asset.should_receive(:resource_id)
|
99
|
-
invoke_silently
|
100
|
-
end
|
101
|
-
|
102
|
-
it "obtains role as #{ACCOUNT}:@:#{KIND}/#{ID}/#{ROLE}" do
|
103
|
-
api.should_receive(:role).with("#{ACCOUNT}:@:#{KIND}/#{ID}/#{ROLE}")
|
104
|
-
invoke_silently
|
105
|
-
end
|
106
89
|
end
|
107
|
-
|
108
|
-
shared_context "asset
|
109
|
-
before(:each) {
|
110
|
-
|
111
|
-
asset.stub(:
|
112
|
-
asset.stub(:
|
113
|
-
api.stub(:role).and_return(role_instance)
|
90
|
+
|
91
|
+
shared_context "asset instance" do
|
92
|
+
before(:each) {
|
93
|
+
api.stub(KIND.to_sym).and_return(asset)
|
94
|
+
asset.stub(:add_member)
|
95
|
+
asset.stub(:remove_member)
|
114
96
|
}
|
115
|
-
let(:role_instance) { double(grant_to: true, revoke_from: true) }
|
116
97
|
end
|
117
98
|
|
118
99
|
describe_command "asset:members:add #{KIND}:#{ID} #{ROLE} #{MEMBER}" do
|
119
|
-
include_context "asset
|
120
|
-
it_behaves_like "it obtains
|
100
|
+
include_context "asset instance"
|
101
|
+
it_behaves_like "it obtains asset by kind and id"
|
121
102
|
it 'calls role.grant_to(member,...)' do
|
122
|
-
|
103
|
+
asset.should_receive(:add_member).with(ROLE, MEMBER, anything)
|
123
104
|
invoke_silently
|
124
105
|
end
|
125
106
|
it { expect { invoke }.to write "Membership granted" }
|
126
107
|
end
|
127
108
|
|
128
109
|
describe_command "asset:members:remove #{KIND}:#{ID} #{ROLE} #{MEMBER}" do
|
129
|
-
include_context "asset
|
130
|
-
it_behaves_like "it obtains
|
110
|
+
include_context "asset instance"
|
111
|
+
it_behaves_like "it obtains asset by kind and id"
|
131
112
|
it 'calls role.revoke_from(member)' do
|
132
|
-
|
113
|
+
asset.should_receive(:remove_member).with(ROLE, MEMBER)
|
133
114
|
invoke_silently
|
134
115
|
end
|
135
116
|
it { expect { invoke }.to write "Membership revoked" }
|
data/spec/command/audit_spec.rb
CHANGED
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Conjur::Command::Audit, logged_in: true do
|
4
|
+
let(:events) { [{'foo' => 'bar', 'zelda' => 'link', 'abc' => 'xyz'}, {'some' => 'other event'}] }
|
5
|
+
|
6
|
+
def expect_api_call method, *args
|
7
|
+
api.should_receive(method.to_sym).with(*args).and_return events
|
8
|
+
described_class.should_receive(:show_audit_events).with(events)
|
9
|
+
end
|
10
|
+
|
11
|
+
def invoke_expecting_api_call method, *args
|
12
|
+
expect_api_call method, *args
|
13
|
+
invoke
|
14
|
+
end
|
15
|
+
|
16
|
+
def invoke_silently
|
17
|
+
silence_stderr { invoke }
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.describe_command_success cmd, method, *expected_args, &block
|
21
|
+
describe_command cmd do
|
22
|
+
it "calls api.#{method}(#{expected_args.map(&:inspect).join(',')})" do
|
23
|
+
instance_eval(&block) if block
|
24
|
+
invoke_expecting_api_call method, *expected_args
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.it_calls_the_api command, api_method, *api_args, &block
|
30
|
+
describe_command_success command, api_method, *api_args, &block
|
31
|
+
accepts_pagination_params command, api_method, *api_args, &block
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
def self.it_fails command, *raise_error_args
|
36
|
+
unless raise_error_args.empty? or ::Class === raise_error_args.first
|
37
|
+
raise_error_args.unshift Exception
|
38
|
+
end
|
39
|
+
describe_command command do
|
40
|
+
it "raises #{raise_error_args.map(&:inspect).join ' '}" do
|
41
|
+
expect { invoke_silently }.to raise_error(*raise_error_args)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.accepts_pagination_params cmd, api_method, *api_method_args, &block
|
47
|
+
context "with valid pagination options" do
|
48
|
+
expected_opts = {limit: 12, offset: 2}
|
49
|
+
api_method_args = case api_method_args.last
|
50
|
+
when Hash
|
51
|
+
api_method_args[0..-2] << api_method_args.last.merge(expected_opts)
|
52
|
+
else
|
53
|
+
api_method_args.dup << expected_opts
|
54
|
+
end
|
55
|
+
describe_command_success cmd + " --limit 12 --offset 2", api_method, *api_method_args, &block
|
56
|
+
end
|
57
|
+
context "with garbage pagination options" do
|
58
|
+
it_fails cmd + " --limit hiythere", RuntimeError, /expected an integer for limit/i
|
59
|
+
it_fails cmd + " --offset hiythere", RuntimeError, /expected an integer for offset/i
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "audit:role" do
|
64
|
+
context "without an argument" do
|
65
|
+
it_calls_the_api "audit:role", :audit_current_role, {}
|
66
|
+
end
|
67
|
+
context "with an argument" do
|
68
|
+
context "of a full id" do
|
69
|
+
it_calls_the_api "audit:role foo:bar:baz", :audit_role, 'foo:bar:baz', {}
|
70
|
+
end
|
71
|
+
context "without an account" do
|
72
|
+
it_calls_the_api "audit:role bar:baz", :audit_role, 'the-conjur-account:bar:baz', {} do
|
73
|
+
Conjur::Command.stub(conjur_account: "the-conjur-account")
|
74
|
+
end
|
75
|
+
end
|
76
|
+
context "without enough tokens" do
|
77
|
+
it_fails "audit:role not-enough-tokens", RuntimeError, /expecting at least two tokens/i
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "audit:resource" do
|
83
|
+
context "without an argument" do
|
84
|
+
it_fails "audit:resource", /missing parameter: resource/i
|
85
|
+
end
|
86
|
+
context "with an argument of" do
|
87
|
+
context "a full id" do
|
88
|
+
it_calls_the_api "audit:resource foo:bar:baz", :audit_resource, "foo:bar:baz", {}
|
89
|
+
end
|
90
|
+
context "an id with two tokens" do
|
91
|
+
it_calls_the_api "audit:resource foo:bar", :audit_resource, "the-conjur-account:foo:bar", {} do
|
92
|
+
Conjur::Command.stub(conjur_account: "the-conjur-account")
|
93
|
+
end
|
94
|
+
end
|
95
|
+
context "an id with one token" do
|
96
|
+
it_fails "audit:resource foo", /expecting at least two tokens/i
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -71,15 +71,16 @@ def post_response(id, attributes = {})
|
|
71
71
|
end
|
72
72
|
|
73
73
|
# stub parameters to be used in resource/asset tests
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
74
|
+
KIND="asset_kind"
|
75
|
+
ID="unique_id"
|
76
|
+
ROLE='<role>'
|
77
|
+
MEMBER='<member>'
|
78
|
+
PRIVILEGE='<privilege>'
|
79
|
+
OWNER='<owner/userid>'
|
80
|
+
ACCOUNT='<core_account>'
|
82
81
|
|
83
82
|
require 'write_expectation'
|
84
83
|
|
84
|
+
ENV['CONJURRC'] = '/dev/null'
|
85
|
+
|
85
86
|
require 'conjur/cli'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: conjur-cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.3.0
|
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: 2013-
|
13
|
+
date: 2013-11-19 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: conjur-api
|
@@ -92,6 +92,22 @@ dependencies:
|
|
92
92
|
- - ! '>='
|
93
93
|
- !ruby/object:Gem::Version
|
94
94
|
version: '0'
|
95
|
+
- !ruby/object:Gem::Dependency
|
96
|
+
name: deep_merge
|
97
|
+
requirement: !ruby/object:Gem::Requirement
|
98
|
+
none: false
|
99
|
+
requirements:
|
100
|
+
- - ! '>='
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
type: :runtime
|
104
|
+
prerelease: false
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
106
|
+
none: false
|
107
|
+
requirements:
|
108
|
+
- - ! '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
95
111
|
- !ruby/object:Gem::Dependency
|
96
112
|
name: cas_rest_client
|
97
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -198,6 +214,7 @@ executables:
|
|
198
214
|
extensions: []
|
199
215
|
extra_rdoc_files: []
|
200
216
|
files:
|
217
|
+
- .githooks/pre_commit/run_specs.rb
|
201
218
|
- .gitignore
|
202
219
|
- .kateproject
|
203
220
|
- .project
|
@@ -208,8 +225,17 @@ files:
|
|
208
225
|
- bin/conjur
|
209
226
|
- bin/jsonfield
|
210
227
|
- conjur.gemspec
|
228
|
+
- features/dsl_context.feature
|
229
|
+
- features/dsl_host_create.feature
|
230
|
+
- features/dsl_ownership.feature
|
231
|
+
- features/dsl_permission.feature
|
232
|
+
- features/dsl_resource_create.feature
|
233
|
+
- features/dsl_role_create.feature
|
234
|
+
- features/dsl_user_create.feature
|
211
235
|
- features/jsonfield.feature
|
236
|
+
- features/step_definitions/dsl_steps.rb
|
212
237
|
- features/support/env.rb
|
238
|
+
- features/support/hooks.rb
|
213
239
|
- lib/conjur.rb
|
214
240
|
- lib/conjur/authn.rb
|
215
241
|
- lib/conjur/cli.rb
|
@@ -223,10 +249,13 @@ files:
|
|
223
249
|
- lib/conjur/command/ids.rb
|
224
250
|
- lib/conjur/command/resources.rb
|
225
251
|
- lib/conjur/command/roles.rb
|
252
|
+
- lib/conjur/command/script.rb
|
226
253
|
- lib/conjur/command/secrets.rb
|
227
254
|
- lib/conjur/command/users.rb
|
228
255
|
- lib/conjur/command/variables.rb
|
229
256
|
- lib/conjur/config.rb
|
257
|
+
- lib/conjur/dsl/runner.rb
|
258
|
+
- lib/conjur/identifier_manipulation.rb
|
230
259
|
- lib/conjur/version.rb
|
231
260
|
- spec/command/assets_spec.rb
|
232
261
|
- spec/command/audit_spec.rb
|
@@ -240,6 +269,7 @@ files:
|
|
240
269
|
- spec/command_spec.rb
|
241
270
|
- spec/spec_helper.rb
|
242
271
|
- spec/write_expectation.rb
|
272
|
+
- update_ci.sh
|
243
273
|
homepage: https://github.com/inscitiv/cli-ruby
|
244
274
|
licenses:
|
245
275
|
- MIT
|
@@ -255,7 +285,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
255
285
|
version: '0'
|
256
286
|
segments:
|
257
287
|
- 0
|
258
|
-
hash: -
|
288
|
+
hash: -1644875280166095669
|
259
289
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
260
290
|
none: false
|
261
291
|
requirements:
|
@@ -264,7 +294,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
264
294
|
version: '0'
|
265
295
|
segments:
|
266
296
|
- 0
|
267
|
-
hash: -
|
297
|
+
hash: -1644875280166095669
|
268
298
|
requirements: []
|
269
299
|
rubyforge_project:
|
270
300
|
rubygems_version: 1.8.25
|
@@ -272,8 +302,17 @@ signing_key:
|
|
272
302
|
specification_version: 3
|
273
303
|
summary: Conjur command line interface
|
274
304
|
test_files:
|
305
|
+
- features/dsl_context.feature
|
306
|
+
- features/dsl_host_create.feature
|
307
|
+
- features/dsl_ownership.feature
|
308
|
+
- features/dsl_permission.feature
|
309
|
+
- features/dsl_resource_create.feature
|
310
|
+
- features/dsl_role_create.feature
|
311
|
+
- features/dsl_user_create.feature
|
275
312
|
- features/jsonfield.feature
|
313
|
+
- features/step_definitions/dsl_steps.rb
|
276
314
|
- features/support/env.rb
|
315
|
+
- features/support/hooks.rb
|
277
316
|
- spec/command/assets_spec.rb
|
278
317
|
- spec/command/audit_spec.rb
|
279
318
|
- spec/command/authn_spec.rb
|