conjur-cli 5.6.6 → 6.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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,48 +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
- require 'conjur/command/dsl_command'
22
-
23
- class Conjur::Command::Script < Conjur::DSLCommand
24
- desc "Execute Ruby DSL scripts"
25
- command :script do |script|
26
- script.desc "Run a Conjur DSL script"
27
- script.arg_name "script"
28
- script.command :execute do |c|
29
- acting_as_option(c)
30
- collection_option(c)
31
- context_option(c)
32
-
33
- c.action do |_, options, args|
34
- collection = options[:collection]
35
-
36
- if collection.nil?
37
- run_script args, options
38
- else
39
- run_script args, options do |runner, &block|
40
- runner.scope collection do
41
- block.call
42
- end
43
- end
44
- end
45
- end
46
- end
47
- end
48
- end
@@ -1,67 +0,0 @@
1
- #
2
- # Copyright (C) 2016 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::Server < Conjur::Command
22
- desc 'Show Conjur client and server versions'
23
- command :version do |v|
24
- v.action do |*_|
25
- puts "Conjur client version #{Conjur::VERSION}"
26
- show_server_version
27
- end
28
- end
29
-
30
- desc 'Server information'
31
- command :server do |server|
32
- server.desc 'Show service versions'
33
- server.command :version do |c|
34
- c.action do |*_|
35
- show_server_version
36
- end
37
- end
38
-
39
- server.desc 'Show general server information'
40
- server.command :info do |c|
41
- c.action do |*_|
42
- display Conjur::API.appliance_info
43
- end
44
- end
45
-
46
- server.desc 'Show server health information'
47
- server.command :health do |c|
48
- c.desc 'Show health information for a remote host, from the perspective of this server'
49
- c.flag :h, :host
50
- c.action do |_, options, _|
51
- display Conjur::API.appliance_health(options[:host])
52
- end
53
- end
54
- end
55
-
56
- class << self
57
- def show_server_version
58
- services = Conjur::API.appliance_info['services']
59
- appliance = services.delete 'appliance'
60
- puts "Conjur appliance version: #{appliance['version']}"
61
- puts 'Conjur service versions:'
62
- services.each do |name,info|
63
- puts " #{name}: #{info['version']}"
64
- end
65
- end
66
- end
67
- end
@@ -1,71 +0,0 @@
1
- require 'methadone'
2
- require 'json'
3
- require 'open-uri'
4
- require 'conjur/version.rb'
5
- require "conjur/conjurize/script"
6
-
7
- module Conjur
8
- class Conjurize
9
- include Methadone::Main
10
- include Methadone::CLILogging
11
-
12
- description <<-DESC
13
- Generate a script to install Conjur onto a machine. "conjurize" is designed to be used
14
- in a piped execution, along with "conjur host create" and "ssh". For example:
15
-
16
- conjur host create myhost.example.com | tee host.json | conjurize --ssh | ssh myhost.example.com
17
- DESC
18
-
19
- version Conjur::VERSION
20
-
21
- main do
22
- input = if input_file = options[:f]
23
- File.read(input_file)
24
- else
25
- STDIN.read
26
- end
27
-
28
- puts generate JSON.parse input
29
- end
30
-
31
- def self.generate host
32
- config = configuration host
33
-
34
- if options[:json]
35
- JSON.dump config
36
- else
37
- Script.generate config, options
38
- end
39
- end
40
-
41
- def self.apply_client_config
42
- require "conjur/cli"
43
- if conjur_config = options[:c]
44
- Conjur::Config.load [ conjur_config ]
45
- else
46
- Conjur::Config.load
47
- end
48
- Conjur::Config.apply
49
- end
50
-
51
- def self.configuration host
52
- apply_client_config
53
-
54
- host.merge \
55
- "account" => Conjur.configuration.account,
56
- "appliance_url" => Conjur.configuration.appliance_url,
57
- "certificate" => File.read(Conjur.configuration.cert_file).strip
58
- end
59
-
60
- on("-c CONJUR_CONFIG_FILE", "Overrides defaults (CONJURRC env var, ~/.conjurrc, /etc/conjur.conf).")
61
- on("-f HOST_JSON_FILE", "Host login and API key can be read from the output emitted from 'conjur host create'. This data can be obtained from stdin, or from a file.")
62
- on("--chef-executable PATH", "If specified, the designated chef-solo executable is used, otherwise Chef is installed on the target machine.")
63
- on("--ssh", "Indicates that Conjur SSH should be installed.")
64
- on("--sudo", "Indicates that all commands should be run via 'sudo'.")
65
- on("--conjur-cookbook-url NAME", "Overrides the default Chef cookbook URL for Conjur SSH.")
66
- on("--conjur-run-list RUNLIST", "Overrides the default Chef run list for Conjur SSH.")
67
- on \
68
- "--json",
69
- "Don't generate the script, instead just dump the configuration as JSON"
70
- end
71
- end
@@ -1,150 +0,0 @@
1
- require "json"
2
- require "open-uri"
3
-
4
- class Conjur::Conjurize
5
- # generates a shell script to conjurize a host
6
- class Script
7
- COOKBOOK_RELEASES_URL =
8
- "https://api.github.com/repos/conjur-cookbooks/conjur/releases".freeze
9
-
10
- def self.tarballs_of_releases releases
11
- releases.map do |release|
12
- assets = release["assets"].select do |asset|
13
- asset["name"] =~ /conjur-v\d.\d.\d.tar.gz/
14
- end
15
-
16
- [release["name"], assets.map { |asset| asset["browser_download_url"] }]
17
- end
18
- end
19
-
20
- def self.latest_conjur_cookbook_release
21
- json = JSON.parse open(COOKBOOK_RELEASES_URL).read
22
- tarballs = tarballs_of_releases json
23
-
24
- latest = tarballs.first
25
- selected = tarballs.find { |release| !release[1].empty? }
26
-
27
- if selected != latest
28
- warn "WARNING: Latest cookbook release (#{latest.first}) does not "\
29
- "contain a valid package. Falling back to #{selected.first}."
30
- end
31
-
32
- selected[1].first
33
- end
34
-
35
- HEADER = <<-HEADER.freeze
36
- #!/bin/sh
37
- set -e
38
-
39
- # Implementation note: 'tee' is used as a sudo-friendly 'cat' to populate a file with the contents provided below.
40
- HEADER
41
-
42
- def initialize options
43
- @options = options
44
- end
45
-
46
- attr_reader :options
47
-
48
- def sudo
49
- @sudo ||= options["sudo"] ? ->(x) { "sudo -n #{x}" } : ->(x) { x }
50
- end
51
-
52
- # Generate a piece of shell to write to a file
53
- # @param path [String] absolute path to write to
54
- # @param content [String] contents to write
55
- # @option options [String, Fixnum] :mode mode to apply to the file
56
- def write_file path, content, options = {}
57
- [
58
- ((mode = options[:mode]) && set_mode(path, mode)),
59
- [sudo["tee"], path, "> /dev/null << EOF"].join(" "),
60
- content.strip,
61
- "EOF\n"
62
- ].compact.join("\n")
63
- end
64
-
65
- def set_mode path, mode
66
- mode = mode.to_s(8) if mode.respond_to? :to_int
67
- [
68
- [sudo["touch"], path].join(" "),
69
- [sudo["chmod"], mode, path].join(" ")
70
- ].join("\n")
71
- end
72
-
73
- def self.generate configuration, options
74
- new(options).generate configuration
75
- end
76
-
77
- def install_chef?
78
- run_chef? && !options[:"chef-executable"]
79
- end
80
-
81
- def run_chef?
82
- options.values_at(:ssh, :"conjur-run-list").any?
83
- end
84
-
85
- def chef_executable
86
- options[:"chef-executable"] || "chef-solo"
87
- end
88
-
89
- def conjur_cookbook_url
90
- options[:"conjur-cookbook-url"] || Script.latest_conjur_cookbook_release
91
- end
92
-
93
- def conjur_run_list
94
- options[:"conjur-run-list"] || "conjur"
95
- end
96
-
97
- def chef_script
98
- @chef_script ||= [
99
- ("curl -L https://www.opscode.com/chef/install.sh | " + sudo["bash"] \
100
- if install_chef?),
101
- (sudo["#{chef_executable} --recipe-url #{conjur_cookbook_url} " \
102
- "-o #{conjur_run_list}"] if run_chef?)
103
- ].join "\n"
104
- end
105
-
106
- def self.rc configuration
107
- [
108
- "account: #{configuration['account']}",
109
- "appliance_url: #{configuration['appliance_url']}",
110
- "cert_file: /etc/conjur-#{configuration['account']}.pem",
111
- "netrc_path: /etc/conjur.identity",
112
- "plugins: []"
113
- ].join "\n"
114
- end
115
-
116
- def self.identity configuration
117
- """
118
- machine #{configuration['appliance_url']}/authn
119
- login host/#{configuration['id']}
120
- password #{configuration['api_key']}
121
- """
122
- end
123
-
124
- def configure_conjur configuration
125
- [
126
- write_file("/etc/conjur.conf", Script.rc(configuration)),
127
- write_file(
128
- "/etc/conjur-#{configuration['account']}.pem",
129
- configuration["certificate"]
130
- ),
131
- write_file(
132
- "/etc/conjur.identity",
133
- Script.identity(configuration),
134
- mode: 0600
135
- )
136
- ].join "\n"
137
- end
138
-
139
- def generate configuration
140
- fail "No 'id' field in host JSON" unless configuration["id"]
141
- fail "No 'api_key' field in host JSON" unless configuration["api_key"]
142
-
143
- [
144
- HEADER,
145
- configure_conjur(configuration),
146
- chef_script
147
- ].join("\n")
148
- end
149
- end
150
- end
@@ -1,273 +0,0 @@
1
- require 'conjur/identifier_manipulation'
2
-
3
- module Conjur
4
- module DSL
5
- # Entry point for the Conjur DSL.
6
- #
7
- # Methods are available in two categories: name scoping and asset building.
8
- class Runner
9
- include Conjur::IdentifierManipulation
10
-
11
- attr_reader :script, :filename, :context
12
- attr_reader :policy_role, :policy_resource
13
-
14
- def initialize(script, filename = nil)
15
- @context = {
16
- "account" => Conjur.account,
17
- "api_keys" => {}
18
- }
19
-
20
- @context['env'] = Conjur.env unless Conjur.env == 'production'
21
- @context['stack'] = Conjur.stack unless Conjur.stack == 'v4'
22
- @context['appliance_url'] = Conjur.configuration.appliance_url unless Conjur.configuration.appliance_url.nil?
23
- @context['ssl_certificate'] = File.read(Conjur.configuration.cert_file) unless Conjur.configuration.cert_file.nil?
24
-
25
- @script = script
26
- @filename = filename
27
- @api = nil
28
- @scopes = Array.new
29
- @owners = Array.new
30
- @objects = Array.new
31
- end
32
-
33
- def owner=(owner)
34
- raise "Owner should only be set once" unless @owners.empty?
35
- @owners.push owner
36
- end
37
-
38
- # Provides a hash to export various application specific
39
- # asset ids (or anything else you want)
40
- def assets
41
- @context['assets'] ||= {}
42
- end
43
-
44
- def api
45
- @api ||= connect
46
- end
47
-
48
- def context=(context)
49
- @context.deep_merge! context
50
- end
51
-
52
- def api_keys
53
- @context["api_keys"]
54
- end
55
-
56
- def current_object
57
- !@objects.empty? ? @objects.last : nil
58
- end
59
-
60
- # Current scope, used as a path/delimited/prefix to a role or resource id.
61
- def current_scope
62
- !@scopes.empty? ? @scopes.join('/') : nil
63
- end
64
-
65
- # Current scope, used for user@scope.
66
- def current_user_scope
67
- current_scope ? current_scope.gsub(/[^\w]/, '-') : nil
68
- end
69
-
70
- def scope name = nil, &block
71
- if name != nil
72
- do_scope name, &block
73
- else
74
- current_scope
75
- end
76
- end
77
-
78
- def namespace ns = nil, &block
79
- if block_given?
80
- ns ||= context["namespace"]
81
- if ns.nil?
82
- require 'conjur/api/variables'
83
- ns = context["namespace"] = api.create_variable("text/plain", "namespace").id
84
- end
85
- do_scope ns, &block
86
- context
87
- else
88
- @scopes[0]
89
- end
90
- end
91
-
92
- def policy id, &block
93
- self.role "policy", id do |role|
94
- @policy_role = role
95
- context["policy"] = role.identifier
96
- self.owns do
97
- self.resource "policy", id do |resource|
98
- @policy_resource = resource
99
- scope id do
100
- block.call if block_given?
101
- end
102
- end
103
- end
104
- end
105
- end
106
-
107
- alias model namespace
108
-
109
- def execute
110
- args = [ script ]
111
- args << filename if filename
112
- instance_eval(*args)
113
- end
114
-
115
- def resource kind, id = nil, options = {}, &block
116
- id = full_resource_id([kind, qualify_id(id, kind) ].join(':'))
117
- find_or_create :resource, id, options, &block
118
- end
119
-
120
- def role kind, id = nil, options = {}, &block
121
- id = full_resource_id([ kind, qualify_id(id, kind) ].join(':'))
122
- find_or_create :role, id, options, &block
123
- end
124
-
125
- # purpose and existence of this method are unobvious for model designer
126
- # just "variable" in DSL works fine through method_missing
127
- # is this method OBSOLETED ?
128
- # https://basecamp.com/1949725/projects/4268938-api-version-4-x/todos/84972543-low-variable
129
- def create_variable id = nil, options = {}, &block
130
- options[:id] = id if id
131
- mime_type = options.delete(:mime_type) || 'text/plain'
132
- kind = options.delete(:kind) || 'secret'
133
- var = api.create_variable(mime_type, kind, options)
134
- do_object var, &block
135
- end
136
-
137
- def owns
138
- @owners.push current_object
139
- begin
140
- yield
141
- ensure
142
- @owners.pop
143
- end
144
- end
145
-
146
- protected
147
-
148
- def qualify_id id, kind
149
- if id && id[0] == "/"
150
- id[1..-1]
151
- else
152
- case kind.to_sym
153
- when :user
154
- raise "User id is required" unless id
155
- [ id, current_user_scope ].compact.join('@')
156
- else
157
- [ current_scope, id ].compact.join('/')
158
- end
159
- end
160
- end
161
-
162
- def method_missing(sym, *args, &block)
163
- if create_compatible_args?(args) && api.respond_to?(sym)
164
- id = args[0]
165
- id = qualify_id(id, sym)
166
- find_or_create sym, id, args[1] || {}, &block
167
- elsif current_object && current_object.respond_to?(sym)
168
- current_object.send(sym, *args, &block)
169
- else
170
- super
171
- end
172
- end
173
-
174
- def create_compatible_args?(args)
175
- valid_prototypes = [
176
- lambda { args.length == 1 },
177
- lambda { args.length == 2 && args[1].is_a?(Hash) }
178
- ]
179
- if current_scope
180
- # If there is a scope, it's valid to create a record without an id, because the
181
- # scope name will be used as the id.
182
- valid_prototypes << lambda { args.length == 0 }
183
- end
184
- !valid_prototypes.find{|p| p.call}.nil?
185
- end
186
-
187
- def find_or_create(type, id, options, &block)
188
- find_method = type.to_sym
189
- create_method = "create_#{type}".to_sym
190
-
191
- # TODO: find a way to pass annotations as part of top-level options hash
192
- # https://basecamp.com/1949725/projects/4268938-api-version-4-x/todos/84965324-low-dsl-design
193
- annotations = options.delete(:annotations) || {}
194
-
195
- unless (obj = api.send(find_method, id)) && obj.exists?
196
- options = expand_options(options)
197
-
198
- # create_resource and create_role expect :acting_as to
199
- # specify the "owning" role.
200
- if create_method == :create_resource || create_method == :create_role
201
- options[:acting_as] = options.delete(:ownerid) if options[:ownerid]
202
- end
203
-
204
- obj = if create_method == :create_variable
205
- #NOTE: it duplicates logic of "create_variable" method above
206
- # https://basecamp.com/1949725/projects/4268938-api-version-4-x/todos/84972543-low-variable
207
- options[:id] = id
208
- mime_type = options.delete(:mime_type) || annotations[:mime_type] || 'text/plain'
209
- kind = options.delete(:kind) || annotations[:kind] || 'secret'
210
- api.send(create_method, mime_type, kind, options)
211
- elsif [ 2, -2 ].member?(api.method(create_method).arity)
212
- api.send(create_method, id, options)
213
- else
214
- options[:id] = id
215
- api.send(create_method, options)
216
- end
217
- end
218
- if annotations.kind_of?(Hash) && !annotations.blank?
219
- # TODO: fix API to make 'annotations' available directly on objects
220
- # https://basecamp.com/1949725/projects/4268938-api-version-4-x/todos/84970444-high-support
221
- obj_as_resource = obj.resource
222
- annotations.each { |k,v| obj_as_resource.annotations[k]=v }
223
- end
224
- do_object obj, &block
225
- end
226
-
227
- def do_object obj, &block
228
- begin
229
- api_keys[obj.roleid] = obj.api_key if obj.respond_to?(:api_key) && obj.api_key
230
- rescue
231
- end
232
-
233
- @objects.push obj
234
- begin
235
- yield obj if block_given?
236
- obj
237
- ensure
238
- @objects.pop
239
- end
240
- end
241
-
242
- def do_scope name, &block
243
- return unless block_given?
244
-
245
- @scopes.push(name)
246
- begin
247
- yield
248
- ensure
249
- @scopes.pop
250
- end
251
- end
252
-
253
- def owner(options)
254
- owner = options[:owner] || @owners.last
255
- owner = owner.roleid if owner.respond_to?(:roleid)
256
- owner
257
- end
258
-
259
- def expand_options(opts)
260
- (opts || {}).tap do |options|
261
- if owner = owner(options)
262
- options[:ownerid] = owner
263
- end
264
- end
265
- end
266
-
267
- def connect
268
- require 'conjur/authn'
269
- Conjur::Authn.connect
270
- end
271
- end
272
- end
273
- end