conjur-api 5.0.0 → 5.1.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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +6 -0
- data/Dockerfile +2 -0
- data/Jenkinsfile +2 -8
- data/README.md +85 -2
- data/Rakefile +9 -3
- data/ci/configure_v4.sh +12 -0
- data/ci/configure_v5.sh +14 -0
- data/conjur-api.gemspec +1 -1
- data/docker-compose.yml +47 -12
- data/example/demo_v4.rb +49 -0
- data/example/demo_v5.rb +57 -0
- data/features/authn_local.feature +32 -0
- data/features/support/env.rb +1 -0
- data/features/variable_value.feature +6 -13
- data/features_v4/authn_local.feature +27 -0
- data/features_v4/exists.feature +29 -0
- data/features_v4/host.feature +18 -0
- data/features_v4/host_factory_token.feature +49 -0
- data/features_v4/members.feature +39 -0
- data/features_v4/permitted.feature +15 -0
- data/features_v4/permitted_roles.feature +8 -0
- data/features_v4/resource_fields.feature +47 -0
- data/features_v4/rotate_api_key.feature +13 -0
- data/features_v4/step_definitions/api_steps.rb +17 -0
- data/features_v4/step_definitions/result_steps.rb +3 -0
- data/features_v4/support/env.rb +23 -0
- data/features_v4/support/policy.yml +34 -0
- data/features_v4/support/world.rb +12 -0
- data/features_v4/variable_fields.feature +11 -0
- data/features_v4/variable_value.feature +54 -0
- data/lib/conjur-api/version.rb +1 -1
- data/lib/conjur/acts_as_resource.rb +3 -17
- data/lib/conjur/acts_as_role.rb +2 -4
- data/lib/conjur/acts_as_user.rb +1 -2
- data/lib/conjur/api.rb +1 -0
- data/lib/conjur/api/authn.rb +22 -8
- data/lib/conjur/api/host_factories.rb +2 -5
- data/lib/conjur/api/policies.rb +1 -1
- data/lib/conjur/api/pubkeys.rb +1 -9
- data/lib/conjur/api/resources.rb +1 -6
- data/lib/conjur/api/router/v4.rb +149 -0
- data/lib/conjur/api/router/v5.rb +150 -0
- data/lib/conjur/api/variables.rb +2 -8
- data/lib/conjur/base.rb +61 -18
- data/lib/conjur/base_object.rb +1 -6
- data/lib/conjur/configuration.rb +26 -0
- data/lib/conjur/group.rb +7 -1
- data/lib/conjur/has_attributes.rb +11 -3
- data/lib/conjur/host_factory.rb +1 -1
- data/lib/conjur/routing.rb +29 -0
- data/lib/conjur/user.rb +7 -1
- data/lib/conjur/variable.rb +26 -11
- data/spec/has_attributes_spec.rb +4 -2
- data/test.sh +25 -11
- metadata +33 -12
- data/ci/wait_for_server.sh +0 -10
- data/dev/docker-compose.yml +0 -23
- data/dev/empty.yml +0 -2
- data/dev/start.sh +0 -15
- data/dev/stop.sh +0 -6
data/lib/conjur/api/variables.rb
CHANGED
@@ -50,14 +50,8 @@ module Conjur
|
|
50
50
|
def variable_values variable_ids
|
51
51
|
raise ArgumentError, "Variables list must be an array" unless variable_ids.kind_of? Array
|
52
52
|
raise ArgumentError, "Variables list is empty" if variable_ids.empty?
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
response =
|
57
|
-
RestClient::Resource.
|
58
|
-
new(Conjur.configuration.core_url,credentials)['secrets'+opts].get
|
59
|
-
|
60
|
-
return JSON.parse(response.body)
|
53
|
+
|
54
|
+
JSON.parse(url_for(:secrets_values, credentials, variable_ids).get.body)
|
61
55
|
end
|
62
56
|
|
63
57
|
#@!endgroup
|
data/lib/conjur/base.rb
CHANGED
@@ -37,6 +37,8 @@ module Conjur
|
|
37
37
|
class API
|
38
38
|
include Escape
|
39
39
|
include LogSource
|
40
|
+
include Routing
|
41
|
+
extend Routing
|
40
42
|
|
41
43
|
class << self
|
42
44
|
# Create a new {Conjur::API} instance from a username and a password or api key.
|
@@ -55,7 +57,7 @@ module Conjur
|
|
55
57
|
# @param [String] remote_ip the optional IP address to be recorded in the audit record.
|
56
58
|
# @param [String] account The organization account.
|
57
59
|
# @return [Conjur::API] an api that will authenticate with the given username and api key.
|
58
|
-
def new_from_key username, api_key,
|
60
|
+
def new_from_key username, api_key, account: Conjur.configuration.account, remote_ip: nil
|
59
61
|
self.new.init_from_key username, api_key, remote_ip: remote_ip, account: account
|
60
62
|
end
|
61
63
|
|
@@ -101,6 +103,19 @@ module Conjur
|
|
101
103
|
def new_from_token_file token_file, remote_ip: nil
|
102
104
|
self.new.init_from_token_file token_file, remote_ip: remote_ip
|
103
105
|
end
|
106
|
+
|
107
|
+
# Create a new {Conjur::API} instance which authenticates using +authn-local+
|
108
|
+
# using the specified username.
|
109
|
+
#
|
110
|
+
# @param [String] username the username to use when making authenticated requests.
|
111
|
+
# @param [String] account The organization account.
|
112
|
+
# @param [String] remote_ip the optional IP address to be recorded in the audit record.
|
113
|
+
# @param [String] expiration the optional expiration time of the token (supported in V5 only).
|
114
|
+
# @param [String] cidr the optional CIDR restriction on the token (supported in V5 only).
|
115
|
+
# @return [Conjur::API] an api that will authenticate with the given username.
|
116
|
+
def new_from_authn_local username, account: Conjur.configuration.account, remote_ip: nil, expiration: nil, cidr: nil
|
117
|
+
self.new.init_from_authn_local username, account: account, remote_ip: remote_ip, expiration: expiration, cidr: cidr
|
118
|
+
end
|
104
119
|
end
|
105
120
|
|
106
121
|
#@!attribute [r] api_key
|
@@ -139,6 +154,12 @@ module Conjur
|
|
139
154
|
return @token
|
140
155
|
end
|
141
156
|
|
157
|
+
# @api private
|
158
|
+
# Force the API to obtain a new access token on the next invocation.
|
159
|
+
def force_token_refresh
|
160
|
+
@token = nil
|
161
|
+
end
|
162
|
+
|
142
163
|
# Credentials that can be merged with options to be passed to `RestClient::Resource` HTTP request methods.
|
143
164
|
# These include a username and an Authorization header containing the authentication token.
|
144
165
|
#
|
@@ -152,17 +173,7 @@ module Conjur
|
|
152
173
|
{ headers: headers, username: username }
|
153
174
|
end
|
154
175
|
|
155
|
-
module MonotonicTime
|
156
|
-
def monotonic_time
|
157
|
-
Process.clock_gettime Process::CLOCK_MONOTONIC
|
158
|
-
rescue
|
159
|
-
# fall back to normal clock if there's no CLOCK_MONOTONIC
|
160
|
-
Time.now.to_f
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
176
|
module TokenExpiration
|
165
|
-
include MonotonicTime
|
166
177
|
|
167
178
|
# The four minutes is to work around a bug in Conjur < 4.7 causing a 404 on
|
168
179
|
# long-running operations (when the token is used right around the 5 minute mark).
|
@@ -174,9 +185,20 @@ module Conjur
|
|
174
185
|
token_age > TOKEN_STALE
|
175
186
|
end
|
176
187
|
|
188
|
+
def update_token_born
|
189
|
+
self.token_born = gettime
|
190
|
+
end
|
191
|
+
|
177
192
|
def token_age
|
178
193
|
gettime - token_born
|
179
194
|
end
|
195
|
+
|
196
|
+
def gettime
|
197
|
+
Process.clock_gettime Process::CLOCK_MONOTONIC
|
198
|
+
rescue
|
199
|
+
# fall back to normal clock if there's no CLOCK_MONOTONIC
|
200
|
+
Time.now.to_f
|
201
|
+
end
|
180
202
|
end
|
181
203
|
|
182
204
|
# When the API is constructed with an API key, the token can be refreshed using
|
@@ -191,6 +213,7 @@ module Conjur
|
|
191
213
|
@account = account
|
192
214
|
@username = username
|
193
215
|
@api_key = api_key
|
216
|
+
|
194
217
|
update_token_born
|
195
218
|
end
|
196
219
|
|
@@ -199,20 +222,32 @@ module Conjur
|
|
199
222
|
update_token_born
|
200
223
|
end
|
201
224
|
end
|
225
|
+
end
|
202
226
|
|
203
|
-
|
204
|
-
|
227
|
+
# Obtains access tokens from the +authn-local+ service.
|
228
|
+
class LocalAuthenticator
|
229
|
+
include TokenExpiration
|
230
|
+
|
231
|
+
attr_reader :account, :username, :expiration, :cidr
|
232
|
+
|
233
|
+
def initialize account, username, expiration, cidr
|
234
|
+
@account = account
|
235
|
+
@username = username
|
236
|
+
@expiration = expiration
|
237
|
+
@cidr = cidr
|
238
|
+
|
239
|
+
update_token_born
|
205
240
|
end
|
206
241
|
|
207
|
-
def
|
208
|
-
|
242
|
+
def refresh_token
|
243
|
+
Conjur::API.authenticate_local(username, account: account, expiration: expiration, cidr: cidr).tap do
|
244
|
+
update_token_born
|
245
|
+
end
|
209
246
|
end
|
210
247
|
end
|
211
248
|
|
212
249
|
# When the API is constructed with a token, the token cannot be refreshed.
|
213
250
|
class UnableAuthenticator
|
214
|
-
include MonotonicTime
|
215
|
-
|
216
251
|
def refresh_token
|
217
252
|
raise "Unable to re-authenticate using an access token"
|
218
253
|
end
|
@@ -255,7 +290,7 @@ module Conjur
|
|
255
290
|
end
|
256
291
|
end
|
257
292
|
|
258
|
-
def init_from_key username, api_key,
|
293
|
+
def init_from_key username, api_key, account: Conjur.configuration.account, remote_ip: nil
|
259
294
|
@username = username
|
260
295
|
@api_key = api_key
|
261
296
|
@remote_ip = remote_ip
|
@@ -276,6 +311,14 @@ module Conjur
|
|
276
311
|
self
|
277
312
|
end
|
278
313
|
|
314
|
+
def init_from_authn_local username, account: Conjur.configuration.account, remote_ip: nil, expiration: nil, cidr: nil
|
315
|
+
@username = username
|
316
|
+
@api_key = api_key
|
317
|
+
@remote_ip = remote_ip
|
318
|
+
@authenticator = LocalAuthenticator.new(account, username, expiration, cidr)
|
319
|
+
self
|
320
|
+
end
|
321
|
+
|
279
322
|
attr_reader :authenticator
|
280
323
|
|
281
324
|
private
|
data/lib/conjur/base_object.rb
CHANGED
@@ -26,6 +26,7 @@ module Conjur
|
|
26
26
|
include QueryString
|
27
27
|
include LogSource
|
28
28
|
include BuildObject
|
29
|
+
include Routing
|
29
30
|
|
30
31
|
attr_reader :id, :credentials
|
31
32
|
|
@@ -47,11 +48,5 @@ module Conjur
|
|
47
48
|
def username
|
48
49
|
credentials[:username] or raise "No username found in credentials"
|
49
50
|
end
|
50
|
-
|
51
|
-
protected
|
52
|
-
|
53
|
-
def core_resource
|
54
|
-
RestClient::Resource.new(Conjur.configuration.core_url, credentials)
|
55
|
-
end
|
56
51
|
end
|
57
52
|
end
|
data/lib/conjur/configuration.rb
CHANGED
@@ -369,6 +369,32 @@ module Conjur
|
|
369
369
|
# @see cert_file
|
370
370
|
add_option :ssl_certificate
|
371
371
|
|
372
|
+
# @!attribute version
|
373
|
+
#
|
374
|
+
# Selects the major API version of the Conjur server. With this setting, the API
|
375
|
+
# will use the routing scheme for API version `4` or `5`.
|
376
|
+
#
|
377
|
+
# Methods which are not available in the selected version will raise NoMethodError.
|
378
|
+
add_option :version, default: 5
|
379
|
+
|
380
|
+
# @!attribute authn_local_socket
|
381
|
+
#
|
382
|
+
# File path to the Unix socket used for local authentication.
|
383
|
+
# This is only available when the API client is running on the Conjur server.
|
384
|
+
add_option :authn_local_socket, default: "/run/authn-local/.socket"
|
385
|
+
|
386
|
+
# Calls a major-version-specific function.
|
387
|
+
def version_logic v4_logic, v5_logic
|
388
|
+
case version.to_s
|
389
|
+
when "4"
|
390
|
+
v4_logic.call
|
391
|
+
when "5"
|
392
|
+
v5_logic.call
|
393
|
+
else
|
394
|
+
raise "Unspported major version #{version}"
|
395
|
+
end
|
396
|
+
end
|
397
|
+
|
372
398
|
# Add the certificate configured by the {#ssl_certificate} and {#cert_file} options to the certificate
|
373
399
|
# store used by Conjur clients.
|
374
400
|
#
|
data/lib/conjur/group.rb
CHANGED
@@ -29,7 +29,13 @@ module Conjur
|
|
29
29
|
# @return [Fixnum] the gidnumber
|
30
30
|
# @raise [RestClient::Forbidden] if you don't have permission to `show` the group.
|
31
31
|
def gidnumber
|
32
|
-
|
32
|
+
parser_for(:group_gidnumber, group_attributes)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def group_attributes
|
38
|
+
@group_attributes ||= url_for(:group_attributes, credentials, self, id)
|
33
39
|
end
|
34
40
|
end
|
35
41
|
end
|
@@ -23,6 +23,14 @@ module Conjur
|
|
23
23
|
# methods on specific asset classes (for example, {Conjur::Resource#owner}), the are available as
|
24
24
|
# a `Hash` on all types supporting attributes.
|
25
25
|
module HasAttributes
|
26
|
+
class << self
|
27
|
+
|
28
|
+
# @api private
|
29
|
+
def annotation_value annotations, name
|
30
|
+
(annotations.find{|a| a['name'] == name} || {})['value']
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
26
34
|
def as_json options={}
|
27
35
|
result = super(options)
|
28
36
|
if @attributes
|
@@ -67,7 +75,7 @@ module Conjur
|
|
67
75
|
protected
|
68
76
|
|
69
77
|
def annotation_value name
|
70
|
-
|
78
|
+
HasAttributes.annotation_value attributes['annotations'], name
|
71
79
|
end
|
72
80
|
|
73
81
|
# @api private
|
@@ -78,9 +86,9 @@ module Conjur
|
|
78
86
|
|
79
87
|
# @api private
|
80
88
|
def fetch_attributes
|
81
|
-
cache_key = Conjur.cache_key username,
|
89
|
+
cache_key = Conjur.cache_key username, url_for(:resources_resource, credentials, id).url
|
82
90
|
Conjur.cache.fetch_attributes cache_key do
|
83
|
-
JSON.parse(
|
91
|
+
JSON.parse(url_for(:resources_resource, credentials, id).get.body)
|
84
92
|
end
|
85
93
|
end
|
86
94
|
end
|
data/lib/conjur/host_factory.rb
CHANGED
@@ -47,7 +47,7 @@ module Conjur
|
|
47
47
|
options[:host_factory] = id
|
48
48
|
options[:count] = count
|
49
49
|
options[:cidr] = cidr if cidr
|
50
|
-
response = JSON.parse
|
50
|
+
response = JSON.parse url_for(:host_factory_create_tokens, credentials, id).post(options)
|
51
51
|
response.map do |data|
|
52
52
|
HostFactoryToken.new data, credentials
|
53
53
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Conjur
|
2
|
+
module Routing
|
3
|
+
def url_for method, *args
|
4
|
+
router.send method, *args
|
5
|
+
end
|
6
|
+
|
7
|
+
def parser_for method, *args
|
8
|
+
router.send "parse_#{method}", *args
|
9
|
+
end
|
10
|
+
|
11
|
+
protected
|
12
|
+
|
13
|
+
def router
|
14
|
+
require 'conjur/api/router/v4'
|
15
|
+
require 'conjur/api/router/v5'
|
16
|
+
|
17
|
+
variable_id = "@v#{Conjur.configuration.version}_router"
|
18
|
+
router = instance_variable_get variable_id
|
19
|
+
if router.nil?
|
20
|
+
router = instance_variable_set variable_id, router_for_version
|
21
|
+
end
|
22
|
+
router
|
23
|
+
end
|
24
|
+
|
25
|
+
def router_for_version
|
26
|
+
Conjur::API::Router.const_get("V#{Conjur.configuration.version}")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/conjur/user.rb
CHANGED
@@ -28,7 +28,13 @@ module Conjur
|
|
28
28
|
# @return [Fixnum] the uidnumber
|
29
29
|
# @raise [RestClient::Forbidden] if you don't have permission to `show` the user.
|
30
30
|
def uidnumber
|
31
|
-
|
31
|
+
parser_for(:user_uidnumber, user_attributes)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def user_attributes
|
37
|
+
@user_attributes ||= url_for(:user_attributes, credentials, self, id)
|
32
38
|
end
|
33
39
|
end
|
34
40
|
end
|
data/lib/conjur/variable.rb
CHANGED
@@ -95,7 +95,7 @@ module Conjur
|
|
95
95
|
# @note this is **not** the same as the `kind` part of a qualified Conjur id.
|
96
96
|
# @return [String] a string representing the kind of secret.
|
97
97
|
def kind
|
98
|
-
|
98
|
+
parser_for(:variable_kind, variable_attributes) || "secret"
|
99
99
|
end
|
100
100
|
|
101
101
|
# The MIME Type of the variable's value.
|
@@ -109,7 +109,7 @@ module Conjur
|
|
109
109
|
#
|
110
110
|
# @return [String] a MIME type, such as `'text/plain'` or `'application/octet-stream'`.
|
111
111
|
def mime_type
|
112
|
-
|
112
|
+
parser_for(:variable_mime_type, variable_attributes) || "text/plain"
|
113
113
|
end
|
114
114
|
|
115
115
|
# Add a new value to the variable.
|
@@ -130,7 +130,12 @@ module Conjur
|
|
130
130
|
logger << "Adding a value to variable #{id}"
|
131
131
|
end
|
132
132
|
invalidate do
|
133
|
-
|
133
|
+
route = url_for(:secrets_add, credentials, id)
|
134
|
+
Conjur.configuration.version_logic lambda {
|
135
|
+
route.post value: value
|
136
|
+
}, lambda {
|
137
|
+
route.post value
|
138
|
+
}
|
134
139
|
end
|
135
140
|
end
|
136
141
|
|
@@ -145,12 +150,16 @@ module Conjur
|
|
145
150
|
#
|
146
151
|
# @return [Integer] the number of versions
|
147
152
|
def version_count
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
153
|
+
Conjur.configuration.version_logic lambda {
|
154
|
+
JSON.parse(url_for(:variable, credentials, id).get)['version_count']
|
155
|
+
}, lambda {
|
156
|
+
secrets = attributes['secrets']
|
157
|
+
if secrets.empty?
|
158
|
+
0
|
159
|
+
else
|
160
|
+
secrets.last['version']
|
161
|
+
end
|
162
|
+
}
|
154
163
|
end
|
155
164
|
|
156
165
|
# Return the version of a variable.
|
@@ -187,7 +196,13 @@ module Conjur
|
|
187
196
|
# @return [String] the value of the variable
|
188
197
|
def value version = nil, options = {}
|
189
198
|
options['version'] = version if version
|
190
|
-
|
199
|
+
url_for(:secrets_value, credentials, id, options).get.body
|
200
|
+
end
|
201
|
+
|
202
|
+
private
|
203
|
+
|
204
|
+
def variable_attributes
|
205
|
+
@variable_attributes ||= url_for(:variable_attributes, credentials, self, id)
|
191
206
|
end
|
192
|
-
end
|
207
|
+
end
|
193
208
|
end
|
data/spec/has_attributes_spec.rb
CHANGED
@@ -4,6 +4,8 @@ describe Conjur::HasAttributes do
|
|
4
4
|
class ObjectWithAttributes
|
5
5
|
include Conjur::HasAttributes
|
6
6
|
|
7
|
+
def id; "the-object"; end
|
8
|
+
def credentials; {}; end
|
7
9
|
def username; 'alice'; end
|
8
10
|
def url; 'http://example.com/the-object'; end
|
9
11
|
end
|
@@ -18,8 +20,8 @@ describe Conjur::HasAttributes do
|
|
18
20
|
let(:rbac_resource_resource) { double(:rbac_resource_resource, url: object.url) }
|
19
21
|
|
20
22
|
before {
|
21
|
-
allow(object).to receive(:
|
22
|
-
allow(second_object).to receive(:
|
23
|
+
allow(object).to receive(:url_for).with(:resources_resource, {}, "the-object").and_return(rbac_resource_resource)
|
24
|
+
allow(second_object).to receive(:url_for).with(:resources_resource, {}, "the-object").and_return(rbac_resource_resource)
|
23
25
|
expect(rbac_resource_resource).to receive(:get).with(no_args).and_return(double(:response, body: attributes.to_json))
|
24
26
|
}
|
25
27
|
|
data/test.sh
CHANGED
@@ -5,36 +5,50 @@ function finish {
|
|
5
5
|
echo '---'
|
6
6
|
docker-compose down --rmi 'local' --volumes
|
7
7
|
}
|
8
|
+
|
8
9
|
trap finish EXIT
|
9
10
|
|
10
11
|
function main() {
|
11
12
|
# Generate reports folders locally
|
12
|
-
mkdir -p spec/reports features/reports
|
13
|
+
mkdir -p spec/reports features/reports features_v4/reports
|
13
14
|
|
14
15
|
startConjur
|
15
|
-
|
16
|
+
runTests_5
|
17
|
+
runTests_4
|
16
18
|
}
|
17
19
|
|
18
20
|
function startConjur() {
|
19
21
|
echo 'Starting Conjur environment'
|
20
22
|
echo '-----'
|
21
|
-
docker-compose pull
|
22
|
-
docker-compose build
|
23
|
-
docker-compose up -d
|
23
|
+
docker-compose pull
|
24
|
+
docker-compose build
|
25
|
+
docker-compose up -d pg conjur_4 conjur_5
|
26
|
+
}
|
27
|
+
|
28
|
+
function runTests_5() {
|
29
|
+
echo 'Waiting for Conjur v5 to come up, and configuring it...'
|
30
|
+
./ci/configure_v5.sh
|
31
|
+
|
32
|
+
local api_key=$(docker-compose exec -T conjur_5 rake 'role:retrieve-key[cucumber:user:admin]')
|
33
|
+
|
34
|
+
echo 'Running tests'
|
35
|
+
echo '-----'
|
36
|
+
docker-compose run --rm \
|
37
|
+
-e CONJUR_AUTHN_API_KEY="$api_key" \
|
38
|
+
tester_5 rake jenkins_init jenkins_spec jenkins_cucumber_v5
|
24
39
|
}
|
25
40
|
|
26
|
-
function
|
27
|
-
echo '
|
28
|
-
|
29
|
-
docker-compose run --rm tester ./ci/wait_for_server.sh
|
41
|
+
function runTests_4() {
|
42
|
+
echo 'Waiting for Conjur v4 to come up, and configuring it...'
|
43
|
+
./ci/configure_v4.sh
|
30
44
|
|
31
|
-
local api_key=$(docker-compose exec -T conjur rails r "
|
45
|
+
local api_key=$(docker-compose exec -T conjur_4 su conjur -c "conjur-plugin-service authn env RAILS_ENV=appliance rails r \"puts User['admin'].api_key\" 2>/dev/null")
|
32
46
|
|
33
47
|
echo 'Running tests'
|
34
48
|
echo '-----'
|
35
49
|
docker-compose run --rm \
|
36
50
|
-e CONJUR_AUTHN_API_KEY="$api_key" \
|
37
|
-
|
51
|
+
tester_4 rake jenkins_cucumber_v4
|
38
52
|
}
|
39
53
|
|
40
54
|
main
|