conjur-cli 4.6.1 → 4.7.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.
Binary file
data/Gemfile CHANGED
@@ -4,7 +4,13 @@ source 'https://rubygems.org'
4
4
  gemspec
5
5
 
6
6
  gem 'conjur-api', git: 'https://github.com/inscitiv/api-ruby.git', branch: 'master'
7
-
8
7
  group :test, :development do
9
8
  gem 'pry'
10
9
  end
10
+
11
+ group :development do
12
+ gem 'conjur-asset-environment-api'
13
+ gem 'conjur-asset-key-pair-api'
14
+ gem 'conjur-asset-layer-api'
15
+ # gem 'conjur-asset-ui-api', github: 'conjurinc/conjur-asset-ui', branch: 'new-audit'
16
+ end
@@ -75,7 +75,11 @@ class Conjur::Command::Assets < Conjur::Command
75
75
  command :list do |c|
76
76
  c.action do |global_options,options,args|
77
77
  kind = require_arg(args, "kind").gsub('-', '_')
78
- api.send(kind.pluralize).each do |e|
78
+ if api.respond_to?(kind.pluralize)
79
+ api.send(kind.pluralize)
80
+ else
81
+ api.resources(kind: kind)
82
+ end.each do |e|
79
83
  display(e, options)
80
84
  end
81
85
  end
@@ -0,0 +1,65 @@
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
+ require 'conjur/command'
22
+
23
+ class Conjur::DSLCommand < Conjur::Command
24
+ class << self
25
+ def file_or_stdin_arg(args)
26
+ end
27
+
28
+ def run_script(args, options, &block)
29
+ filename = nil
30
+ script = if script = args.pop
31
+ filename = script
32
+ script = File.read(script)
33
+ else
34
+ STDIN.read
35
+ end
36
+
37
+ require 'conjur/dsl/runner'
38
+ runner = Conjur::DSL::Runner.new(script, filename)
39
+
40
+ if context = options[:context]
41
+ runner.context = begin
42
+ JSON.parse(File.read(context))
43
+ rescue Errno::ENOENT
44
+ {}
45
+ end
46
+ end
47
+
48
+ if block_given?
49
+ block.call(runner) do
50
+ runner.execute
51
+ end
52
+ else
53
+ runner.execute
54
+ end
55
+
56
+ if context
57
+ File.write(context, JSON.pretty_generate(runner.context))
58
+ File.chmod(0600, context)
59
+ end
60
+
61
+ puts JSON.pretty_generate(runner.context)
62
+ end
63
+ end
64
+
65
+ end
@@ -0,0 +1,83 @@
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
+ require 'conjur/command/dsl_command'
22
+
23
+ class Conjur::Command::Policy < Conjur::DSLCommand
24
+ self.prefix = :policy
25
+
26
+ class << self
27
+ def default_collection_user
28
+ ( ENV['USER'] ).strip
29
+ end
30
+
31
+ def default_collection_hostname
32
+ ( ENV['HOSTNAME'] || `hostname` ).strip
33
+ end
34
+
35
+ def default_collection_name
36
+ [ default_collection_user, default_collection_hostname ].join('@')
37
+ end
38
+ end
39
+
40
+ desc "Load a policy from Conjur DSL"
41
+ long_desc <<-DESC
42
+ This method is EXPERIMENTAL and subject to change
43
+
44
+ Loads a Conjur policy from DSL, applying particular conventions to the role and resource
45
+ ids.
46
+
47
+ The first path element of each id is the collection. Policies are separated into collections
48
+ according to software development lifecycle. The default collection for a policy is $USER@$HOSTNAME,
49
+ in other words, the username and hostname on which the policy is created. This is approriate for
50
+ policy development and local testing. Once tested, policies can be created in more official
51
+ environments such as ci, stage, and production.
52
+
53
+ The second path element of each id is the policy name and version, following the convention
54
+ policy-x.y.z, where x, y, and z are the semantic version of the policy.
55
+
56
+ Next, each policy creates a policy role and policy resource. The policy resource is used to store
57
+ annotations on the policy. The policy role becomes the owner of the owned policy assets. The
58
+ --as-group and --as-role options can be used to set the owner of the policy role. The default
59
+ owner of the policy role is the logged-in user (you), as always.
60
+ DESC
61
+ arg_name "(policy-file | STDIN)"
62
+ command :load do |c|
63
+ acting_as_option(c)
64
+
65
+ c.desc "Policy collection (default: #{default_collection_user}@#{default_collection_hostname})"
66
+ c.arg_name "collection"
67
+ c.flag [:collection]
68
+
69
+ c.desc "Load context from this config file, and save it when finished. The file permissions will be 0600 by default."
70
+ c.arg_name "context"
71
+ c.flag [:c, :context]
72
+
73
+ c.action do |global_options,options,args|
74
+ collection = options[:collection] || default_collection_name
75
+
76
+ run_script args, options do |runner, &block|
77
+ runner.scope collection do
78
+ block.call
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -51,7 +51,7 @@ class Conjur::Command::Resources < Conjur::Command
51
51
  display api.resource(id).attributes
52
52
  end
53
53
  end
54
-
54
+
55
55
  desc "Determines whether a resource exists"
56
56
  arg_name "resource-id"
57
57
  command :exists do |c|
@@ -129,4 +129,82 @@ class Conjur::Command::Resources < Conjur::Command
129
129
  display api.resource(id).permitted_roles(permission)
130
130
  end
131
131
  end
132
+
133
+ desc "Set an annotation on a resource"
134
+ arg_name "resource-id name value"
135
+ command :annotate do |c|
136
+ c.action do |global_options, options, args|
137
+ id = full_resource_id require_arg(args, 'resource-id')
138
+ name = require_arg args, 'name'
139
+ value = require_arg args, 'value'
140
+ api.resource(id).annotations[name] = value
141
+ puts "Set annotation '#{name}' to '#{value}' for resource '#{id}'"
142
+ end
143
+ end
144
+
145
+ desc "Show an annotation for a resource"
146
+ arg_name "resource-id name"
147
+ command :annotation do |c|
148
+ c.action do |global_options, options, args|
149
+ id = full_resource_id require_arg args, 'resource-id'
150
+ name = require_arg args, 'name'
151
+ value = api.resource(id).annotations[name]
152
+ puts value unless value.nil?
153
+ end
154
+ end
155
+
156
+ desc "Print annotations as JSON"
157
+ arg_name 'resource-id'
158
+ command :annotations do |c|
159
+ c.action do |go, o, args|
160
+ id = full_resource_id require_arg args, 'resource-id'
161
+ annots = api.resource(id).annotations.to_h
162
+ puts annots.to_json
163
+ end
164
+ end
165
+
166
+ desc "List all resources"
167
+ command :list do |c|
168
+ c.desc "Role to act as. By default, the current logged-in role is used."
169
+ c.flag [:role]
170
+
171
+ c.desc "Filter by kind"
172
+ c.flag [:k, :kind]
173
+
174
+ c.desc "Full-text search on resource id and annotation values"
175
+ c.flag [:s, :search]
176
+
177
+ c.desc "Maximum number of records to return"
178
+ c.flag [:l, :limit]
179
+
180
+ c.desc "Offset to start from"
181
+ c.flag [:o, :offset]
182
+
183
+ c.desc "Show only ids"
184
+ c.switch [:i, :ids]
185
+
186
+ c.desc "Show annotations in 'raw' format"
187
+ c.switch [:r, :"raw-annotations"]
188
+
189
+ c.action do |global_options, options, args|
190
+ opts = options.slice(:search, :limit, :options, :kind)
191
+ opts[:acting_as] = options[:role] if options[:role]
192
+ resources = api.resources(opts)
193
+ if options[:ids]
194
+ puts resources.map(&:resourceid)
195
+ else
196
+ resources = resources.map &:attributes
197
+ unless options[:'raw-annotations']
198
+ resources = resources.map do |r|
199
+ r['annotations'] = (r['annotations'] || []).inject({}) do |hash, annot|
200
+ hash[annot['name']] = annot['value']
201
+ hash
202
+ end
203
+ r
204
+ end
205
+ end
206
+ puts JSON.pretty_generate resources
207
+ end
208
+ end
209
+ end
132
210
  end
@@ -19,9 +19,9 @@
19
19
  # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
20
  #
21
21
  require 'conjur/authn'
22
- require 'conjur/command'
22
+ require 'conjur/command/dsl_command'
23
23
 
24
- class Conjur::Command::Authn < Conjur::Command
24
+ class Conjur::Command::Script < Conjur::DSLCommand
25
25
  self.prefix = :script
26
26
 
27
27
  desc "Run a Conjur DSL script"
@@ -34,31 +34,7 @@ class Conjur::Command::Authn < Conjur::Command
34
34
  c.flag [:c, :context]
35
35
 
36
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
- File.chmod(0600, options[:context])
59
- end
60
-
61
- puts JSON.pretty_generate(result)
37
+ run_script args, options
62
38
  end
63
39
  end
64
40
  end
@@ -20,6 +20,7 @@
20
20
  #
21
21
  require 'active_support/core_ext/hash/deep_merge'
22
22
  require 'active_support/core_ext/hash/indifferent_access'
23
+
23
24
  module Conjur
24
25
  class Config
25
26
  @@attributes = {}
@@ -62,7 +63,6 @@ module Conjur
62
63
  end
63
64
  if Config[:cert_file]
64
65
  OpenSSL::SSL::SSLContext::DEFAULT_CERT_STORE.add_file Config[:cert_file]
65
- #OpenSSL::X509::Store.add_file Config[:cert_file]
66
66
  end
67
67
  end
68
68
 
@@ -47,10 +47,16 @@ module Conjur
47
47
  !@objects.empty? ? @objects.last : nil
48
48
  end
49
49
 
50
+ # Current scope, used as a path/delimited/prefix to a role or resource id.
50
51
  def current_scope
51
52
  !@scopes.empty? ? @scopes.join('/') : nil
52
53
  end
53
54
 
55
+ # Current scope, used for user@scope.
56
+ def current_user_scope
57
+ current_scope ? current_scope.gsub(/[^\w]/, '-') : nil
58
+ end
59
+
54
60
  def scope name = nil, &block
55
61
  if name != nil
56
62
  do_scope name, &block
@@ -73,6 +79,19 @@ module Conjur
73
79
  end
74
80
  end
75
81
 
82
+ def policy id, &block
83
+ self.role "policy", id do |role|
84
+ context["policy"] = role.identifier
85
+ self.owns do
86
+ self.resource "policy", id do
87
+ scope id do
88
+ block.call if block_given?
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
94
+
76
95
  alias model namespace
77
96
 
78
97
  def execute
@@ -82,15 +101,19 @@ module Conjur
82
101
  end
83
102
 
84
103
  def resource kind, id, options = {}, &block
85
- id = full_resource_id([kind, qualify_id(id) ].join(':'))
104
+ id = full_resource_id([kind, qualify_id(id, kind) ].join(':'))
86
105
  find_or_create :resource, id, options, &block
87
106
  end
88
107
 
89
108
  def role kind, id, options = {}, &block
90
- id = full_resource_id([ kind, qualify_id(id) ].join(':'))
109
+ id = full_resource_id([ kind, qualify_id(id, kind) ].join(':'))
91
110
  find_or_create :role, id, options, &block
92
111
  end
93
112
 
113
+ # purpose and existence of this method are unobvious for model designer
114
+ # just "variable" in DSL works fine through method_missing
115
+ # is this method OBSOLETED ?
116
+ # https://basecamp.com/1949725/projects/4268938-api-version-4-x/todos/84972543-low-variable
94
117
  def create_variable id = nil, options = {}, &block
95
118
  options[:id] = id if id
96
119
  mime_type = options.delete(:mime_type) || 'text/plain'
@@ -110,18 +133,23 @@ module Conjur
110
133
 
111
134
  protected
112
135
 
113
- def qualify_id id
136
+ def qualify_id id, kind
114
137
  if id[0] == "/"
115
138
  id[1..-1]
116
139
  else
117
- [ current_scope, id ].compact.join('/')
140
+ case kind.to_sym
141
+ when :user
142
+ [ id, current_user_scope ].compact.join('@')
143
+ else
144
+ [ current_scope, id ].compact.join('/')
145
+ end
118
146
  end
119
147
  end
120
148
 
121
149
  def method_missing(sym, *args, &block)
122
150
  if create_compatible_args?(args) && api.respond_to?(sym)
123
151
  id = args[0]
124
- id = qualify_id(id) unless sym == :user
152
+ id = qualify_id(id, sym)
125
153
  find_or_create sym, id, args[1] || {}, &block
126
154
  elsif current_object && current_object.respond_to?(sym)
127
155
  current_object.send(sym, *args, &block)
@@ -141,11 +169,20 @@ module Conjur
141
169
  def find_or_create(type, id, options, &block)
142
170
  find_method = type.to_sym
143
171
  create_method = "create_#{type}".to_sym
172
+
173
+ # TODO: find a way to pass annotations as part of top-level options hash
174
+ # https://basecamp.com/1949725/projects/4268938-api-version-4-x/todos/84965324-low-dsl-design
175
+ annotations = options.delete(:annotations)
176
+
144
177
  unless (obj = api.send(find_method, id)) && obj.exists?
145
178
  options = expand_options(options)
146
179
  obj = if create_method == :create_variable
180
+ #NOTE: it duplicates logic of "create_variable" method above
181
+ # https://basecamp.com/1949725/projects/4268938-api-version-4-x/todos/84972543-low-variable
147
182
  options[:id] = id
148
- api.send(create_method, options.delete(:mime_type), options.delete(:kind), options)
183
+ mime_type = options.delete(:mime_type) || annotations[:mime_type] || 'text/plain'
184
+ kind = options.delete(:kind) || annotations[:kind] || 'secret'
185
+ api.send(create_method, mime_type, kind, options)
149
186
  elsif [ 2, -2 ].member?(api.method(create_method).arity)
150
187
  api.send(create_method, id, options)
151
188
  else
@@ -153,6 +190,12 @@ module Conjur
153
190
  api.send(create_method, options)
154
191
  end
155
192
  end
193
+ if annotations.kind_of? Hash
194
+ # TODO: fix API to make 'annotations' available directly on objects
195
+ # https://basecamp.com/1949725/projects/4268938-api-version-4-x/todos/84970444-high-support
196
+ obj_as_resource = obj.resource
197
+ annotations.each { |k,v| obj_as_resource.annotations[k]=v }
198
+ end
156
199
  do_object obj, &block
157
200
  end
158
201
 
@@ -202,4 +245,4 @@ module Conjur
202
245
  end
203
246
  end
204
247
  end
205
- end
248
+ end
@@ -19,5 +19,6 @@
19
19
  # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
20
  #
21
21
  module Conjur
22
- VERSION = "4.6.1"
22
+ VERSION = "4.7.0"
23
+ ::Version=VERSION
23
24
  end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+ require 'conjur/dsl/runner'
3
+
4
+ describe Conjur::Command::Policy do
5
+ context logged_in: true do
6
+ let(:role) do
7
+ double("role", exists?: true, api_key: "the-api-key", roleid: "the-role")
8
+ end
9
+ let(:resource) do
10
+ double("resource", exists?: true).as_null_object
11
+ end
12
+ let(:name) { nil }
13
+ before {
14
+ File.stub(:read).with("policy-body").and_return "{}"
15
+ Conjur::DSL::Runner.any_instance.stub(:api).and_return api
16
+ }
17
+ before {
18
+ api.stub(:role).with("the-account:policy:#{collection}/the-policy-1.0.0").and_return role
19
+ api.stub(:resource).with("the-account:policy:#{collection}/the-policy-1.0.0").and_return resource
20
+ if name
21
+ resource.should_receive(:[]).with(:name, name)
22
+ end
23
+ }
24
+
25
+ describe_command 'policy:load --collection the-collection policy-body' do
26
+ let(:collection) { "the-collection" }
27
+ it "creates the policy" do
28
+ invoke.should == 0
29
+ end
30
+ end
31
+ context "default collection" do
32
+ let(:collection) { "alice@localhost" }
33
+ before {
34
+ stub_const("ENV", "USER" => "alice", "HOSTNAME" => "localhost")
35
+ }
36
+ describe_command 'policy:load policy-body' do
37
+ it "creates the policy with default collection" do
38
+ invoke.should == 0
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
data/tamr.rb ADDED
@@ -0,0 +1,15 @@
1
+ policy "tamr-1.0.0" do
2
+ group "admin" do
3
+ owns do
4
+ ops, developers, build = [
5
+ group("ops"),
6
+ group("developers"),
7
+ group("build")
8
+ ]
9
+
10
+ layer "sandbox" do
11
+ add_member "admin_host", developers
12
+ end
13
+ end
14
+ end
15
+ end
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.6.1
4
+ version: 4.7.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: 2014-03-03 00:00:00.000000000 Z
13
+ date: 2014-03-14 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: conjur-api
@@ -218,6 +218,7 @@ files:
218
218
  - .gitignore
219
219
  - .kateproject
220
220
  - .project
221
+ - .tamr.rb.swp
221
222
  - Gemfile
222
223
  - LICENSE
223
224
  - README.md
@@ -244,11 +245,13 @@ files:
244
245
  - lib/conjur/command/assets.rb
245
246
  - lib/conjur/command/audit.rb
246
247
  - lib/conjur/command/authn.rb
248
+ - lib/conjur/command/dsl_command.rb
247
249
  - lib/conjur/command/field.rb
248
250
  - lib/conjur/command/groups.rb
249
251
  - lib/conjur/command/hosts.rb
250
252
  - lib/conjur/command/ids.rb
251
253
  - lib/conjur/command/init.rb
254
+ - lib/conjur/command/policy.rb
252
255
  - lib/conjur/command/resources.rb
253
256
  - lib/conjur/command/roles.rb
254
257
  - lib/conjur/command/rspec/describe_command.rb
@@ -271,6 +274,7 @@ files:
271
274
  - spec/command/groups_spec.rb
272
275
  - spec/command/hosts_spec.rb
273
276
  - spec/command/init_spec.rb
277
+ - spec/command/policy_spec.rb
274
278
  - spec/command/resources_spec.rb
275
279
  - spec/command/roles_spec.rb
276
280
  - spec/command/users_spec.rb
@@ -280,6 +284,7 @@ files:
280
284
  - spec/conjurrc
281
285
  - spec/dsl/runner_spec.rb
282
286
  - spec/spec_helper.rb
287
+ - tamr.rb
283
288
  - update_ci.sh
284
289
  homepage: https://github.com/conjurinc/cli-ruby
285
290
  licenses:
@@ -294,12 +299,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
294
299
  - - ! '>='
295
300
  - !ruby/object:Gem::Version
296
301
  version: '0'
302
+ segments:
303
+ - 0
304
+ hash: -1938562320841533221
297
305
  required_rubygems_version: !ruby/object:Gem::Requirement
298
306
  none: false
299
307
  requirements:
300
308
  - - ! '>='
301
309
  - !ruby/object:Gem::Version
302
310
  version: '0'
311
+ segments:
312
+ - 0
313
+ hash: -1938562320841533221
303
314
  requirements: []
304
315
  rubyforge_project:
305
316
  rubygems_version: 1.8.25
@@ -326,6 +337,7 @@ test_files:
326
337
  - spec/command/groups_spec.rb
327
338
  - spec/command/hosts_spec.rb
328
339
  - spec/command/init_spec.rb
340
+ - spec/command/policy_spec.rb
329
341
  - spec/command/resources_spec.rb
330
342
  - spec/command/roles_spec.rb
331
343
  - spec/command/users_spec.rb