conjur-cli 4.1.1 → 4.3.0
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/.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
|