conjur-cli 4.9.3 → 4.10.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -17,104 +17,105 @@
17
17
  # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18
18
  # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19
19
  # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
- #
21
- require 'conjur/authn'
22
- require 'conjur/command'
23
20
 
24
21
  class Conjur::Command::Assets < Conjur::Command
25
- self.prefix = :asset
26
-
27
- desc "Create an asset"
28
- arg_name "kind:id"
29
- command :create do |c|
30
- def c.nodoc; true end
31
- acting_as_option(c)
32
-
33
- c.action do |global_options, options, args|
34
- # NOTE: no generic functions there, as :id is optional
35
- kind, id = require_arg(args, 'kind:id').split(':')
36
- id = nil if id.blank?
37
- kind.gsub!('-', '_')
22
+ # Toplevel command
23
+ desc "Manage assets"
24
+ command :asset do |asset|
25
+ hide_docs(asset)
26
+ asset.desc "Create an asset"
27
+ asset.arg_name "kind:id"
28
+ asset.command :create do |create|
29
+ hide_docs(create)
30
+ acting_as_option(create)
31
+ create.action do |global_options, options, args|
32
+ # NOTE: no generic functions there, as :id is optional
33
+ kind, id = require_arg(args, 'kind:id').split(':')
34
+ id = nil if id.blank?
35
+ kind.gsub!('-', '_')
38
36
 
39
-
40
- m = "create_#{kind}"
41
- record = if [ 1, -1 ].member?(api.method(m).arity)
42
- if id
43
- options[:id] = id
44
- end
45
- api.send(m, options)
46
- else
47
- unless id
48
- raise "for kind #{kind} id should be specified explicitly after colon"
49
- end
50
- api.send(m, id, options)
37
+ m = "create_#{kind}"
38
+ record = if [ 1, -1 ].member?(api.method(m).arity)
39
+ if id
40
+ options[:id] = id
41
+ end
42
+ api.send(m, options)
43
+ else
44
+ unless id
45
+ raise "for kind #{kind} id should be specified explicitly after colon"
46
+ end
47
+ api.send(m, id, options)
48
+ end
49
+ display(record, options)
51
50
  end
52
- display(record, options)
53
51
  end
54
- end
55
-
56
- desc "Show an asset"
57
- arg_name "id"
58
- command :show do |c|
59
- def c.nodoc; true end
60
- c.action do |global_options,options,args|
61
- kind, id = get_kind_and_id_from_args(args, 'id')
62
- display api.send(kind, id).attributes
52
+
53
+ asset.desc "Show an asset"
54
+ asset.arg_name "id"
55
+ asset.command :show do |c|
56
+ c.action do |global_options,options,args|
57
+ kind, id = get_kind_and_id_from_args(args, 'id')
58
+ display api.send(kind, id).attributes
59
+ end
63
60
  end
64
- end
65
61
 
66
- desc "Checks for the existance of an asset"
67
- arg_name "id"
68
- command :exists do |c|
69
- def c.nodoc; true end
70
- c.action do |global_options,options,args|
71
- kind, id = get_kind_and_id_from_args(args, 'id')
72
- puts api.send(kind, id).exists?
62
+ asset.desc "Checks for the exisistance of an asset"
63
+ asset.arg_name "id"
64
+ asset.command :exists do |c|
65
+ c.action do |global_options,options,args|
66
+ kind, id = get_kind_and_id_from_args(args, 'id')
67
+ puts api.send(kind, id).exists?
68
+ end
73
69
  end
74
- end
75
70
 
76
- desc "List an asset"
77
- arg_name "kind"
78
- command :list do |c|
79
- def c.nodoc; true end
80
- c.action do |global_options,options,args|
81
- kind = require_arg(args, "kind").gsub('-', '_')
82
- if api.respond_to?(kind.pluralize)
83
- api.send(kind.pluralize)
84
- else
85
- api.resources(kind: kind)
86
- end.each do |e|
87
- display(e, options)
71
+ asset.desc "List assets of a given kind"
72
+ asset.arg_name "kind"
73
+ asset.command :list do |c|
74
+ hide_docs c
75
+ c.action do |global_options,options,args|
76
+ kind = require_arg(args, "kind").gsub('-', '_')
77
+ if api.respond_to?(kind.pluralize)
78
+ api.send(kind.pluralize)
79
+ else
80
+ api.resources(kind: kind)
81
+ end.each do |e|
82
+ display(e, options)
83
+ end
88
84
  end
89
85
  end
90
- end
91
86
 
92
- desc "Add a member to an asset"
93
- arg_name "id role-name member"
94
- command :"members:add" do |c|
95
- c.desc "Grant with admin option"
96
- c.flag [:a, :admin]
87
+ asset.desc "Manage asset membership"
88
+ asset.command :members do |members|
89
+ members.desc "Add a member to an asset"
90
+ members.arg_name "id role-name member"
91
+ members.command :add do |c|
92
+ hide_docs(c)
93
+ c.desc "Grant with admin option"
94
+ c.flag [:a, :admin]
97
95
 
98
- c.action do |global_options, options, args|
99
- kind, id = get_kind_and_id_from_args(args, 'id')
100
- role_name = require_arg(args, 'role-name')
101
- member = require_arg(args, 'member')
102
- admin_option = !options.delete(:admin).nil?
103
-
104
- api.send(kind, id).add_member role_name, member, admin_option: admin_option
105
- puts "Membership granted"
106
- end
107
- end
96
+ c.action do |global_options, options, args|
97
+ kind, id = get_kind_and_id_from_args(args, 'id')
98
+ role_name = require_arg(args, 'role-name')
99
+ member = require_arg(args, 'member')
100
+ admin_option = !options.delete(:admin).nil?
108
101
 
109
- desc "Remove a member from an asset"
110
- arg_name "id role-name member"
111
- command :"members:remove" do |c|
112
- c.action do |global_options, options, args|
113
- kind, id = get_kind_and_id_from_args(args, 'id')
114
- role_name = require_arg(args, 'role-name')
115
- member = require_arg(args, 'member')
116
- api.send(kind, id).remove_member role_name, member
117
- puts "Membership revoked"
102
+ api.send(kind, id).add_member role_name, member, admin_option: admin_option
103
+ puts "Membership granted"
104
+ end
105
+ end
106
+
107
+ members.desc "Remove a member from an asset"
108
+ members.arg_name "id role-name member"
109
+ members.command :remove do |c|
110
+ hide_docs c
111
+ c.action do |global_options, options, args|
112
+ kind, id = get_kind_and_id_from_args(args, 'id')
113
+ role_name = require_arg(args, 'role-name')
114
+ member = require_arg(args, 'member')
115
+ api.send(kind, id).remove_member role_name, member
116
+ puts "Membership revoked"
117
+ end
118
+ end
118
119
  end
119
120
  end
120
121
  end
@@ -1,11 +1,5 @@
1
- require 'conjur/command'
2
- require 'active_support/ordered_hash'
3
- require 'conjur/audit/follower'
4
-
5
1
  class Conjur::Command
6
2
  class Audit < self
7
- self.prefix = 'audit'
8
-
9
3
  class << self
10
4
  private
11
5
  SHORT_FORMATS = {
@@ -15,7 +9,7 @@ class Conjur::Command
15
9
  'resource:destroy' => lambda{|e| "destroyed resource #{e[:resource]}" },
16
10
  'resource:permit' => lambda{|e| "permitted #{e[:grantee]} to #{e[:privilege]} #{e[:resource]} (grant option: #{!!e[:grant_option]})" },
17
11
  'resource:deny' => lambda{|e| "denied #{e[:privilege]} from #{e[:grantee]} on #{e[:resource]}" },
18
- 'resource:permitted_roles' => lambda{|e| "listed roles permitted to #{e[:permission]} on #{e[:resource]}" },
12
+ 'resource:permitted_roles' => lambda{|e| "listed roles permitted to #{e[:privilege]} on #{e[:resource]}" },
19
13
  'role:check' => lambda{|e| "checked that #{e[:role] == e[:user] ? 'they' : e[:role]} can #{e[:privilege]} #{e[:resource]} (#{e[:allowed]})" },
20
14
  'role:grant' => lambda{|e| "granted role #{e[:role]} to #{e[:member]} #{e[:admin_option] ? ' with ' : ' without '}admin" },
21
15
  'role:revoke' => lambda{|e| "revoked role #{e[:role]} from #{e[:member]}" },
@@ -66,8 +60,8 @@ class Conjur::Command
66
60
  end
67
61
  end
68
62
 
69
- def audit_feed_command kind, &block
70
- command kind do |c|
63
+ def audit_feed_command parent, kind, &block
64
+ parent.command kind do |c|
71
65
  c.desc "Maximum number of events to fetch"
72
66
  c.flag [:l, :limit]
73
67
 
@@ -88,23 +82,28 @@ class Conjur::Command
88
82
  end
89
83
  end
90
84
 
91
- desc "Show all audit events visible to the current user"
92
- audit_feed_command :all do |args, options|
93
- api.audit(options){ |es| show_audit_events es, options }
94
- end
95
-
96
- desc "Show audit events related to a role"
97
- arg_name 'role'
98
- audit_feed_command :role do |args, options|
99
- id = full_resource_id(require_arg(args, "role"))
100
- api.audit_role(id, options){ |es| show_audit_events es, options }
101
- end
102
-
103
- desc "Show audit events related to a resource"
104
- arg_name 'resource'
105
- audit_feed_command :resource do |args, options|
106
- id = full_resource_id(require_arg args, "resource")
107
- api.audit_resource(id, options){|es| show_audit_events es, options}
85
+ desc "Show audit events"
86
+ command :audit do |audit|
87
+ audit.desc "Show all audit events visible to the current user"
88
+ audit_feed_command audit, :all do |args, options|
89
+ api.audit(options){ |es| show_audit_events es, options }
90
+ end
91
+
92
+
93
+ audit.desc "Show audit events related to a role"
94
+ audit.arg_name 'role'
95
+ audit_feed_command audit, :role do |args, options|
96
+ id = full_resource_id(require_arg(args, "role"))
97
+ api.audit_role(id, options){ |es| show_audit_events es, options }
98
+ end
99
+
100
+
101
+ audit.desc "Show audit events related to a resource"
102
+ audit.arg_name 'resource'
103
+ audit_feed_command audit, :resource do |args, options|
104
+ id = full_resource_id(require_arg args, "resource")
105
+ api.audit_resource(id, options){|es| show_audit_events es, options}
106
+ end
108
107
  end
109
108
  end
110
109
  end
@@ -17,68 +17,80 @@
17
17
  # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18
18
  # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19
19
  # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
- #
21
- require 'conjur/authn'
22
- require 'conjur/command'
20
+
23
21
 
24
22
  class Conjur::Command::Authn < Conjur::Command
25
- self.prefix = :authn
26
-
27
- desc "Logs in and caches credentials to netrc"
28
- long_desc <<-DESC
29
- After successful login, subsequent commands automatically use the cached credentials. To switch users, login again using the new user credentials.
30
- To erase credentials, use the authn:logout command.
23
+ desc "Login and logout"
24
+ command :authn do |authn|
25
+ authn.desc "Logs in and caches credentials to netrc."
26
+ authn.arg_name "login-name"
27
+ authn.long_desc <<-DESC
28
+ Logins in a user. Login name can be provided as the command argument, as -u or --username, or the command will prompt
29
+ for the username. Password can be provided as -p, --password, or the command will prompt for the password.
30
+
31
+ On successful login, the password is exchanged for the API key, which is cached in the operating system user's
32
+ .netrc file. Subsequent "conjur" commands will authenticate with the cached login name and API key. To switch users,
33
+ login again using the new user credentials. To erase credentials, use the 'authn logout' command.
31
34
 
32
35
  If specified, the CAS server URL should be in the form https://<hostname>/v1.
33
36
  It should be running the CAS RESTful services at the /v1 path
34
37
  (or other path as specified by this argument).
35
- DESC
36
- command :login do |c|
37
- c.arg_name 'username'
38
- c.flag [:u,:username]
38
+ DESC
39
+ authn.command :login do |c|
40
+ c.arg_name 'username'
41
+ c.flag [:u,:username]
39
42
 
40
- c.arg_name 'password'
41
- c.flag [:p,:password]
43
+ c.arg_name 'password'
44
+ c.flag [:p,:password]
42
45
 
43
- c.arg_name 'CAS server'
44
- c.desc 'Specifies a CAS server URL to use for login'
45
- c.flag [:"cas-server"]
46
-
47
- c.action do |global_options,options,args|
48
- Conjur::Authn.login(options)
46
+ c.arg_name 'CAS server'
47
+ c.desc 'Specifies a CAS server URL to use for login'
48
+ c.flag [:"cas-server"]
49
+
50
+ c.action do |global_options,options,args|
51
+ if options[:username].blank? && !args.empty?
52
+ options[:username] = args.pop
53
+ end
54
+
55
+ Conjur::Authn.login(options.slice(:username, :password))
56
+
57
+ puts "Logged in"
58
+ end
49
59
  end
50
- end
51
-
52
- desc "Obtains an authentication token using the current logged-in user"
53
- command :authenticate do |c|
54
- c.arg_name 'header'
55
- c.desc "Base64 encode the result and format as an HTTP Authorization header"
56
- c.switch [:H,:header]
57
60
 
58
- c.action do |global_options,options,args|
59
- token = Conjur::Authn.authenticate(options)
60
- if options[:header]
61
- puts "Authorization: Token token=\"#{Base64.strict_encode64(token.to_json)}\""
62
- else
63
- puts token
61
+ authn.desc "Obtains an authentication token using the current logged-in user"
62
+ authn.command :authenticate do |c|
63
+ c.arg_name 'header'
64
+ c.desc "Base64 encode the result and format as an HTTP Authorization header"
65
+ c.switch [:H,:header]
66
+
67
+ c.action do |global_options,options,args|
68
+ token = Conjur::Authn.authenticate(options)
69
+ if options[:header]
70
+ puts "Authorization: Token token=\"#{Base64.strict_encode64(token.to_json)}\""
71
+ else
72
+ display token
73
+ end
64
74
  end
65
75
  end
66
- end
67
-
68
- desc "Logs out"
69
- command :logout do |c|
70
- c.action do
71
- Conjur::Authn.delete_credentials
76
+
77
+ authn.desc "Logs out"
78
+ authn.command :logout do |c|
79
+ c.action do
80
+ Conjur::Authn.delete_credentials
81
+
82
+ puts "Logged out"
83
+ end
72
84
  end
73
- end
74
85
 
75
- desc "Prints out the current logged in username"
76
- command :whoami do |c|
77
- c.action do
78
- if creds = Conjur::Authn.read_credentials
79
- puts({account: Conjur::Core::API.conjur_account, username: creds[0]}.to_json)
80
- else
81
- exit_now! 'Not logged in.', -1
86
+ authn.desc "Prints out the current logged in username"
87
+ authn.command :whoami do |c|
88
+ c.action do
89
+ if creds = Conjur::Authn.read_credentials
90
+ puts({account: Conjur::Core::API.conjur_account, username: creds[0]}.to_json)
91
+ else
92
+ exit_now! 'Not logged in.', -1
93
+ end
82
94
  end
83
95
  end
84
96
  end
@@ -18,7 +18,6 @@
18
18
  # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19
19
  # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
20
  #
21
- require 'conjur/command'
22
21
 
23
22
  class Conjur::DSLCommand < Conjur::Command
24
23
  class << self
@@ -18,14 +18,15 @@
18
18
  # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19
19
  # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
20
  #
21
- require 'conjur/authn'
22
- require 'conjur/command'
21
+ #require 'conjur/authn'
22
+ #require 'conjur/command'
23
23
  require 'conjur/conjurenv'
24
24
  require 'tempfile'
25
25
 
26
26
  class Conjur::Command::Env < Conjur::Command
27
-
28
- self.prefix = :env
27
+
28
+ desc "Use values of Conjur variables in local context"
29
+ #self.prefix = :env
29
30
 
30
31
  def self.common_parameters c
31
32
  c.desc "Environment configuration file"
@@ -49,8 +50,9 @@ class Conjur::Command::Env < Conjur::Command
49
50
  return env
50
51
  end
51
52
 
52
- desc "Execute external command with environment variables populated from Conjur"
53
- long_desc <<'RUNLONGDESC'
53
+ command :env do |env|
54
+ env.desc "Execute external command with environment variables populated from Conjur"
55
+ env.long_desc <<'RUNLONGDESC'
54
56
  Processes environment configuration (see env:help for details), and executes a command (with optional arguments) in the modified environment.
55
57
  Local names are uppercased and used as names of environment variables.
56
58
 
@@ -66,38 +68,37 @@ KEY_PAIR_NAME="jenkins_key",
66
68
  SSH_KEYPAIR_PATH="/dev/shm/temp_file_with_key_obtained_from_Conjur",
67
69
  API_KEY="api key obtained from Conjur"
68
70
  RUNLONGDESC
69
- arg_name "-- command [arg1, arg2 ...] "
70
- command :run do |c|
71
- common_parameters(c)
72
-
73
- c.action do |global_options,options,args|
74
- if args.empty?
75
- exit_now! "External command with optional arguments should be provided"
76
- end
77
- env = get_env_object(options)
78
- runtime_environment = Hash[ env.obtain(api).map {|k,v| [k.upcase, v] } ]
79
- if Conjur.log
80
- Conjur.log << "Running command in the prepared environment: #{args}"
71
+ env.arg_name "-- command [arg1, arg2 ...] "
72
+ env.command :run do |c|
73
+ common_parameters(c)
74
+
75
+ c.action do |global_options,options,args|
76
+ if args.empty?
77
+ exit_now! "External command with optional arguments should be provided"
78
+ end
79
+ env = get_env_object(options)
80
+ runtime_environment = Hash[ env.obtain(api).map {|k,v| [k.upcase, v] } ]
81
+ if Conjur.log
82
+ Conjur.log << "Running command in the prepared environment: #{args}"
83
+ end
84
+ Kernel.system(runtime_environment, *args) or exit($?.to_i) # keep original exit code in case of failure
81
85
  end
82
- Kernel.system(runtime_environment, *args) or exit($?.to_i) # keep original exit code in case of failure
83
86
  end
84
- end
85
-
86
- desc "Check availability of Conjur variables"
87
- long_desc "Checks availability of Conjur variables mentioned in an environment configuration (see env:help for details), and prints out each local name and appropriate status"
88
87
 
89
- command :check do |c|
90
- common_parameters(c)
91
- c.action do |global_options,options,args|
92
- env = get_env_object(options)
93
- result = env.check(api)
94
- result.each { |k,v| puts "#{k}: #{v}" }
95
- raise "Some variables are not available" unless result.values.select {|v| v == :unavailable }.empty?
96
- end
97
- end # command
88
+ env.desc "Check availability of Conjur variables"
89
+ env.long_desc "Checks availability of Conjur variables mentioned in an environment configuration (see env:help for details), and prints out each local name and appropriate status"
90
+ env.command :check do |c|
91
+ common_parameters(c)
92
+ c.action do |global_options,options,args|
93
+ env = get_env_object(options)
94
+ result = env.check(api)
95
+ result.each { |k,v| puts "#{k}: #{v}" }
96
+ raise "Some variables are not available" unless result.values.select {|v| v == :unavailable }.empty?
97
+ end
98
+ end # command
98
99
 
99
- desc "Render ERB template with variables obtained from Conjur"
100
- long_desc <<'TEMPLATEDESC'
100
+ env.desc "Render ERB template with variables obtained from Conjur"
101
+ env.long_desc <<'TEMPLATEDESC'
101
102
  Processes environment configuration (see env:help for details), and creates a temporary file, which contains result of ERB template rendering in appropriate context.
102
103
  Template should refer to Conjur values by local name as "%<= conjurenv['local_name'] %>".
103
104
 
@@ -117,37 +118,38 @@ key_pair=jenkins_key, path_to_ssh_key=/dev/shm/temp_file_with_key_obtained_from_
117
118
 
118
119
  Result of the rendering will be stored in temporary file, which location is than printed to stdout
119
120
  TEMPLATEDESC
120
- arg_name "template.erb"
121
- command :template do |c|
122
- common_parameters(c)
123
-
124
- c.action do |global_options,options,args|
125
- template_file = args.first
126
- exit_now! "Location of readable ERB template should be provided" unless template_file and File.readable?(template_file)
127
- template = File.read(template_file)
128
- env = get_env_object(options)
129
- conjurenv = env.obtain(api) # needed for binding
130
- rendered = ERB.new(template).result(binding)
131
-
132
- #
133
- tempfile = if File.directory?("/dev/shm") and File.writable?("/dev/shm")
134
- Tempfile.new("conjur","/dev/shm")
135
- else
136
- Tempfile.new("conjur")
137
- end
138
- tempfile.write(rendered)
139
- tempfile.close()
140
- old_path = tempfile.path
141
- new_path = old_path+".saved"
142
- FileUtils.copy(old_path, new_path) # prevent garbage collection
143
- puts new_path
121
+ env.arg_name "template.erb"
122
+
123
+ env.command :template do |c|
124
+ common_parameters(c)
125
+
126
+ c.action do |global_options,options,args|
127
+ template_file = args.first
128
+ exit_now! "Location of readable ERB template should be provided" unless template_file and File.readable?(template_file)
129
+ template = File.read(template_file)
130
+ env = get_env_object(options)
131
+ conjurenv = env.obtain(api) # needed for binding
132
+ rendered = ERB.new(template).result(binding)
133
+
134
+ #
135
+ tempfile = if File.directory?("/dev/shm") and File.writable?("/dev/shm")
136
+ Tempfile.new("conjur","/dev/shm")
137
+ else
138
+ Tempfile.new("conjur")
139
+ end
140
+ tempfile.write(rendered)
141
+ tempfile.close()
142
+ old_path = tempfile.path
143
+ new_path = old_path+".saved"
144
+ FileUtils.copy(old_path, new_path) # prevent garbage collection
145
+ puts new_path
146
+ end
144
147
  end
145
- end
146
148
 
147
- desc "Print description of environment configuration format"
148
- command :help do |c|
149
- c.action do |global_options,options,args|
150
- puts """
149
+ env.desc "Print description of environment configuration format"
150
+ env.command :help do |c|
151
+ c.action do |global_options,options,args|
152
+ puts """
151
153
  Environment configuration (either stored in file referred by -f option or provided inline with --yaml option) should be a YAML document describing one-level Hash.
152
154
  Keys of the hash are 'local names', used to refer to variable values in convenient manner. (See help for env:run and env:template for more details about how they are interpreted).
153
155
 
@@ -163,8 +165,9 @@ Example of environment configuration:
163
165
 
164
166
  { local_variable_1: 'literal value', local_variable_2: !var id/of/Conjur/Variable , local_variable_3: !tmp id/of/another/Conjur/variable }
165
167
 
166
- """
168
+ """
169
+ end
167
170
  end
168
- end
169
171
 
172
+ end
170
173
  end