conjur-cli 2.1.3 → 2.1.4

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/.gitignore CHANGED
@@ -16,3 +16,5 @@ spec/reports
16
16
  test/tmp
17
17
  test/version_tmp
18
18
  tmp
19
+ .kateproject.d
20
+ .idea
data/.kateproject ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "name": "Conjur CLI"
3
+ , "files": [ { "git": 1 } ]
4
+ }
5
+
data/conjur.gemspec CHANGED
@@ -5,7 +5,7 @@ Gem::Specification.new do |gem|
5
5
  gem.authors = ["Rafa\305\202 Rzepecki", "Kevin Gilpin"]
6
6
  gem.email = ["divided.mind@gmail.com", "kevin.gilpin@inscitiv.com",]
7
7
  gem.summary = %q{Conjur command line interface}
8
- gem.homepage = ""
8
+ gem.homepage = "https://github.com/inscitiv/cli-ruby"
9
9
 
10
10
  gem.files = `git ls-files`.split($\) + Dir['build_number']
11
11
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
data/lib/conjur/authn.rb CHANGED
@@ -43,8 +43,11 @@ module Conjur::Authn
43
43
 
44
44
  def ask_for_credentials(options = {})
45
45
  raise "No credentials provided or found" if options[:noask]
46
-
47
- hl = HighLine.new
46
+
47
+ # also use stderr here, because we might be prompting for a password as part
48
+ # of a command like user:create that we'd want to send to a file.
49
+ hl = HighLine.new $stdin, $stderr
50
+
48
51
  user = options[:username] || hl.ask("Enter your username to log into Conjur: ")
49
52
  pass = options[:password] || hl.ask("Please enter your password (it will not be echoed): "){ |q| q.echo = false }
50
53
  api_key = if cas_server = options[:"cas-server"]
data/lib/conjur/cli.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'gli'
2
2
  require 'conjur/config'
3
+ require 'conjur/log'
3
4
 
4
5
  module Conjur
5
6
  class CLI
@@ -9,7 +10,9 @@ module Conjur
9
10
  def load_config
10
11
  [ File.join("/etc", "conjur.conf"), ( ENV['CONJURRC'] || File.join(ENV['HOME'], ".conjurrc") ) ].each do |f|
11
12
  if File.exists?(f)
12
- $stderr.puts "Loading #{f}"
13
+ if Conjur.log
14
+ Conjur.log << "Loading #{f}\n"
15
+ end
13
16
  Conjur::Config.merge YAML.load(IO.read(f))
14
17
  end
15
18
  end
@@ -21,7 +24,7 @@ module Conjur
21
24
  ENV['CONJUR_ENV'] = Config[:env] || "production"
22
25
  ENV['CONJUR_STACK'] = Config[:stack] if Config[:stack]
23
26
  ENV['CONJUR_STACK'] ||= 'v3' if ENV['CONJUR_ENV'] == 'production'
24
- ENV['CONJUR_ACCOUNT'] = Config[:account] or raise "Missing configuration setting: account"
27
+ ENV['CONJUR_ACCOUNT'] = Config[:account] or raise "Missing configuration setting: account. Please set it in ~/.conjurrc"
25
28
 
26
29
  Conjur::Config.plugins.each do |plugin|
27
30
  require "conjur-asset-#{plugin}"
@@ -29,8 +32,10 @@ module Conjur
29
32
 
30
33
  commands_from 'conjur/command'
31
34
 
32
- $stderr.puts "Using host #{Conjur::Authn::API.host}"
33
-
35
+ if Conjur.log
36
+ Conjur.log << "Using host #{Conjur::Authn::API.host}\n"
37
+ end
38
+
34
39
  pre do |global,command,options,args|
35
40
  require 'active_support/core_ext'
36
41
  options.delete_if{|k,v| v.blank?}
@@ -10,7 +10,7 @@ class Conjur::Command::Assets < Conjur::Command
10
10
  acting_as_option(c)
11
11
 
12
12
  c.action do |global_options, options, args|
13
- kind = require_arg(args, 'kind')
13
+ kind = require_arg(args, 'kind').gsub('-', '_')
14
14
 
15
15
  m = "create_#{kind}"
16
16
  record = if api.method(m).arity == 1
@@ -31,7 +31,7 @@ class Conjur::Command::Assets < Conjur::Command
31
31
  arg_name "kind id"
32
32
  command :show do |c|
33
33
  c.action do |global_options,options,args|
34
- kind = require_arg(args, "kind")
34
+ kind = require_arg(args, "kind").gsub('-', '_')
35
35
  id = require_arg(args, "resource-id")
36
36
  display api.send(kind, id).attributes
37
37
  end
@@ -41,7 +41,7 @@ class Conjur::Command::Assets < Conjur::Command
41
41
  arg_name "kind id"
42
42
  command :exists do |c|
43
43
  c.action do |global_options,options,args|
44
- kind = require_arg(args, "kind")
44
+ kind = require_arg(args, "kind").gsub('-', '_')
45
45
  id = require_arg(args, "id")
46
46
  puts api.send(kind, id).exists?
47
47
  end
@@ -51,7 +51,7 @@ class Conjur::Command::Assets < Conjur::Command
51
51
  arg_name "kind"
52
52
  command :list do |c|
53
53
  c.action do |global_options,options,args|
54
- kind = require_arg(args, "kind")
54
+ kind = require_arg(args, "kind").gsub('-', '_')
55
55
  api.send(kind.pluralize).each do |e|
56
56
  display(e, options)
57
57
  end
@@ -35,4 +35,15 @@ DESC
35
35
  Conjur::Authn.delete_credentials
36
36
  end
37
37
  end
38
+
39
+ desc "Prints out the current logged in username"
40
+ command :whoami do |c|
41
+ c.action do
42
+ if creds = Conjur::Authn.read_credentials
43
+ puts creds[0]
44
+ else
45
+ exit_now! 'Not logged in.', -1
46
+ end
47
+ end
48
+ end
38
49
  end
@@ -0,0 +1,25 @@
1
+ require 'conjur/command'
2
+
3
+ class Conjur::Command::Field < Conjur::Command
4
+ self.prefix = :field
5
+
6
+ desc "Selects a field from structured input"
7
+ arg_name "pattern (value | STDIN)"
8
+ command :select do |c|
9
+ c.action do |global_options,options,args|
10
+ pattern = require_arg(args, 'pattern')
11
+ value = args.shift || STDIN.read
12
+
13
+ require 'json'
14
+ json = JSON.parse(value)
15
+ class << json
16
+ def get_binding
17
+ record = self
18
+
19
+ binding
20
+ end
21
+ end
22
+ puts json.get_binding.eval(pattern)
23
+ end
24
+ end
25
+ end
@@ -29,6 +29,22 @@ class Conjur::Command::Groups < Conjur::Command
29
29
 
30
30
  group = api.group(group)
31
31
  api.role(group.roleid).grant_to member, !!options[:admin]
32
+
33
+ puts "Membership granted"
34
+ end
35
+ end
36
+
37
+ desc "Remove a group member"
38
+ arg_name "group member"
39
+ command :"members:remove" do |c|
40
+ c.action do |global_options,options,args|
41
+ group = require_arg(args, 'group')
42
+ member = require_arg(args, 'member')
43
+
44
+ group = api.group(group)
45
+ api.role(group.roleid).revoke_from member
46
+
47
+ puts "Membership revoked"
32
48
  end
33
49
  end
34
50
  end
@@ -17,7 +17,11 @@ class Conjur::Command::Users < Conjur::Command
17
17
 
18
18
  opts = options.slice(:ownerid)
19
19
  if options[:p]
20
- hl = HighLine.new
20
+
21
+ # use stderr to allow output redirection, e.g.
22
+ # conjur user:create -p username > user.json
23
+ hl = HighLine.new($stdin, $stderr)
24
+
21
25
  password = hl.ask("Enter the password (it will not be echoed): "){ |q| q.echo = false }
22
26
  confirmation = hl.ask("Confirm the password: "){ |q| q.echo = false }
23
27
 
@@ -48,7 +48,7 @@ class Conjur::Command::Variables < Conjur::Command
48
48
 
49
49
  c.action do |global_options,options,args|
50
50
  id = require_arg(args, 'variable')
51
- puts api.variable(id).value(options[:version])
51
+ $stdout.write api.variable(id).value(options[:version])
52
52
  end
53
53
  end
54
54
  end
@@ -1,3 +1,3 @@
1
1
  module Conjur
2
- VERSION = "2.1.3"
2
+ VERSION = "2.1.4"
3
3
  end
@@ -1,15 +1,40 @@
1
1
  require 'spec_helper'
2
2
  require 'tempfile'
3
+ require 'write_expectation'
3
4
 
4
5
  describe Conjur::Command::Authn do
5
6
  let(:netrcfile) { Tempfile.new 'authtest' }
7
+ let(:netrc) { Netrc.read(netrcfile.path) }
8
+ let(:host) { 'https://authn.example.com' }
9
+
6
10
  before do
7
- Conjur::Auth.stub netrc: Netrc.read(netrcfile.path)
11
+ Conjur::Authn.stub netrc: netrc, host: host
12
+ end
13
+
14
+ context "when not logged in" do
15
+ describe_command 'authn:whoami' do
16
+ it "errors out" do
17
+ expect{ invoke }.to write(/not logged in/i).to :stderr
18
+ end
19
+ end
8
20
  end
9
- describe_command 'auth:logout' do
10
- it "deletes credentials" do
11
- Conjur::Auth.should_receive :delete_credentials
12
- invoke
21
+
22
+ context "when logged in" do
23
+ let(:username) { 'dknuth' }
24
+ let(:api_key) { 'sekrit' }
25
+ before { netrc[host] = [username, api_key] }
26
+
27
+ describe_command 'authn:logout' do
28
+ it "deletes credentials" do
29
+ invoke
30
+ netrc[host].should_not be
31
+ end
32
+ end
33
+
34
+ describe_command 'authn:whoami' do
35
+ it "prints the current username to stdout" do
36
+ expect { invoke }.to write username
37
+ end
13
38
  end
14
39
  end
15
40
  end
data/spec/spec_helper.rb CHANGED
@@ -5,9 +5,12 @@ require "simplecov"
5
5
  SimpleCov.start
6
6
 
7
7
  module RSpec::Core::DSL
8
- def describe_command name, *a, &block
9
- describe name, *a do
10
- let(:invoke) { Conjur::Cli.run [name] }
8
+ def describe_command *argv, &block
9
+ describe *argv do
10
+ let(:invoke) do
11
+ Conjur::CLI.error_device = $stderr
12
+ Conjur::CLI.run argv
13
+ end
11
14
  instance_eval &block
12
15
  end
13
16
  end
@@ -0,0 +1,74 @@
1
+ # from https://gist.github.com/elgalu/5073871
2
+ require 'rspec'
3
+ require 'stringio'
4
+
5
+ # Custom matcher to test text written to standard output and standard error
6
+ #
7
+ # @example
8
+ # expect { $stderr.puts "Some random error" }.to write(/Some.* error/).to(:stderr)
9
+ #
10
+ # @example
11
+ # expect { $stderr.puts "Some specific error" }.to write('Some specific error').to(:stderr)
12
+ #
13
+ # @note http://greyblake.com/blog/2012/12/14/custom-expectations-with-rspec/
14
+ RSpec::Matchers.define :write do |message|
15
+ chain(:to) do |io|
16
+ @io = io
17
+ end
18
+
19
+ match do |block|
20
+ output =
21
+ case io
22
+ when :stdout then fake_stdout(&block)
23
+ when :stderr then fake_stderr(&block)
24
+ else fail("Allowed values for `to` are :stdout and :stderr, got `#{io.inspect}`")
25
+ end
26
+
27
+ case message
28
+ when String then output.include? message
29
+ when Regexp then output.match message
30
+ else fail("Allowed types for write `message` are String or Regexp, got `#{message.class}`")
31
+ end
32
+ end
33
+
34
+ description do
35
+ %Q[write #{message.inspect} to #{@io}]
36
+ end
37
+
38
+ def failure_message(to = 'to')
39
+ %Q[expected #{to} #{description} but got #{@buffer.inspect}]
40
+ end
41
+
42
+ failure_message_for_should do
43
+ failure_message 'to'
44
+ end
45
+
46
+ failure_message_for_should_not do
47
+ failure_message 'not to'
48
+ end
49
+
50
+ # Fake STDERR and return a string written to it.
51
+ def fake_stderr
52
+ original_stderr = $stderr
53
+ $stderr = StringIO.new
54
+ yield
55
+ @buffer = $stderr.string
56
+ ensure
57
+ $stderr = original_stderr
58
+ end
59
+
60
+ # Fake STDOUT and return a string written to it.
61
+ def fake_stdout
62
+ original_stdout = $stdout
63
+ $stdout = StringIO.new
64
+ yield
65
+ @buffer = $stdout.string
66
+ ensure
67
+ $stdout = original_stdout
68
+ end
69
+
70
+ # default IO is standard output
71
+ def io
72
+ @io ||= :stdout
73
+ end
74
+ 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: 2.1.3
4
+ version: 2.1.4
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-04-30 00:00:00.000000000 Z
13
+ date: 2013-05-10 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: conjur-api
@@ -134,6 +134,7 @@ extensions: []
134
134
  extra_rdoc_files: []
135
135
  files:
136
136
  - .gitignore
137
+ - .kateproject
137
138
  - .project
138
139
  - .rvmrc
139
140
  - Gemfile
@@ -148,6 +149,7 @@ files:
148
149
  - lib/conjur/command.rb
149
150
  - lib/conjur/command/assets.rb
150
151
  - lib/conjur/command/authn.rb
152
+ - lib/conjur/command/field.rb
151
153
  - lib/conjur/command/groups.rb
152
154
  - lib/conjur/command/hosts.rb
153
155
  - lib/conjur/command/permissions.rb
@@ -160,7 +162,8 @@ files:
160
162
  - lib/conjur/version.rb
161
163
  - spec/command/authn_spec.rb
162
164
  - spec/spec_helper.rb
163
- homepage: ''
165
+ - spec/write_expectation.rb
166
+ homepage: https://github.com/inscitiv/cli-ruby
164
167
  licenses: []
165
168
  post_install_message:
166
169
  rdoc_options: []
@@ -187,3 +190,4 @@ summary: Conjur command line interface
187
190
  test_files:
188
191
  - spec/command/authn_spec.rb
189
192
  - spec/spec_helper.rb
193
+ - spec/write_expectation.rb