conjur-cli 5.6.6 → 6.0.0.rc1

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.
Files changed (203) hide show
  1. checksums.yaml +5 -5
  2. data/.dockerignore +1 -1
  3. data/.gitignore +2 -0
  4. data/.rubocop.yml +1 -1
  5. data/APPLIANCE_VERSION +1 -1
  6. data/CHANGELOG.md +3 -42
  7. data/Gemfile +4 -7
  8. data/Humanfile.md +31 -0
  9. data/Jenkinsfile +34 -63
  10. data/README.md +41 -55
  11. data/Rakefile +5 -1
  12. data/bin/conjur +0 -2
  13. data/build-deb.sh +1 -3
  14. data/ci/cli-test.sh +6 -0
  15. data/ci/package.sh +3 -1
  16. data/ci/publish.sh +2 -2
  17. data/ci/secrets/publish.yml +2 -2
  18. data/ci/wait_for_server.sh +10 -0
  19. data/conjur-cli.gemspec +7 -7
  20. data/dev/docker-compose.yml +24 -0
  21. data/dev/start.sh +15 -0
  22. data/dev/stop.sh +5 -0
  23. data/docker-compose.yml +30 -0
  24. data/features/authentication/authenticate.feature +34 -0
  25. data/features/authentication/login.feature +13 -0
  26. data/features/authentication/logout.feature +15 -0
  27. data/{acceptance-features → features}/authentication/whoami.feature +0 -0
  28. data/features/authorization/resource/annotate.feature +22 -0
  29. data/features/authorization/resource/check.feature +47 -0
  30. data/{acceptance-features → features}/authorization/resource/exists.feature +18 -6
  31. data/features/authorization/resource/permitted_roles.feature +35 -0
  32. data/features/authorization/resource/show.feature +34 -0
  33. data/features/authorization/role/exists.feature +28 -0
  34. data/features/authorization/role/members.feature +45 -0
  35. data/features/authorization/role/memberships.feature +43 -0
  36. data/features/conjurenv/check.feature +34 -0
  37. data/features/conjurenv/run.feature +15 -0
  38. data/{acceptance-features → features}/conjurenv/template.feature +8 -3
  39. data/{acceptance-features → features}/directory/user/update_password.feature +8 -2
  40. data/{acceptance-features → features}/directory/variable/value.feature +9 -5
  41. data/{acceptance-features → features}/directory/variable/values-add.feature +8 -3
  42. data/features/hostfactory/tokens.feature +22 -0
  43. data/features/pubkeys/show.feature +18 -0
  44. data/features/step_definitions/authn_steps.rb +22 -0
  45. data/features/step_definitions/cli_steps.rb +28 -0
  46. data/features/step_definitions/file_steps.rb +12 -0
  47. data/features/step_definitions/flow_control_steps.rb +7 -0
  48. data/features/step_definitions/graph_steps.rb +4 -3
  49. data/{acceptance-features → features}/step_definitions/http_steps.rb +0 -0
  50. data/features/step_definitions/overrides.rb +9 -0
  51. data/features/step_definitions/policy_steps.rb +11 -0
  52. data/{acceptance-features → features}/step_definitions/trusted_proxy_steps.rb +0 -0
  53. data/features/support/blank.yml +1 -0
  54. data/features/support/env.rb +21 -7
  55. data/features/support/hooks.rb +31 -116
  56. data/features/support/world.rb +16 -76
  57. data/jenkins.sh +33 -0
  58. data/lib/conjur/authenticator.rb +83 -0
  59. data/lib/conjur/authn.rb +5 -20
  60. data/lib/conjur/cli.rb +13 -6
  61. data/lib/conjur/command.rb +30 -350
  62. data/lib/conjur/command/authn.rb +23 -15
  63. data/lib/conjur/command/host_factories.rb +2 -74
  64. data/lib/conjur/command/hosts.rb +6 -113
  65. data/lib/conjur/command/init.rb +20 -35
  66. data/lib/conjur/command/{secrets.rb → policies.rb} +33 -22
  67. data/lib/conjur/command/pubkeys.rb +3 -63
  68. data/lib/conjur/command/resources.rb +45 -162
  69. data/lib/conjur/command/roles.rb +11 -181
  70. data/lib/conjur/command/rspec/helpers.rb +0 -1
  71. data/lib/conjur/command/rspec/mock_services.rb +4 -4
  72. data/lib/conjur/command/users.rb +2 -159
  73. data/lib/conjur/command/variables.rb +5 -218
  74. data/lib/conjur/complete.rb +2 -2
  75. data/lib/conjur/config.rb +1 -11
  76. data/lib/conjur/conjurenv.rb +12 -9
  77. data/lib/conjur/identifier_manipulation.rb +3 -5
  78. data/lib/conjur/version.rb +2 -2
  79. data/{publish-rubygem.sh → publish.sh} +0 -4
  80. data/spec/authn_spec.rb +4 -0
  81. data/spec/command/hosts_spec.rb +2 -69
  82. data/spec/command/init_spec.rb +16 -11
  83. data/spec/command/pubkeys_spec.rb +1 -46
  84. data/spec/command/resources_spec.rb +21 -170
  85. data/spec/command/roles_spec.rb +5 -181
  86. data/spec/command/users_spec.rb +3 -79
  87. data/spec/command_spec.rb +1 -20
  88. data/spec/complete_spec.rb +1 -23
  89. data/spec/config_spec.rb +1 -1
  90. data/spec/spec_helper.rb +4 -5
  91. data/test.sh +29 -25
  92. metadata +92 -212
  93. data/.githooks/pre_commit/run_specs.rb +0 -23
  94. data/Dockerfile +0 -15
  95. data/Dockerfile.fpm +0 -18
  96. data/Dockerfile.publish +0 -12
  97. data/Dockerfile.standalone +0 -33
  98. data/Dockerfile.validate-packaging +0 -9
  99. data/VERSION +0 -1
  100. data/acceptance-features/audit/audit_event_send.feature +0 -107
  101. data/acceptance-features/audit/fetch.feature +0 -16
  102. data/acceptance-features/audit/send.feature +0 -51
  103. data/acceptance-features/authentication/authenticate.feature +0 -10
  104. data/acceptance-features/authentication/login.feature +0 -12
  105. data/acceptance-features/authentication/logout.feature +0 -13
  106. data/acceptance-features/authorization/resource/annotate.feature +0 -35
  107. data/acceptance-features/authorization/resource/check.feature +0 -24
  108. data/acceptance-features/authorization/resource/create.feature +0 -21
  109. data/acceptance-features/authorization/resource/deny.feature +0 -12
  110. data/acceptance-features/authorization/resource/give.feature +0 -24
  111. data/acceptance-features/authorization/resource/permit.feature +0 -20
  112. data/acceptance-features/authorization/resource/permitted_roles.feature +0 -16
  113. data/acceptance-features/authorization/resource/show.feature +0 -28
  114. data/acceptance-features/authorization/role/create.feature +0 -13
  115. data/acceptance-features/authorization/role/exists.feature +0 -19
  116. data/acceptance-features/authorization/role/grant_to.feature +0 -21
  117. data/acceptance-features/authorization/role/graph.feature +0 -57
  118. data/acceptance-features/authorization/role/members.feature +0 -23
  119. data/acceptance-features/authorization/role/memberships.feature +0 -27
  120. data/acceptance-features/bootstrap.feature +0 -13
  121. data/acceptance-features/conjurenv/check.feature +0 -21
  122. data/acceptance-features/conjurenv/run.feature +0 -10
  123. data/acceptance-features/directory/group/create.feature +0 -20
  124. data/acceptance-features/directory/group/retire.feature +0 -54
  125. data/acceptance-features/directory/host/create.feature +0 -23
  126. data/acceptance-features/directory/host/retire.feature +0 -6
  127. data/acceptance-features/directory/hostfactory/create.feature +0 -28
  128. data/acceptance-features/directory/hostfactory/tokens.feature +0 -16
  129. data/acceptance-features/directory/layer/create.feature +0 -10
  130. data/acceptance-features/directory/layer/hosts-add.feature +0 -9
  131. data/acceptance-features/directory/layer/hosts-remove.feature +0 -10
  132. data/acceptance-features/directory/layer/retire.feature +0 -43
  133. data/acceptance-features/directory/user/create.feature +0 -23
  134. data/acceptance-features/directory/user/retire.feature +0 -6
  135. data/acceptance-features/directory/variable/create.feature +0 -14
  136. data/acceptance-features/directory/variable/retire.feature +0 -17
  137. data/acceptance-features/dsl/policy_owner.feature +0 -45
  138. data/acceptance-features/dsl/resource_owner.feature +0 -17
  139. data/acceptance-features/dsl/retire.feature +0 -15
  140. data/acceptance-features/global-privilege/elevate.feature +0 -20
  141. data/acceptance-features/global-privilege/reveal.privilege +0 -20
  142. data/acceptance-features/pubkeys/add.feature +0 -22
  143. data/acceptance-features/pubkeys/delete.feature +0 -9
  144. data/acceptance-features/pubkeys/names.feature +0 -26
  145. data/acceptance-features/pubkeys/show.feature +0 -27
  146. data/acceptance-features/step_definitions/cli_steps.rb +0 -57
  147. data/acceptance-features/step_definitions/graph_steps.rb +0 -22
  148. data/acceptance-features/step_definitions/user_steps.rb +0 -51
  149. data/acceptance-features/support/env.rb +0 -23
  150. data/acceptance-features/support/hooks.rb +0 -178
  151. data/acceptance-features/support/world.rb +0 -176
  152. data/acceptance-features/trusted_proxies.feature +0 -82
  153. data/bin/conjurize +0 -26
  154. data/bin/jsonfield +0 -70
  155. data/build-standalone +0 -6
  156. data/deprecations.sh +0 -38
  157. data/features/conjurize.feature +0 -134
  158. data/features/dsl_context.feature +0 -36
  159. data/features/dsl_host_create.feature +0 -11
  160. data/features/dsl_ownership.feature +0 -30
  161. data/features/dsl_permission.feature +0 -45
  162. data/features/dsl_resource_create.feature +0 -23
  163. data/features/dsl_role_create.feature +0 -11
  164. data/features/dsl_user_create.feature +0 -23
  165. data/features/jsonfield.feature +0 -49
  166. data/features/role_graph.feature +0 -58
  167. data/features/step_definitions/conjurize_steps.rb +0 -5
  168. data/features/step_definitions/dsl_steps.rb +0 -52
  169. data/features/support/conjur.conf +0 -6
  170. data/lib/conjur/command/assets.rb +0 -121
  171. data/lib/conjur/command/audit.rb +0 -155
  172. data/lib/conjur/command/bootstrap.rb +0 -129
  173. data/lib/conjur/command/dsl_command.rb +0 -75
  174. data/lib/conjur/command/elevate.rb +0 -76
  175. data/lib/conjur/command/field.rb +0 -45
  176. data/lib/conjur/command/groups.rb +0 -208
  177. data/lib/conjur/command/ids.rb +0 -34
  178. data/lib/conjur/command/layers.rb +0 -211
  179. data/lib/conjur/command/ldapsync.rb +0 -118
  180. data/lib/conjur/command/rspec/audit_helpers.rb +0 -68
  181. data/lib/conjur/command/rubydsl.rb +0 -93
  182. data/lib/conjur/command/script.rb +0 -48
  183. data/lib/conjur/command/server.rb +0 -67
  184. data/lib/conjur/conjurize.rb +0 -71
  185. data/lib/conjur/conjurize/script.rb +0 -150
  186. data/lib/conjur/dsl/runner.rb +0 -273
  187. data/publish-deb.sh +0 -6
  188. data/push-image +0 -29
  189. data/spec/command/assets_spec.rb +0 -115
  190. data/spec/command/audit_spec.rb +0 -376
  191. data/spec/command/elevate_spec.rb +0 -28
  192. data/spec/command/env_spec.rb +0 -168
  193. data/spec/command/groups_spec.rb +0 -77
  194. data/spec/command/host_factories_spec.rb +0 -38
  195. data/spec/command/layers_spec.rb +0 -35
  196. data/spec/command/ldapsync_spec.rb +0 -28
  197. data/spec/command/rubydsl_spec.rb +0 -63
  198. data/spec/command/variable_expiration_spec.rb +0 -164
  199. data/spec/command/variables_spec.rb +0 -192
  200. data/spec/conjurize/script_spec.rb +0 -62
  201. data/spec/conjurize_spec.rb +0 -70
  202. data/spec/dsl/runner_spec.rb +0 -93
  203. data/spec/env_spec.rb +0 -214
@@ -1,23 +0,0 @@
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 "bob"
20
- end
21
- """
22
- Then the model should contain "user" "bob@foobar"
23
-
@@ -1,49 +0,0 @@
1
- Feature: Extracting JSON fields
2
-
3
- In order to use conjur output in shell scripts
4
- As a Conjur user
5
- I want to extract fields from JSON data
6
-
7
- Scenario: An array element
8
- When I successfully run `jsonfield 2 '[1, 2, 3]'`
9
- Then the output should contain "3"
10
-
11
- Scenario: An out of bounds array element
12
- When I run `jsonfield 3 '[1, 2, 3]'`
13
- Then the output should contain "No field 3"
14
- And the exit status should be 2
15
-
16
- Scenario: A hash element
17
- When I successfully run `jsonfield a '{"a": 4}'`
18
- Then the output should contain "4"
19
-
20
- Scenario: A non-existent hash element
21
- When I run `jsonfield b '{"a": 4}'`
22
- Then the output should contain "No field b"
23
- And the exit status should be 2
24
-
25
- Scenario: Nested elements
26
- When I successfully run `jsonfield 0.a.1.b '[{"a": [42, {"b": "foo", "d": null}, 33], "bar": true}]'`
27
- Then the output should contain "foo"
28
-
29
- Scenario: Standard input
30
- Given a file named "test.json" with:
31
- """
32
- {
33
- "a": [
34
- 42,
35
- {
36
- "b": "foo",
37
- "d": null
38
- },
39
- 33
40
- ],
41
- "bar": true
42
- }
43
- """
44
- When I run `cat test.json | jsonfield 0.a.1.b`
45
- Then the output should contain "foo"
46
-
47
- Scenario: An element with hyphen in key
48
- When I successfully run `jsonfield variables.db-password '{"variables": {"db-password": "foo"}}'`
49
- Then the output should contain "foo"
@@ -1,58 +0,0 @@
1
- @real-api
2
- Feature: Retrieving role graphs
3
- As a Conjur user
4
- In order to understand the role hierarchy
5
- I want to retrieve role graphs and present them in a useful format
6
-
7
- Background:
8
- Given a graph with edges
9
- | Tywin | Jamie |
10
- | Tywin | Cersei |
11
- | Cersei | Joffrey |
12
- | Jamie | Joffrey |
13
- | Aerys | Tyrion |
14
- | Joanna | Tyrion |
15
-
16
- Scenario: Showing the graph as JSON
17
- When I successfully run with role expansion "conjur role graph --as-role Joffrey Joffrey"
18
- Then the graph JSON should be:
19
- """
20
- {
21
- "graph": [
22
- { "parent": "Tywin", "child": "Jamie" },
23
- { "parent": "Tywin", "child": "Cersei"},
24
- { "parent": "Cersei", "child": "Joffrey"},
25
- { "parent": "Jamie", "child": "Joffrey" }
26
- ]
27
- }
28
- """
29
-
30
- Scenario: Short JSON output
31
- When I successfully run with role expansion "conjur role graph --short --as-role Joffrey Joffrey"
32
- Then the graph JSON should be:
33
- """
34
- [
35
- [ "Tywin", "Jamie" ],
36
- [ "Tywin", "Cersei" ],
37
- [ "Jamie", "Joffrey" ],
38
- [ "Cersei", "Joffrey"]
39
- ]
40
- """
41
-
42
- Scenario: I can restrict the output to show only ancestors or descendants
43
- When I successfully run with role expansion "conjur role graph --short --no-ancestors --as-role Cersei Cersei"
44
- Then the graph JSON should be:
45
- """
46
- [
47
- [ "Cersei", "Joffrey" ]
48
- ]
49
- """
50
- When I successfully run with role expansion "conjur role graph --short --no-descendants --as-role Cersei Cersei Jamie"
51
- Then the graph JSON should be:
52
- """
53
- [
54
- [ "Tywin", "Cersei" ],
55
- [ "Tywin", "Jamie" ]
56
- ]
57
- """
58
-
@@ -1,5 +0,0 @@
1
- When(/^I conjurize "(.*?)"$/) do |args|
2
- cmd = "conjurize -f ../../features/support/host.json -c ../../features/support/conjur.conf"
3
- step %Q(I run `#{[ cmd, args ].compact.join(' ')}`)
4
- end
5
-
@@ -1,52 +0,0 @@
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
- Then(/^the model should contain "(.*?)" \/(.*?)\/$/) do |kind, id|
16
- @mock_api.thing_like(kind, Regexp.new(id)).should_not be_nil
17
- end
18
- Then(/^the "(.*?)" "(.*?)" should be owned by "(.*?)"$/) do |kind, id, owner|
19
- step "the model should contain \"#{kind}\" \"#{id}\""
20
- if kind == 'role' || kind == 'resource'
21
- @mock_api.thing(kind, id).acting_as.should == owner
22
- else
23
- @mock_api.thing(kind, id).ownerid.should == owner
24
- end
25
- end
26
-
27
- Then(/^the "(.*?)" "(.*?)" should not have an owner$/) do |kind, id|
28
- step "the model should contain \"#{kind}\" \"#{id}\""
29
- @mock_api.thing(kind, id).ownerid.should be_nil
30
- end
31
-
32
- Then(/^"(.*?)" can "(.*?)" "(.*?)"( with grant option)?$/) do |role, privilege, resource, grant_option|
33
- resource = @mock_api.thing(:resource, resource)
34
- permission = resource.permissions.find do |p|
35
- p.privilege == privilege && p.role == role && p.grant_option == !grant_option.nil?
36
- end
37
- raise "#{role} cannot #{privilege} #{resource.id} with#{grant_option ? "" : "out"} grant_option" unless permission
38
- end
39
-
40
- Then(/^the context should contain "(.*?)"$/) do |key|
41
- @runner.context.should have_key(key.to_s)
42
- end
43
-
44
- Then(/^the context "(.*?)" should be "(.*?)"$/) do |key, value|
45
- @runner.context[key].should == value
46
- end
47
-
48
- Then(/^the context "(.*?)" should contain "(.*?)" item$/) do |key, key_count|
49
- step "the context should contain \"#{key}\""
50
- expect(@runner.context[key].length).to eq key_count.to_i
51
- end
52
-
@@ -1,6 +0,0 @@
1
- ---
2
- account: test
3
- plugins:
4
- - ui
5
- appliance_url: https://conjur/api
6
- cert_file: ../../features/support/conjur-test.pem
@@ -1,121 +0,0 @@
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
- class Conjur::Command::Assets < Conjur::Command
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!('-', '_')
36
-
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)
50
- end
51
- end
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
60
- end
61
-
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
69
- end
70
-
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
84
- end
85
- end
86
-
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]
95
-
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?
101
-
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
119
- end
120
- end
121
- end
@@ -1,155 +0,0 @@
1
- class Conjur::Command
2
- class Audit < self
3
- class << self
4
- private
5
- SHORT_FORMATS = {
6
- 'resource:check' => lambda{|e| "checked that they can #{e[:privilege]} #{e[:resource]} (#{e[:allowed]})" },
7
- 'resource:create' => lambda{|e| "created resource #{e[:resource]} owned by #{e[:owner]}" },
8
- 'resource:update' => lambda{|e| "gave #{e[:resource]} to #{e[:owner]}" },
9
- 'resource:destroy' => lambda{|e| "destroyed resource #{e[:resource]}" },
10
- 'resource:permit' => lambda{|e| "permitted #{e[:grantee]} to #{e[:privilege]} #{e[:resource]} (grant option: #{!!e[:grant_option]})" },
11
- 'resource:deny' => lambda{|e| "denied #{e[:privilege]} from #{e[:grantee]} on #{e[:resource]}" },
12
- 'resource:permitted_roles' => lambda{|e| "listed roles permitted to #{e[:privilege]} on #{e[:resource]}" },
13
- 'role:check' => lambda{|e| "checked that #{e[:role] == e[:user] ? 'they' : e[:role]} can #{e[:privilege]} #{e[:resource]} (#{e[:allowed]})" },
14
- 'role:grant' => lambda{|e| "granted role #{e[:role]} to #{e[:member]} #{e[:admin_option] ? 'with' : 'without'} admin" },
15
- 'role:revoke' => lambda{|e| "revoked role #{e[:role]} from #{e[:member]}" },
16
- 'role:create' => lambda{|e| "created role #{e[:role]}" },
17
- 'audit' => lambda{ |e|
18
- action_part = [ e[:facility], e[:action] ].compact.join(":")
19
- actor_part = e[:role] ? "by #{e[:role]}" : nil
20
- resource_part = e[:resource_id] ? "on #{e[:resource_id]}" : nil
21
- allowed_part = e.has_key?(:allowed) ? "(allowed: #{e[:allowed]})" : nil
22
- message_part = e[:audit_message] ? "; message: #{e[:audit_message]}" : ""
23
- statement = [ action_part, actor_part, resource_part, allowed_part ].compact.join(" ")
24
- "reported #{statement}"+ message_part
25
- },
26
- 'conjur:use_extra_privilege' => lambda{|e| "requested extra privilege #{e[:privilege]}"}
27
- }
28
-
29
- def ssh_sudo_message(e)
30
- s = "#{e[:system_user]}"
31
- s << " " << (e[:allowed] ? "ran" : "attempted to run")
32
- s << " '" << e[:command] << "' as " << e[:target_user]
33
- s
34
- end
35
-
36
- def short_event_format e
37
- e.symbolize_keys!
38
- s = "[#{Time.parse(e[:timestamp])}]"
39
- s << " #{e[:user]}"
40
- s << " (as #{e[:acting_as]})" if e[:acting_as] != e[:user]
41
- if e[:facility] == 'ssh' && e[:action] == 'sudo'
42
- e[:audit_message] = ssh_sudo_message(e)
43
- end
44
- formatter = SHORT_FORMATS["#{e[:kind]}:#{e[:action]}"] || SHORT_FORMATS[e[:kind]]
45
- if formatter
46
- s << " " << formatter.call(e)
47
- else
48
- s << " unknown event: #{e[:kind]}:#{e[:action]}!"
49
- end
50
- s << " (failed with #{e[:error]})" if e[:error]
51
- s
52
- end
53
-
54
- def extract_int_option(source, name, dest=nil)
55
- if val = source[name]
56
- raise "Expected an integer for #{name}, but got #{val}" unless /\d+/ =~ val
57
- val.to_i.tap{ |i| dest[name] = i if dest }
58
- end
59
- end
60
-
61
- def extract_audit_options options
62
- # Do a little song and dance to simplify testing
63
- extracted = options.slice :follow, :short
64
- [:limit, :offset].each do |name|
65
- extract_int_option(options, name, extracted)
66
- end
67
- if extracted[:follow] && extracted[:offset]
68
- exit_now! "--offset option not allowed for --follow", 1
69
- end
70
- extracted
71
- end
72
-
73
- def show_audit_events events, options
74
- @count ||= 0
75
-
76
- events = [events] unless events.kind_of?(Array)
77
- # offset and limit options seem to be broken. this is a temporary workaround (should be applied on server-side eventually)
78
- events = events.drop(options[:offset]) if options[:offset]
79
- events = events.take(options[:limit]) if options[:limit]
80
-
81
- if options[:short]
82
- events.each do |e|
83
- puts short_event_format(e)
84
-
85
- # Undocumented, but for the sake of testing.... Allow
86
- # --limit with --follow. When we hit the limit, bail out
87
- # immediately: don't raise any exceptions, don't print any
88
- # messages, just exit with status 0.
89
- @count += 1
90
- if options[:follow] && @count == options[:limit]
91
- exit_now! 0
92
- end
93
- end
94
- else
95
- events.each{|e| puts JSON.pretty_generate(e) }
96
- end
97
- end
98
-
99
- def audit_feed_command parent, kind, &block
100
- parent.command kind do |c|
101
- c.desc "Maximum number of events to fetch"
102
- c.flag [:l, :limit]
103
-
104
- c.desc "Offset of the first event to return"
105
- c.flag [:o, :offset]
106
-
107
- c.desc "Short output format"
108
- c.switch [:s, :short]
109
-
110
- c.desc "Follow events as they are generated"
111
- c.switch [:f, :follow]
112
-
113
- c.action do |global_options, options, args|
114
- options = extract_audit_options options
115
- instance_exec(args, options, &block)
116
- end
117
- end
118
- end
119
- end
120
-
121
- desc "Fetch audit events"
122
- command :audit do |audit|
123
- audit.desc "Show all audit events visible to the current user"
124
- audit_feed_command audit, :all do |args, options|
125
- api.audit(options){ |es| show_audit_events es, options }
126
- end
127
-
128
- audit.desc "Show audit events related to a role"
129
- audit.arg_name 'role'
130
- audit_feed_command audit, :role do |args, options|
131
- id = full_resource_id(require_arg(args, "role"))
132
- api.audit_role(id, options){ |es| show_audit_events es, options }
133
- end
134
-
135
- audit.desc "Show audit events related to a resource"
136
- audit.arg_name 'resource'
137
- audit_feed_command audit, :resource do |args, options|
138
- id = full_resource_id(require_arg args, "resource")
139
- api.audit_resource(id, options){|es| show_audit_events es, options}
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
-
153
- end
154
- end
155
- end