conjur-api 5.2.1 → 5.3.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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +10 -0
  3. data/.github/CODEOWNERS +10 -0
  4. data/.github/ISSUE_TEMPLATE/bug.md +42 -0
  5. data/.github/ISSUE_TEMPLATE/feature_request.md +27 -0
  6. data/.github/PULL_REQUEST_TEMPLATE.md +21 -0
  7. data/.gitignore +1 -0
  8. data/.gitleaks.toml +219 -0
  9. data/.overcommit.yml +16 -0
  10. data/.rubocop.yml +3 -0
  11. data/.rubocop_settings.yml +86 -0
  12. data/.rubocop_todo.yml +709 -0
  13. data/CHANGELOG.md +358 -177
  14. data/CONTRIBUTING.md +141 -0
  15. data/Gemfile +1 -1
  16. data/Jenkinsfile +27 -29
  17. data/LICENSE +202 -0
  18. data/README.md +19 -126
  19. data/SECURITY.md +42 -0
  20. data/bin/parse-changelog.sh +12 -0
  21. data/ci/codeclimate.dockerfile +6 -0
  22. data/conjur-api.gemspec +4 -1
  23. data/docker-compose.yml +2 -0
  24. data/features/authenticators.feature +33 -0
  25. data/features/host.feature +39 -9
  26. data/features/step_definitions/api_steps.rb +14 -3
  27. data/features/step_definitions/policy_steps.rb +40 -0
  28. data/features/support/env.rb +2 -0
  29. data/features/update_password.feature +2 -2
  30. data/features/user.feature +47 -6
  31. data/features_v4/support/env.rb +2 -0
  32. data/lib/conjur-api/version.rb +2 -2
  33. data/lib/conjur/acts_as_role.rb +15 -19
  34. data/lib/conjur/acts_as_user.rb +5 -1
  35. data/lib/conjur/api.rb +2 -0
  36. data/lib/conjur/api/authenticators.rb +35 -0
  37. data/lib/conjur/api/host_factories.rb +20 -19
  38. data/lib/conjur/{cast.rb → api/ldap_sync.rb} +14 -17
  39. data/lib/conjur/api/resources.rb +17 -21
  40. data/lib/conjur/api/router/v5.rb +39 -7
  41. data/lib/conjur/base.rb +19 -5
  42. data/lib/conjur/base_object.rb +31 -26
  43. data/lib/conjur/build_object.rb +13 -20
  44. data/lib/conjur/cert_utils.rb +14 -0
  45. data/lib/conjur/configuration.rb +1 -7
  46. data/lib/conjur/has_attributes.rb +6 -3
  47. data/lib/conjur/id.rb +22 -19
  48. data/lib/conjur/role_grant.rb +13 -18
  49. data/spec/api/host_factories_spec.rb +34 -0
  50. data/spec/api_spec.rb +55 -6
  51. data/spec/base_object_spec.rb +13 -0
  52. data/spec/cert_utils_spec.rb +92 -0
  53. data/spec/id_spec.rb +29 -0
  54. data/spec/ldap_sync_spec.rb +21 -0
  55. data/spec/spec_helper.rb +3 -0
  56. data/spec/uri_escape_spec.rb +14 -2
  57. data/test.sh +23 -1
  58. metadata +34 -12
  59. data/LICENSE.md +0 -195
  60. data/spec/cast_spec.rb +0 -21
@@ -44,6 +44,20 @@ module Conjur
44
44
  end
45
45
  end
46
46
  end
47
+
48
+ # Add a certificate to a given store. If the certificate has more than
49
+ # one certificate in its chain, it will be parsed and added to the store
50
+ # one by one. This is done because `OpenSSL::X509::Store.new.add_cert`
51
+ # adds only the intermediate certificate to the store.
52
+ def add_chained_cert store, chained_cert
53
+ parse_certs(chained_cert).each do |cert|
54
+ begin
55
+ store.add_cert cert
56
+ rescue OpenSSL::X509::StoreError => ex
57
+ raise unless ex.message == 'cert already in hash table'
58
+ end
59
+ end
60
+ end
47
61
  end
48
62
  end
49
63
  end
@@ -402,13 +402,7 @@ module Conjur
402
402
  # @return [Boolean] whether a certificate was added to the store.
403
403
  def apply_cert_config! store=OpenSSL::SSL::SSLContext::DEFAULT_CERT_STORE
404
404
  if ssl_certificate
405
- CertUtils.parse_certs(ssl_certificate).each do |cert|
406
- begin
407
- store.add_cert cert
408
- rescue OpenSSL::X509::StoreError => ex
409
- raise unless ex.message == 'cert already in hash table'
410
- end
411
- end
405
+ CertUtils.add_chained_cert(store, ssl_certificate)
412
406
  elsif cert_file
413
407
  ensure_cert_readable!(cert_file)
414
408
  store.add_file cert_file
@@ -71,11 +71,14 @@ module Conjur
71
71
  @attributes = nil
72
72
  end
73
73
 
74
-
74
+ def annotations
75
+ Hash[(attributes['annotations']||{}).collect {|e| [e['name'],e['value']]}]
76
+ end
77
+
75
78
  protected
76
79
 
77
80
  def annotation_value name
78
- HasAttributes.annotation_value attributes['annotations'], name
81
+ annotations[name]
79
82
  end
80
83
 
81
84
  # @api private
@@ -92,4 +95,4 @@ module Conjur
92
95
  end
93
96
  end
94
97
  end
95
- end
98
+ end
@@ -1,23 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2013-2018 CyberArk Ltd.
1
4
  #
2
- # Copyright 2013-2017 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.
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
13
8
  #
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.
9
+ # http://www.apache.org/licenses/LICENSE-2.0
20
10
  #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
21
17
  require 'conjur/escape'
22
18
 
23
19
  module Conjur
@@ -28,7 +24,7 @@ module Conjur
28
24
  attr_reader :id
29
25
 
30
26
  def initialize id
31
- @id = id
27
+ @id = Id.normalize id
32
28
  end
33
29
 
34
30
  # The organization account, obtained from the first component of the id.
@@ -56,7 +52,7 @@ module Conjur
56
52
  # Splits the id into 3 components, and then joins them with a forward-slash `/`.
57
53
  def to_url_path
58
54
  id.split(':', 3)
59
- .map(&method(:path_escape))
55
+ .map(&method(:fully_escape))
60
56
  .join('/')
61
57
  end
62
58
 
@@ -64,5 +60,12 @@ module Conjur
64
60
  def to_s
65
61
  id
66
62
  end
63
+
64
+ def self.normalize id
65
+ Array(id).join(':').tap do |id|
66
+ raise ArgumentError, "id must be fully qualified: #{id}" \
67
+ unless id =~ /.*:.*:.*/
68
+ end
69
+ end
67
70
  end
68
71
  end
@@ -1,23 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2013-2018 CyberArk Ltd.
1
4
  #
2
- # Copyright 2013-2017 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.
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
13
8
  #
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.
9
+ # http://www.apache.org/licenses/LICENSE-2.0
20
10
  #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
21
17
  module Conjur
22
18
  # Represents the membership of a role. `RoleGrant`s are returned
23
19
  # by {ActsAsRole#members} and represent members of the role on which the method was invoked.
@@ -28,7 +24,6 @@ module Conjur
28
24
  #
29
25
  class RoleGrant
30
26
  extend BuildObject::ClassMethods
31
- extend Cast
32
27
 
33
28
  # The role which was granted.
34
29
  # @return [Conjur::Role]
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'conjur/api/host_factories'
5
+
6
+ describe "Conjur::API.host_factory_create_host", api: :dummy do
7
+ it "returns a Host instance correctly on v4" do
8
+ token = "host factory token"
9
+ id = "test-host"
10
+
11
+ allow(Conjur::API).to receive(:url_for)
12
+ .with(:host_factory_create_host, token).and_return(
13
+ resource = instance_double(RestClient::Resource, "hosts")
14
+ )
15
+
16
+ allow(resource).to receive(:post).with(id: id).and_return(
17
+ instance_double(RestClient::Response, "host response", body: '
18
+ {
19
+ "id": "test-host",
20
+ "userid": "hosts",
21
+ "created_at": "2015-11-13T22:57:14Z",
22
+ "ownerid": "cucumber:group:ops",
23
+ "roleid": "cucumber:host:test-host",
24
+ "resource_identifier": "cucumber:host:test-host",
25
+ "api_key": "14x82x72syhnnd1h8jj24zj1kqd2j09sjy3tddwxc35cmy5nx33ph7"
26
+ }
27
+ ')
28
+ )
29
+
30
+ host = Conjur::API.host_factory_create_host token, id
31
+
32
+ expect(host).to be_a Conjur::Host
33
+ end
34
+ end
@@ -60,11 +60,11 @@ describe Conjur::API do
60
60
  context "after expiration" do
61
61
  it 'it reads a new token' do
62
62
  expect(Time.parse(api.token['timestamp'])).to be_within(5.seconds).of(Time.now)
63
-
63
+
64
64
  time_travel 6.minutes
65
65
  new_token = token.merge "timestamp" => Time.now.to_s
66
66
  write_token new_token
67
-
67
+
68
68
  expect(api.token).to eq(new_token)
69
69
  end
70
70
  end
@@ -85,10 +85,10 @@ describe Conjur::API do
85
85
  it 'by refreshing' do
86
86
  allow(Conjur::API).to receive(:authenticate).with(login, api_key, account: account).and_return token
87
87
  expect(Time.parse(api.token['timestamp'])).to be_within(5.seconds).of(Time.now)
88
-
88
+
89
89
  time_travel 6.minutes
90
90
  new_token = token.merge "timestamp" => Time.now.to_s
91
-
91
+
92
92
  expect(Conjur::API).to receive(:authenticate).with(login, api_key, account: account).and_return new_token
93
93
  expect(api.token).to eq(new_token)
94
94
  end
@@ -118,7 +118,7 @@ describe Conjur::API do
118
118
  subject { super().credentials }
119
119
  it { is_expected.to eq({ headers: { authorization: "Token token=\"#{Base64.strict_encode64(token.to_json)}\"" }, username: login }) }
120
120
  end
121
-
121
+
122
122
  context "with remote_ip" do
123
123
  let(:remote_ip) { "66.0.0.1" }
124
124
  describe '#credentials' do
@@ -153,7 +153,7 @@ describe Conjur::API do
153
153
  context 'basic functioning' do
154
154
  it_behaves_like 'it can clone itself'
155
155
  end
156
-
156
+
157
157
  context "forwarded for" do
158
158
  let(:forwarded_for_header) { "66.0.0.1" }
159
159
  let(:headers) { base_headers.merge(x_forwarded_for: forwarded_for_header) }
@@ -172,6 +172,55 @@ describe Conjur::API do
172
172
  end
173
173
  end
174
174
 
175
+ describe "#username" do
176
+ let(:jwt_payload) do
177
+ 'eyJzdWIiOiJ1c2VyLTlhYjBiYmZiOWJlNjA5Yzk2ZjUyN2Y1YiIsImlhdCI6MTYwMzQ5MDA4MH0='
178
+ end
179
+
180
+ let(:jwt_header) do
181
+ 'eyJhbGciOiJjb25qdXIub3JnL3Nsb3NpbG8vdjIiLCJraWQiOiI2MWZjOGRiZDM4MjA4NDll' \
182
+ 'ZDI4YTZhYTAwMzFjNjM5MjkxZjJmMDQzNDVjYTU0MWI5NzUxMGQ5NjkyM2I3NDlmIn0='
183
+ end
184
+
185
+ let(:conjur_token) do
186
+ {
187
+ 'data' => 'conjur-user-1234',
188
+ 'timestamp' => Time.now.to_s
189
+ }
190
+ end
191
+
192
+ let(:jwt_token) do
193
+ {
194
+ 'protected' => jwt_header,
195
+ 'payload' => jwt_payload,
196
+ }
197
+ end
198
+
199
+ it "can correctly extract the username from old Conjur token" do
200
+ expect(Conjur::API.new_from_token(conjur_token).username).to(
201
+ eq('conjur-user-1234')
202
+ )
203
+ end
204
+
205
+ context 'when using JWT token' do
206
+ it "can correctly extract username" do
207
+ expect(Conjur::API.new_from_token(jwt_token).username).to(
208
+ eq('user-9ab0bbfb9be609c96f527f5b')
209
+ )
210
+ end
211
+
212
+ it "returns nil when JWT token has no payload field" do
213
+ no_payload_jwt_token = { 'protected' => jwt_header }
214
+ expect(Conjur::API.new_from_token(no_payload_jwt_token).username).to be_nil
215
+ end
216
+
217
+ it "returns nil when JWT token has no 'sub' field in payload" do
218
+ no_sub_token = { 'payload' => 'eyJpYXQiOjE2MDM0OTAwODB9' }
219
+ expect(Conjur::API.new_from_token(no_sub_token).username).to be_nil
220
+ end
221
+ end
222
+ end
223
+
175
224
  describe "#current_role", logged_in: true do
176
225
  context "when logged in as user" do
177
226
  let(:login) { 'joerandom' }
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Conjur::BaseObject do
6
+
7
+ it "returns custom string for #inspect" do
8
+ id_str = 'foo:bar:baz'
9
+ base_obj = Conjur::BaseObject.new(Conjur::Id.new(id_str), { username: 'foo' })
10
+ expect(base_obj.inspect).to include("id='#{id_str}'")
11
+ expect(base_obj.inspect).to include(Conjur::BaseObject.name)
12
+ end
13
+ end
@@ -78,4 +78,96 @@ RjvSxre4Xg2qlI9Laybb4oZ4g6DI8hRbL0VdFAsveg6SXg2RxgJcXeJUFw==
78
78
  end
79
79
  end
80
80
  end
81
+
82
+ describe '.add_chained_cert' do
83
+ let(:one_certificate_chain) do
84
+ """-----BEGIN CERTIFICATE-----
85
+ MIIDPjCCAiagAwIBAgIVAKW1gdmOFrXt6xB0iQmYQ4z8Pf+kMA0GCSqGSIb3DQEB
86
+ CwUAMD0xETAPBgNVBAoTCGN1Y3VtYmVyMRIwEAYDVQQLEwlDb25qdXIgQ0ExFDAS
87
+ BgNVBAMTC2N1a2UtbWFzdGVyMB4XDTE1MTAwNzE2MzAwNloXDTI1MTAwNDE2MzAw
88
+ NlowFjEUMBIGA1UEAwwLY3VrZS1tYXN0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IB
89
+ DwAwggEKAoIBAQC9e8bGIHOLOypKA4lsLcAOcDLAq+ICuVxn9Vg0No0m32Ok/K7G
90
+ uEGtlC8RidObntblUwqdX2uP7mqAQm19j78UTl1KT97vMmmFrpVZ7oQvEm1FUq3t
91
+ FBmJglthJrSbpdZjLf7a7eL1NnunkfBdI1DK9QL9ndMjNwZNFbXhld4fC5zuSr/L
92
+ PxawSzTEsoTaB0Nw0DdRowaZgrPxc0hQsrj9OF20gTIJIYO7ctZzE/JJchmBzgI4
93
+ CdfAYg7zNS+0oc0ylV0CWMerQtLICI6BtiQ482bCuGYJ00NlDcdjd3w+A2cj7PrH
94
+ wH5UhtORL5Q6i9EfGGUCDbmfpiVD9Bd3ukbXAgMBAAGjXDBaMA4GA1UdDwEB/wQE
95
+ AwIFoDAdBgNVHQ4EFgQU2jmj7l5rSw0yVb/vlWAYkK/YBwkwKQYDVR0RBCIwIIIL
96
+ Y3VrZS1tYXN0ZXKCCWxvY2FsaG9zdIIGY29uanVyMA0GCSqGSIb3DQEBCwUAA4IB
97
+ AQBCepy6If67+sjuVnT9NGBmjnVaLa11kgGNEB1BZQnvCy0IN7gpLpshoZevxYDR
98
+ 3DnPAetQiZ70CSmCwjL4x6AVxQy59rRj0Awl9E1dgFTYI3JxxgLsI9ePdIRVEPnH
99
+ dhXqPY5ZIZhvdHlLStjsXX7laaclEtMeWfSzxe4AmP/Sm/er4ks0gvLQU6/XJNIu
100
+ RnRH59ZB1mZMsIv9Ii790nnioYFR54JmQu1JsIib77ZdSXIJmxAtraJSTLcZbU1E
101
+ +SM3XCE423Xols7onyluMYDy3MCUTFwoVMRBcRWCAk5gcv6XvZDfLi6Zwdne6x3Y
102
+ bGenr4vsPuSFsycM03/EcQDT
103
+ -----END CERTIFICATE-----
104
+ """
105
+ end
106
+
107
+ let(:two_certificates_chain) do
108
+ """-----BEGIN CERTIFICATE-----
109
+ MIIDPjCCAiagAwIBAgIVAKW1gdmOFrXt6xB0iQmYQ4z8Pf+kMA0GCSqGSIb3DQEB
110
+ CwUAMD0xETAPBgNVBAoTCGN1Y3VtYmVyMRIwEAYDVQQLEwlDb25qdXIgQ0ExFDAS
111
+ BgNVBAMTC2N1a2UtbWFzdGVyMB4XDTE1MTAwNzE2MzAwNloXDTI1MTAwNDE2MzAw
112
+ NlowFjEUMBIGA1UEAwwLY3VrZS1tYXN0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IB
113
+ DwAwggEKAoIBAQC9e8bGIHOLOypKA4lsLcAOcDLAq+ICuVxn9Vg0No0m32Ok/K7G
114
+ uEGtlC8RidObntblUwqdX2uP7mqAQm19j78UTl1KT97vMmmFrpVZ7oQvEm1FUq3t
115
+ FBmJglthJrSbpdZjLf7a7eL1NnunkfBdI1DK9QL9ndMjNwZNFbXhld4fC5zuSr/L
116
+ PxawSzTEsoTaB0Nw0DdRowaZgrPxc0hQsrj9OF20gTIJIYO7ctZzE/JJchmBzgI4
117
+ CdfAYg7zNS+0oc0ylV0CWMerQtLICI6BtiQ482bCuGYJ00NlDcdjd3w+A2cj7PrH
118
+ wH5UhtORL5Q6i9EfGGUCDbmfpiVD9Bd3ukbXAgMBAAGjXDBaMA4GA1UdDwEB/wQE
119
+ AwIFoDAdBgNVHQ4EFgQU2jmj7l5rSw0yVb/vlWAYkK/YBwkwKQYDVR0RBCIwIIIL
120
+ Y3VrZS1tYXN0ZXKCCWxvY2FsaG9zdIIGY29uanVyMA0GCSqGSIb3DQEBCwUAA4IB
121
+ AQBCepy6If67+sjuVnT9NGBmjnVaLa11kgGNEB1BZQnvCy0IN7gpLpshoZevxYDR
122
+ 3DnPAetQiZ70CSmCwjL4x6AVxQy59rRj0Awl9E1dgFTYI3JxxgLsI9ePdIRVEPnH
123
+ dhXqPY5ZIZhvdHlLStjsXX7laaclEtMeWfSzxe4AmP/Sm/er4ks0gvLQU6/XJNIu
124
+ RnRH59ZB1mZMsIv9Ii790nnioYFR54JmQu1JsIib77ZdSXIJmxAtraJSTLcZbU1E
125
+ +SM3XCE423Xols7onyluMYDy3MCUTFwoVMRBcRWCAk5gcv6XvZDfLi6Zwdne6x3Y
126
+ bGenr4vsPuSFsycM03/EcQDT
127
+ -----END CERTIFICATE-----
128
+ -----BEGIN CERTIFICATE-----
129
+ MIIDhzCCAm+gAwIBAgIJAJnsrJ1+j9MhMA0GCSqGSIb3DQEBCwUAMD0xETAPBgNV
130
+ BAoTCGN1Y3VtYmVyMRIwEAYDVQQLEwlDb25qdXIgQ0ExFDASBgNVBAMTC2N1a2Ut
131
+ bWFzdGVyMB4XDTE1MTAwNzE2MzAwM1oXDTI1MTAwNDE2MzAwM1owPTERMA8GA1UE
132
+ ChMIY3VjdW1iZXIxEjAQBgNVBAsTCUNvbmp1ciBDQTEUMBIGA1UEAxMLY3VrZS1t
133
+ YXN0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsuZ06Ld4JDhxZ
134
+ FcxKVxu7MTjXVv6W8pI7qFKmgr39aNqmDpKYJ1H9aM+r9zaTAeithpM4wJpVswkJ
135
+ d0RSuKdm1LOx11yHLyZ1OvlPHFhsVWdZIQZ6R9srhPYBUCMem4sHR5IAcBBX+HkR
136
+ 35gaPYUl1uFV/9zCniekt92Kdta+it1WL7XinXTBURlhDawiD/kv1C9x6dICEJVe
137
+ IT/jRohmqHAoM/JSOQTthaDli3Qvu5K8XAx8UXvWVmv3eStZFVDbC4ZEueRd9KAe
138
+ 4IZ5FxdpFYkPBgt2lBYeydYKRShyYrDKye1uJBDkeplNaYW4cS4mOhYuRkdKn7MH
139
+ uY/xb1lFAgMBAAGjgYkwgYYwKQYDVR0RBCIwIIILY3VrZS1tYXN0ZXKCCWxvY2Fs
140
+ aG9zdIIGY29uanVyMB0GA1UdDgQWBBRHpGF7aQbHdORYgQKDC2hV6NzEKzAfBgNV
141
+ HSMEGDAWgBRHpGF7aQbHdORYgQKDC2hV6NzEKzAMBgNVHRMEBTADAQH/MAsGA1Ud
142
+ DwQEAwIB5jANBgkqhkiG9w0BAQsFAAOCAQEAGZT9Wek1hYluIVaxu03wSKCKIJ4p
143
+ KxTHw+mLDapg1y9t3Fa/5IQQK0Bx0xGU2qWiQKjda3vdFPJWO6l6XJvsUY5Nwtm5
144
+ Gcsk8l3L/zWCrjrFTH3TdVad5E+DTwVhThelmEjw68AyM+WuOL61j0MItd9mLW74
145
+ Lv2zouj9nQBdnUBHWQ0EL/9d5cfaCVu/bFlDfYt7Yj0IzXCuaWZfJeHodU1hmqVX
146
+ BvYRjnTB2LSxfmSnkrCeFPmhE11bWVtsLIdrGIgtEMX0/s9xg58QuNnva1U3pJsW
147
+ RjvSxre4Xg2qlI9Laybb4oZ4g6DI8hRbL0VdFAsveg6SXg2RxgJcXeJUFw==
148
+ -----END CERTIFICATE-----
149
+ """
150
+ end
151
+
152
+ let(:store){ double('default store') }
153
+
154
+ context 'with one certificate in the chain' do
155
+ subject{ Conjur::CertUtils.add_chained_cert(store, one_certificate_chain) }
156
+
157
+ it 'adds one certificate to the store' do
158
+ expect(store).to receive(:add_cert).once
159
+ expect(subject).to be_truthy
160
+ end
161
+ end
162
+
163
+ context 'with two certificate in the chain' do
164
+ subject{ Conjur::CertUtils.add_chained_cert(store, two_certificates_chain) }
165
+
166
+ it 'adds both certificate to the store' do
167
+ expect(store).to receive(:add_cert).twice
168
+ expect(subject).to be_truthy
169
+ end
170
+ end
171
+
172
+ end
81
173
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Conjur::Id do
6
+ it 'requires the id to be fully qualified' do
7
+ expect { Conjur::Id.new 'foo:bar' }.to raise_error ArgumentError
8
+ end
9
+
10
+ it 'can be constructed from a string' do
11
+ id = Conjur::Id.new 'foo:bar:baz'
12
+ expect(id).to be
13
+ {
14
+ account: 'foo',
15
+ kind: 'bar',
16
+ identifier: 'baz'
17
+ }.each { |k, v| expect(id.send(k)).to eq v }
18
+ end
19
+
20
+ it 'can be constructed from an array' do
21
+ id = Conjur::Id.new %w(foo bar baz)
22
+ expect(id).to be
23
+ {
24
+ account: 'foo',
25
+ kind: 'bar',
26
+ identifier: 'baz'
27
+ }.each { |k, v| expect(id.send(k)).to eq v }
28
+ end
29
+ end