conjur-cli 4.28.2 → 4.29.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.dockerignore +8 -0
- data/.gitignore +2 -0
- data/.overcommit.yml +10 -0
- data/.rubocop.yml +14 -0
- data/CHANGELOG.md +16 -0
- data/Dockerfile +10 -0
- data/Gemfile +2 -0
- data/Rakefile +1 -1
- data/acceptance-features/audit/audit_event_send.feature +46 -43
- data/acceptance-features/audit/send.feature +0 -19
- data/acceptance-features/authentication/login.feature +0 -2
- data/acceptance-features/authentication/logout.feature +0 -3
- data/acceptance-features/authorization/resource/check.feature +6 -4
- data/acceptance-features/authorization/resource/create.feature +4 -2
- data/acceptance-features/authorization/resource/exists.feature +8 -6
- data/acceptance-features/authorization/resource/give.feature +3 -1
- data/acceptance-features/authorization/resource/show.feature +3 -1
- data/acceptance-features/authorization/role/graph.feature +0 -1
- data/acceptance-features/conjurenv/check.feature +3 -10
- data/acceptance-features/conjurenv/run.feature +3 -3
- data/acceptance-features/conjurenv/template.feature +1 -1
- data/acceptance-features/directory/hostfactory/create.feature +13 -0
- data/acceptance-features/directory/hostfactory/tokens.feature +16 -0
- data/acceptance-features/directory/layer/retire.feature +43 -0
- data/acceptance-features/directory/user/update_password.feature +0 -1
- data/acceptance-features/directory/variable/value.feature +3 -2
- data/acceptance-features/dsl/policy_owner.feature +21 -7
- data/acceptance-features/dsl/resource_owner.feature +4 -4
- data/acceptance-features/pubkeys/add.feature +4 -2
- data/acceptance-features/pubkeys/names.feature +6 -3
- data/acceptance-features/pubkeys/show.feature +4 -2
- data/acceptance-features/step_definitions/{cli.rb → cli_steps.rb} +18 -4
- data/acceptance-features/step_definitions/user_steps.rb +13 -12
- data/acceptance-features/support/env.rb +0 -1
- data/acceptance-features/support/hooks.rb +11 -14
- data/acceptance-features/support/world.rb +16 -18
- data/build-deb.sh +19 -0
- data/ci/test.sh +19 -0
- data/conjur.gemspec +9 -12
- data/debify.sh +4 -0
- data/distrib/bin/_conjur +3 -0
- data/distrib/bin/conjur +3 -0
- data/distrib/bin/conjurize +3 -0
- data/distrib/bin/jsonfield +3 -0
- data/features/conjurize.feature +25 -25
- data/features/support/env.rb +5 -1
- data/features/support/hooks.rb +0 -1
- data/jenkins.sh +29 -1
- data/lib/conjur/cli.rb +27 -4
- data/lib/conjur/command.rb +36 -0
- data/lib/conjur/command/audit.rb +12 -0
- data/lib/conjur/command/bootstrap.rb +5 -9
- data/lib/conjur/command/host_factories.rb +187 -0
- data/lib/conjur/command/hosts.rb +82 -2
- data/lib/conjur/command/layers.rb +28 -0
- data/lib/conjur/command/resources.rb +1 -0
- data/lib/conjur/command/rspec/mock_services.rb +1 -1
- data/lib/conjur/command/server.rb +67 -0
- data/lib/conjur/command/users.rb +67 -12
- data/lib/conjur/command/variables.rb +101 -14
- data/lib/conjur/conjurize.rb +25 -69
- data/lib/conjur/conjurize/script.rb +133 -0
- data/lib/conjur/version.rb +1 -1
- data/publish.sh +6 -0
- data/spec/command/elevate_spec.rb +1 -1
- data/spec/command/host_factories_spec.rb +38 -0
- data/spec/command/hosts_spec.rb +86 -22
- data/spec/command/users_spec.rb +51 -3
- data/spec/command/variable_expiration_spec.rb +174 -0
- data/spec/command/variables_spec.rb +1 -1
- data/spec/conjurize_spec.rb +70 -0
- metadata +61 -64
data/build-deb.sh
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/bin/bash -ex
|
2
|
+
|
3
|
+
export DEBUG=true
|
4
|
+
export GLI_DEBUG=true
|
5
|
+
|
6
|
+
# Make sure Gemfile.lock exists
|
7
|
+
gem install -N bundler
|
8
|
+
bundle
|
9
|
+
|
10
|
+
debify clean
|
11
|
+
|
12
|
+
debify package \
|
13
|
+
--dockerfile ci/Dockerfile.fpm \
|
14
|
+
cli \
|
15
|
+
-- \
|
16
|
+
--depends ruby2.0
|
17
|
+
|
18
|
+
debify test -t 4.6-stable cli ci/test.sh
|
19
|
+
|
data/ci/test.sh
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
conjur_cid="$1"
|
4
|
+
|
5
|
+
cat << TEST | docker exec -i $conjur_cid bash
|
6
|
+
#!/bin/bash -ex
|
7
|
+
|
8
|
+
cd /src/cli
|
9
|
+
|
10
|
+
unset CONJUR_AUTHN_LOGIN
|
11
|
+
|
12
|
+
bundle exec rake jenkins || true
|
13
|
+
|
14
|
+
env CONJUR_AUTHN_LOGIN=admin CONJUR_AUTHN_API_KEY=secret bundle exec cucumber -r acceptance-features/support \
|
15
|
+
-r acceptance-features/step_definitions \
|
16
|
+
-f pretty \
|
17
|
+
-f junit --out acceptance-features/reports \
|
18
|
+
acceptance-features || true
|
19
|
+
TEST
|
data/conjur.gemspec
CHANGED
@@ -16,26 +16,23 @@ Gem::Specification.new do |gem|
|
|
16
16
|
gem.version = Conjur::VERSION
|
17
17
|
|
18
18
|
|
19
|
-
gem.add_dependency 'activesupport'
|
20
|
-
gem.add_dependency 'conjur-api', '~> 4.
|
19
|
+
gem.add_dependency 'activesupport', '~> 4.2'
|
20
|
+
gem.add_dependency 'conjur-api', '~> 4.20'
|
21
21
|
gem.add_dependency 'gli', '>=2.8.0'
|
22
|
-
gem.add_dependency 'highline'
|
22
|
+
gem.add_dependency 'highline', '~> 1.7'
|
23
23
|
gem.add_dependency 'netrc', '~> 0.10.2'
|
24
|
-
gem.add_dependency 'methadone'
|
25
|
-
gem.add_dependency 'deep_merge'
|
26
|
-
gem.add_dependency 'xdg'
|
24
|
+
gem.add_dependency 'methadone', '~> 1.9'
|
25
|
+
gem.add_dependency 'deep_merge', '~> 1.0'
|
26
|
+
gem.add_dependency 'xdg', '~> 2.2'
|
27
27
|
|
28
|
-
gem.add_runtime_dependency 'cas_rest_client'
|
28
|
+
gem.add_runtime_dependency 'cas_rest_client', '~> 1.3'
|
29
29
|
|
30
30
|
gem.add_development_dependency 'rspec', '~> 3.0'
|
31
31
|
gem.add_development_dependency 'simplecov'
|
32
|
-
gem.add_development_dependency 'aruba', '~> 0.
|
32
|
+
gem.add_development_dependency 'aruba', '~> 0.12.0'
|
33
33
|
gem.add_development_dependency 'ci_reporter_rspec', '~> 1.0'
|
34
|
-
gem.add_development_dependency 'ci_reporter_cucumber'
|
34
|
+
gem.add_development_dependency 'ci_reporter_cucumber', '~> 1.0'
|
35
35
|
gem.add_development_dependency 'rake', '~> 10.0'
|
36
36
|
gem.add_development_dependency 'io-grab', '~> 0.0.1'
|
37
37
|
gem.add_development_dependency 'json_spec'
|
38
|
-
# For cukes
|
39
|
-
gem.add_development_dependency 'conjur-asset-audit-send'
|
40
|
-
gem.add_development_dependency 'conjur-asset-host-factory'
|
41
38
|
end
|
data/debify.sh
ADDED
data/distrib/bin/_conjur
ADDED
data/distrib/bin/conjur
ADDED
data/features/conjurize.feature
CHANGED
@@ -11,22 +11,22 @@ Feature: conjurize program generates install scripts
|
|
11
11
|
|
12
12
|
Scenario: Minimal conjurize script
|
13
13
|
When I conjurize ""
|
14
|
-
Then the stdout should contain
|
14
|
+
Then the stdout should contain:
|
15
15
|
"""
|
16
16
|
#!/bin/sh
|
17
17
|
set -e
|
18
18
|
|
19
19
|
# Implementation note: 'tee' is used as a sudo-friendly 'cat' to populate a file with the contents provided below.
|
20
20
|
|
21
|
-
tee /etc/conjur.conf > /dev/null <<
|
21
|
+
tee /etc/conjur.conf > /dev/null << EOF
|
22
22
|
account: test
|
23
23
|
appliance_url: https://conjur/api
|
24
24
|
cert_file: /etc/conjur-test.pem
|
25
25
|
netrc_path: /etc/conjur.identity
|
26
26
|
plugins: []
|
27
|
-
|
27
|
+
EOF
|
28
28
|
|
29
|
-
tee /etc/conjur-test.pem > /dev/null <<
|
29
|
+
tee /etc/conjur-test.pem > /dev/null << EOF
|
30
30
|
-----BEGIN CERTIFICATE-----
|
31
31
|
MIIDZTCCAk2gAwIBAgIJAMzfPBZBq82XMA0GCSqGSIb3DQEBBQUAMDMxMTAvBgNV
|
32
32
|
BAMTKGVjMi01NC04My05OS0xMzUuY29tcHV0ZS0xLmFtYXpvbmF3cy5jb20wHhcN
|
@@ -48,15 +48,15 @@ yvml0YdVSiMdTdIk58qG84pkmteSX9VYE1IF7xfWb3ji8292fm5q6cgqFLNYx2MI
|
|
48
48
|
MVs0y+HobWbOKKhyfxpMT59dJxGu21QPbWfQLkHCCOlo2P4z9oku23sbvQQ7CbvS
|
49
49
|
VoykXurdaZo9
|
50
50
|
-----END CERTIFICATE-----
|
51
|
-
|
51
|
+
EOF
|
52
52
|
|
53
|
-
|
53
|
+
touch /etc/conjur.identity
|
54
|
+
chmod 600 /etc/conjur.identity
|
55
|
+
tee /etc/conjur.identity > /dev/null << EOF
|
54
56
|
machine https://conjur/api/authn
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
chmod 0600 /etc/conjur.identity
|
59
|
-
|
57
|
+
login host/ec2/i-eaa5f700
|
58
|
+
password 3a4rb19rpjejr89h6r29kd2fb3808cpy
|
59
|
+
EOF
|
60
60
|
"""
|
61
61
|
|
62
62
|
Scenario: conjurize with SSH installation
|
@@ -68,15 +68,15 @@ set -e
|
|
68
68
|
|
69
69
|
# Implementation note: 'tee' is used as a sudo-friendly 'cat' to populate a file with the contents provided below.
|
70
70
|
|
71
|
-
tee /etc/conjur.conf > /dev/null <<
|
71
|
+
tee /etc/conjur.conf > /dev/null << EOF
|
72
72
|
account: test
|
73
73
|
appliance_url: https://conjur/api
|
74
74
|
cert_file: /etc/conjur-test.pem
|
75
75
|
netrc_path: /etc/conjur.identity
|
76
76
|
plugins: []
|
77
|
-
|
77
|
+
EOF
|
78
78
|
|
79
|
-
tee /etc/conjur-test.pem > /dev/null <<
|
79
|
+
tee /etc/conjur-test.pem > /dev/null << EOF
|
80
80
|
-----BEGIN CERTIFICATE-----
|
81
81
|
MIIDZTCCAk2gAwIBAgIJAMzfPBZBq82XMA0GCSqGSIb3DQEBBQUAMDMxMTAvBgNV
|
82
82
|
BAMTKGVjMi01NC04My05OS0xMzUuY29tcHV0ZS0xLmFtYXpvbmF3cy5jb20wHhcN
|
@@ -98,17 +98,17 @@ yvml0YdVSiMdTdIk58qG84pkmteSX9VYE1IF7xfWb3ji8292fm5q6cgqFLNYx2MI
|
|
98
98
|
MVs0y+HobWbOKKhyfxpMT59dJxGu21QPbWfQLkHCCOlo2P4z9oku23sbvQQ7CbvS
|
99
99
|
VoykXurdaZo9
|
100
100
|
-----END CERTIFICATE-----
|
101
|
-
|
101
|
+
EOF
|
102
102
|
|
103
|
-
|
103
|
+
touch /etc/conjur.identity
|
104
|
+
chmod 600 /etc/conjur.identity
|
105
|
+
tee /etc/conjur.identity > /dev/null << EOF
|
104
106
|
machine https://conjur/api/authn
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
chmod 0600 /etc/conjur.identity
|
107
|
+
login host/ec2/i-eaa5f700
|
108
|
+
password 3a4rb19rpjejr89h6r29kd2fb3808cpy
|
109
|
+
EOF
|
109
110
|
|
110
111
|
curl -L https://www.opscode.com/chef/install.sh | bash
|
111
|
-
|
112
112
|
"""
|
113
113
|
And the output should match:
|
114
114
|
"""
|
@@ -126,9 +126,9 @@ curl -L https://www.opscode.com/chef/install.sh | bash
|
|
126
126
|
|
127
127
|
Scenario: conjurize with sudo-ized commands
|
128
128
|
When I conjurize "--sudo --ssh"
|
129
|
-
Then the stdout should contain "sudo -n tee /etc/conjur.conf > /dev/null <<
|
130
|
-
And the stdout should contain "sudo -n tee /etc/conjur-test.pem > /dev/null <<
|
131
|
-
And the stdout should contain "sudo -n tee /etc/conjur.identity > /dev/null <<
|
132
|
-
And the stdout should contain "sudo -n chmod
|
129
|
+
Then the stdout should contain "sudo -n tee /etc/conjur.conf > /dev/null << EOF"
|
130
|
+
And the stdout should contain "sudo -n tee /etc/conjur-test.pem > /dev/null << EOF"
|
131
|
+
And the stdout should contain "sudo -n tee /etc/conjur.identity > /dev/null << EOF"
|
132
|
+
And the stdout should contain "sudo -n chmod 600 /etc/conjur.identity"
|
133
133
|
And the stdout should contain "curl -L https://www.opscode.com/chef/install.sh | sudo -n bash"
|
134
134
|
|
data/features/support/env.rb
CHANGED
data/features/support/hooks.rb
CHANGED
data/jenkins.sh
CHANGED
@@ -1,5 +1,33 @@
|
|
1
|
-
#!/bin/bash -
|
1
|
+
#!/bin/bash -ex
|
2
2
|
|
3
|
+
# Constants
|
4
|
+
RUBY_VERSION_DEFAULT="2.1.5"
|
5
|
+
|
6
|
+
# Arguments
|
7
|
+
RUBY_VERSION=${1-${RUBY_VERSION_DEFAULT}}
|
8
|
+
|
9
|
+
# Script
|
10
|
+
|
11
|
+
# Clones 'Dockerfile' and updates the Ruby version in FROM, returning the cloned file's path
|
12
|
+
function dockerfile_path {
|
13
|
+
echo "Setting Ruby version as ${RUBY_VERSION}" >&2
|
14
|
+
cp "Dockerfile" "Dockerfile.${RUBY_VERSION}"
|
15
|
+
sed -i -e "s/${RUBY_VERSION_DEFAULT}/${RUBY_VERSION}/g" Dockerfile.${RUBY_VERSION}
|
16
|
+
|
17
|
+
echo "Dockerfile.${RUBY_VERSION}"
|
18
|
+
}
|
19
|
+
|
20
|
+
rm -f Gemfile.lock # Needed for bundle to work right
|
21
|
+
|
22
|
+
IMAGE_NAME="cli-ruby:${RUBY_VERSION}" # The tag is the version of Ruby tested against
|
23
|
+
|
24
|
+
docker build -t ${IMAGE_NAME} -f $(dockerfile_path) .
|
25
|
+
|
26
|
+
docker run --rm \
|
27
|
+
-v $PWD:/src \
|
28
|
+
${IMAGE_NAME} \
|
29
|
+
bash -c '''
|
3
30
|
bundle update
|
4
31
|
bundle exec rake jenkins
|
5
32
|
bundle exec rake build
|
33
|
+
'''
|
data/lib/conjur/cli.rb
CHANGED
@@ -49,6 +49,8 @@ module Conjur
|
|
49
49
|
class CLI
|
50
50
|
extend GLI::App
|
51
51
|
|
52
|
+
@current_command = nil
|
53
|
+
|
52
54
|
class << self
|
53
55
|
def load_config
|
54
56
|
Conjur::Config.load
|
@@ -69,8 +71,7 @@ module Conjur
|
|
69
71
|
|
70
72
|
def load_plugins
|
71
73
|
# These used to be plugins but now they are in the core CLI
|
72
|
-
plugins = Conjur::Config.plugins - %w(layer pubkeys)
|
73
|
-
|
74
|
+
plugins = Conjur::Config.plugins - %w(audit-send host-factory layer pubkeys)
|
74
75
|
plugins.each do |plugin|
|
75
76
|
begin
|
76
77
|
filename = "conjur-asset-#{plugin}"
|
@@ -92,6 +93,19 @@ module Conjur
|
|
92
93
|
load_plugins
|
93
94
|
commands_from 'conjur/command'
|
94
95
|
end
|
96
|
+
|
97
|
+
def appliance_version
|
98
|
+
Conjur::API.service_version 'appliance'
|
99
|
+
rescue
|
100
|
+
nil
|
101
|
+
end
|
102
|
+
|
103
|
+
def command_version_compatible? command
|
104
|
+
!command.instance_variable_defined?(:@conjur_min_version) ||
|
105
|
+
(appliance_version &&
|
106
|
+
command.instance_variable_get(:@conjur_min_version) <= appliance_version
|
107
|
+
)
|
108
|
+
end
|
95
109
|
end
|
96
110
|
|
97
111
|
init!
|
@@ -123,13 +137,22 @@ module Conjur
|
|
123
137
|
|
124
138
|
true
|
125
139
|
end
|
140
|
+
|
141
|
+
around do |global,command,options,args,code|
|
142
|
+
@current_command = command
|
143
|
+
code.call
|
144
|
+
@current_command = nil
|
145
|
+
end
|
126
146
|
|
127
147
|
on_error do |exception|
|
128
148
|
require 'rest-client'
|
129
149
|
require 'patches/conjur/error'
|
130
|
-
|
150
|
+
|
131
151
|
run_default_handler = true
|
132
|
-
if
|
152
|
+
if @current_command != nil && !command_version_compatible?(@current_command)
|
153
|
+
$stderr.puts "error: this command is not supported by the current Conjur server version"
|
154
|
+
run_default_handler = false
|
155
|
+
elsif exception.is_a?(RestClient::Exception) && exception.response
|
133
156
|
err = Conjur::Error.create exception.response.body
|
134
157
|
if err
|
135
158
|
$stderr.puts "error: " + err.message
|
data/lib/conjur/command.rb
CHANGED
@@ -19,6 +19,7 @@
|
|
19
19
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
20
20
|
#
|
21
21
|
require 'base64'
|
22
|
+
require 'semantic'
|
22
23
|
|
23
24
|
module Conjur
|
24
25
|
class Command
|
@@ -104,6 +105,17 @@ module Conjur
|
|
104
105
|
command.switch [:a, :annotate]
|
105
106
|
end
|
106
107
|
|
108
|
+
def min_version command, version
|
109
|
+
version = Semantic::Version.new version
|
110
|
+
if version.pre == nil
|
111
|
+
# Version check doesn't work correctly if one version has
|
112
|
+
# the "-###" suffix and the other does not. Versions
|
113
|
+
# returned by the server have the suffix.
|
114
|
+
version.pre = "0"
|
115
|
+
end
|
116
|
+
command.instance_variable_set(:@conjur_min_version, version)
|
117
|
+
end
|
118
|
+
|
107
119
|
def prompt_for_annotations
|
108
120
|
highline.say('Add annotations (a name and value for each one):')
|
109
121
|
{}.tap do |annotations|
|
@@ -254,6 +266,22 @@ an alternative destination role.)
|
|
254
266
|
obj.role.revoke_from member
|
255
267
|
end
|
256
268
|
end
|
269
|
+
|
270
|
+
def retire_internal_role roleObj
|
271
|
+
members = roleObj.members
|
272
|
+
# Move the invoking role to the end of the roles list, so that it doesn't
|
273
|
+
# lose its permissions in the middle of this operation.
|
274
|
+
self_member = members.select{|m| m.member.roleid == current_user.role.roleid}
|
275
|
+
self_member.each do |m|
|
276
|
+
members.delete m
|
277
|
+
end
|
278
|
+
members.concat self_member if self_member
|
279
|
+
members.each do |r|
|
280
|
+
member = api.role(r.member)
|
281
|
+
puts "Revoking from role #{member.roleid}"
|
282
|
+
roleObj.revoke_from member
|
283
|
+
end
|
284
|
+
end
|
257
285
|
|
258
286
|
def give_away_resource obj, options
|
259
287
|
destination = options[:"destination-role"]
|
@@ -420,6 +448,14 @@ an alternative destination role.)
|
|
420
448
|
|
421
449
|
password
|
422
450
|
end
|
451
|
+
|
452
|
+
def has_admin?(role, other_role)
|
453
|
+
memberships = role.memberships.map(&:roleid)
|
454
|
+
other_role.members.any? { |m| memberships.member?(m.member.roleid) && m.admin_option }
|
455
|
+
rescue RestClient::Forbidden
|
456
|
+
false
|
457
|
+
end
|
458
|
+
|
423
459
|
end
|
424
460
|
end
|
425
461
|
end
|
data/lib/conjur/command/audit.rb
CHANGED
@@ -138,6 +138,18 @@ class Conjur::Command
|
|
138
138
|
id = full_resource_id(require_arg args, "resource")
|
139
139
|
api.audit_resource(id, options){|es| show_audit_events es, options}
|
140
140
|
end
|
141
|
+
|
142
|
+
audit.desc "Send custom event(s) to audit system"
|
143
|
+
audit.long_desc "Send custom event(s) to audit system. Events should be provided in JSON format, describing either single hash or array of hashes."
|
144
|
+
audit.arg_name "( json_string | STDIN )"
|
145
|
+
audit.command :send do |c|
|
146
|
+
c.action do |global_options, options, args|
|
147
|
+
json = ( args.shift || STDIN.read )
|
148
|
+
api.audit_send json
|
149
|
+
puts "Events sent successfully"
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
141
153
|
end
|
142
154
|
end
|
143
155
|
end
|
@@ -58,18 +58,14 @@ class Conjur::Command::Bootstrap < Conjur::Command
|
|
58
58
|
api.user(username)
|
59
59
|
end
|
60
60
|
security_admin = api.group("security_admin")
|
61
|
-
memberships = user.role.memberships.map(&:roleid) if user
|
62
61
|
|
63
62
|
if user
|
63
|
+
memberships = user.role.memberships.map(&:roleid)
|
64
64
|
if security_admin.exists?
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
memberships.member?(security_admin.resource.ownerid)
|
70
|
-
rescue RestClient::Forbidden
|
71
|
-
false
|
72
|
-
end
|
65
|
+
# The user has a role which is admin of the security_admin role
|
66
|
+
# The user has the role which owns the security_admin resource
|
67
|
+
has_admin?(user.role, security_admin.role) &&
|
68
|
+
memberships.member?(security_admin.resource.ownerid)
|
73
69
|
else
|
74
70
|
user.login == "admin"
|
75
71
|
end
|
@@ -0,0 +1,187 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (C) 2014 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
|
+
|
22
|
+
class Conjur::Command::HostFactories < Conjur::Command
|
23
|
+
desc "Manage host factories"
|
24
|
+
|
25
|
+
command :hostfactory do |hf|
|
26
|
+
hf.desc "Create a new host factory"
|
27
|
+
hf.arg_name "id"
|
28
|
+
hf.command :create do |c|
|
29
|
+
acting_as_option(c)
|
30
|
+
|
31
|
+
c.arg_name "layer"
|
32
|
+
c.desc "A space-delimited list of layers to which new hosts will belong"
|
33
|
+
c.flag [:l, :layer]
|
34
|
+
|
35
|
+
c.action do |global_options,options,args|
|
36
|
+
id = require_arg(args, 'hostfactory')
|
37
|
+
|
38
|
+
unless options[:ownerid]
|
39
|
+
exit_now! "Use --as-group or --as-role to indicate the host factory role"
|
40
|
+
end
|
41
|
+
|
42
|
+
owner_role = api.role(options[:ownerid])
|
43
|
+
|
44
|
+
layers = (options[:layer] || "").split(/\s/)
|
45
|
+
exit_now! "Provide at least one layer" unless layers.count > 0
|
46
|
+
|
47
|
+
layers.each do |layerid|
|
48
|
+
layer = api.layer(layerid)
|
49
|
+
exit_now! "Layer '#{layerid}' does not exist" unless layer.exists?
|
50
|
+
unless has_admin?(owner_role, layer.role)
|
51
|
+
exit_now! "#{owner_role.id} must be an admin of layer '#{layerid}' to create a host factory for it"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
command_options = options.dup
|
56
|
+
command_options[:layers] = layers
|
57
|
+
command_options[:roleid] = options[:ownerid]
|
58
|
+
|
59
|
+
host_factory = api.create_host_factory id, command_options
|
60
|
+
display host_factory
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
hf.desc "Show a host factory"
|
65
|
+
hf.arg_name "id"
|
66
|
+
hf.command :show do |c|
|
67
|
+
c.action do |global_options,options,args|
|
68
|
+
id = require_arg(args, 'id')
|
69
|
+
display(api.host_factory(id), options)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
hf.desc "List host factories"
|
74
|
+
hf.command :list do |c|
|
75
|
+
command_options_for_list c
|
76
|
+
c.action do |global_options, options, args|
|
77
|
+
command_impl_for_list global_options, options.merge(kind: "host_factory"), args
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
hf.desc "Operations on tokens"
|
82
|
+
hf.long_desc <<-DESC
|
83
|
+
This command creates one or more identical tokens. A token is always created with an
|
84
|
+
expiration time, which by default is 1 hour from now. The expiration time can be customized
|
85
|
+
with command arguments specifying the number of minutes, hours, days for which the token
|
86
|
+
will be valid.
|
87
|
+
|
88
|
+
By default, this command creates one token. Optionally, it can be used to create multiple identical tokens.
|
89
|
+
DESC
|
90
|
+
hf.command :tokens do |tokens|
|
91
|
+
|
92
|
+
tokens.desc "Create one or more tokens"
|
93
|
+
tokens.arg_name "hostfactory"
|
94
|
+
tokens.command :create do |c|
|
95
|
+
c.arg_name "duration in minutes"
|
96
|
+
c.desc "Number of minutes from now in which the token will expire"
|
97
|
+
c.flag [:"duration-minutes"]
|
98
|
+
|
99
|
+
c.arg_name "duration in hours"
|
100
|
+
c.desc "Number of hours from now in which the token will expire"
|
101
|
+
c.flag [:"duration-hours"]
|
102
|
+
|
103
|
+
c.arg_name "duration in days"
|
104
|
+
c.desc "Number of days from now in which the token will expire"
|
105
|
+
c.flag [:"duration-days"]
|
106
|
+
|
107
|
+
c.arg_name "count"
|
108
|
+
c.desc "Number of identical tokens to create"
|
109
|
+
c.flag [:c, :count]
|
110
|
+
|
111
|
+
c.arg_name "cidr"
|
112
|
+
c.desc "A comma-delimited list of CIDR addresses to restrict token to (optional)"
|
113
|
+
c.flag [:cidr]
|
114
|
+
|
115
|
+
c.action do |global_options,options,args|
|
116
|
+
id = require_arg(args, 'hostfactory')
|
117
|
+
|
118
|
+
duration = 0
|
119
|
+
%w(duration-minutes duration-hours duration-days).each do |d|
|
120
|
+
if t = options[d.to_sym]
|
121
|
+
duration += t.to_i.send(d.split('-')[-1])
|
122
|
+
end
|
123
|
+
end
|
124
|
+
if duration == 0
|
125
|
+
duration = 1.hour
|
126
|
+
end
|
127
|
+
expiration = Time.now + duration
|
128
|
+
count = (options[:count] || 1).to_i
|
129
|
+
command_options = {}
|
130
|
+
|
131
|
+
cidr = format_cidr(options.delete(:cidr))
|
132
|
+
command_options[:cidr] = cidr unless cidr.nil?
|
133
|
+
|
134
|
+
tokens = api.host_factory(id).create_tokens expiration, count, command_options
|
135
|
+
display tokens.map(&:to_json)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
tokens.desc "Revoke (delete) a token"
|
140
|
+
tokens.arg_name "token"
|
141
|
+
tokens.command :revoke do |c|
|
142
|
+
c.action do |global_options,options,args|
|
143
|
+
token = require_arg(args, 'token')
|
144
|
+
|
145
|
+
api.revoke_host_factory_token token
|
146
|
+
puts "Token revoked"
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
tokens.desc "Show a token"
|
151
|
+
tokens.arg_name "token"
|
152
|
+
tokens.command :show do |c|
|
153
|
+
c.action do |global_options,options,args|
|
154
|
+
token = require_arg(args, 'token')
|
155
|
+
|
156
|
+
display api.show_host_factory_token(token), options
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
hf.desc "Operations on hosts"
|
162
|
+
hf.command :hosts do |hosts|
|
163
|
+
hosts.desc "Use a token to create a host"
|
164
|
+
hosts.arg_name "token host-id"
|
165
|
+
hosts.command :create do |c|
|
166
|
+
c.action do |global_options,options,args|
|
167
|
+
token = require_arg(args, 'token')
|
168
|
+
id = require_arg(args, 'host-id')
|
169
|
+
|
170
|
+
host = Conjur::API.host_factory_create_host token, id, options
|
171
|
+
display host
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def self.format_cidr(cidr)
|
178
|
+
case cidr
|
179
|
+
when 'all'
|
180
|
+
[]
|
181
|
+
when nil
|
182
|
+
nil
|
183
|
+
else
|
184
|
+
cidr.split(',').each {|x| x.strip!}
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|