conjur-api 5.3.2 → 5.3.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,17 +1,58 @@
1
- Feature: Display User object fields.
1
+ Feature: User object
2
2
 
3
3
  Background:
4
- Given a new user
5
4
 
6
- Scenario: User has a uidnumber.
7
- Then I run the code:
5
+ Scenario: User has a uidnumber
6
+ Given a new user
7
+ Then I can run the code:
8
8
  """
9
9
  @user.uidnumber
10
10
  """
11
11
  Then the result should be "1000"
12
12
 
13
- Scenario: Logged-in user is the current_role.
14
- Then I run the code:
13
+ Scenario: Logged-in user is the current_role
14
+ Given a new user
15
+ Then I can run the code:
15
16
  """
16
17
  expect($conjur.current_role(Conjur.configuration.account).id.to_s).to eq("cucumber:user:admin")
17
18
  """
19
+
20
+ # Rotation of own API key should be done via `Conjur::API.rotate_api_key()`
21
+ Scenario: User's own API key cannot be rotated with an API key
22
+ Given a new user
23
+ Then this code should fail with "You cannot rotate your own API key via this method"
24
+ """
25
+ user = Conjur::API.new_from_key(@user.login, @user_api_key).resource(@user.id)
26
+ user.rotate_api_key
27
+ """
28
+
29
+ # Rotation of own API key should be done via `Conjur::API.rotate_api_key()`
30
+ Scenario: User's own API key cannot be rotated with a token
31
+ Given a new user
32
+ Then this code should fail with "You cannot rotate your own API key via this method"
33
+ """
34
+ token = Conjur::API.new_from_key(@user.login, @user_api_key).token
35
+
36
+ user = Conjur::API.new_from_token(token).resource(@user.id)
37
+ user.rotate_api_key
38
+ """
39
+
40
+ Scenario: Delegated user's API key can be rotated with an API key
41
+ Given a new delegated user
42
+ Then I can run the code:
43
+ """
44
+ delegated_user_resource = Conjur::API.new_from_key(@user_owner.login, @user_owner_api_key).resource(@user.id)
45
+ api_key = delegated_user_resource.rotate_api_key
46
+ Conjur::API.new_from_key(delegated_user_resource.login, api_key).token
47
+ """
48
+
49
+ Scenario: Delegated user's API key can be rotated with a token
50
+ Given a new delegated user
51
+ Then I can run the code:
52
+ """
53
+ token = Conjur::API.new_from_key(@user_owner.login, @user_owner_api_key).token
54
+
55
+ delegated_user_resource = Conjur::API.new_from_token(token).resource(@user.id)
56
+ api_key = delegated_user_resource.rotate_api_key
57
+ Conjur::API.new_from_key(delegated_user_resource.login, api_key).token
58
+ """
@@ -1,7 +1,5 @@
1
1
  require 'simplecov'
2
- require 'simplecov-cobertura'
3
2
 
4
- SimpleCov.formatter = SimpleCov::Formatter::CoberturaFormatter
5
3
  SimpleCov.start
6
4
 
7
5
  require 'json_spec/cucumber'
@@ -52,12 +52,16 @@ module Conjur
52
52
  # @note You will not be able to access the API key returned by this method later, so you should
53
53
  # probably hang onto it it.
54
54
  #
55
- # @note You cannot rotate your own API key with this method. To do so, use `Conjur::API.rotate_api_key`
55
+ # @note You cannot rotate your own API key with this method. To do so, use `Conjur::API.rotate_api_key`.
56
56
  #
57
57
  # @note This feature requires a Conjur appliance running version 4.6 or higher.
58
58
  #
59
59
  # @return [String] the new API key for this user.
60
60
  def rotate_api_key
61
+ if login == username
62
+ raise 'You cannot rotate your own API key via this method. To do so, use `Conjur::API.rotate_api_key`'
63
+ end
64
+
61
65
  url_for(:authn_rotate_api_key, credentials, account, id).put("").body
62
66
  end
63
67
  end
@@ -50,7 +50,7 @@ module Conjur
50
50
  url_for(:authn_login, account, username, password).get
51
51
  end
52
52
 
53
- # Exchanges Conjur the API key (refresh token) for an access token. The access token can
53
+ # Exchanges Conjur the API key (refresh token) for an access token. The access token can
54
54
  # then be used to authenticate further API calls.
55
55
  #
56
56
  # @param [String] username The username or host id for which we want a token
@@ -65,7 +65,7 @@ module Conjur
65
65
  JSON.parse url_for(:authn_authenticate, account, username).post(api_key, content_type: 'text/plain')
66
66
  end
67
67
 
68
- # Obtains an access token from the +authn_local+ service. The access token can
68
+ # Obtains an access token from the +authn_local+ service. The access token can
69
69
  # then be used to authenticate further API calls.
70
70
  #
71
71
  # @param [String] username The username or host id for which we want a token
@@ -80,7 +80,7 @@ module Conjur
80
80
  require 'json'
81
81
  require 'socket'
82
82
  message = url_for(:authn_authenticate_local, username, account, expiration, cidr)
83
- JSON.parse(UNIXSocket.open(Conjur.configuration.authn_local_socket) {|s| s.puts message; s.gets })
83
+ JSON.parse(UNIXSocket.open(Conjur.configuration.authn_local_socket) {|s| s.puts message; s.gets })
84
84
  end
85
85
 
86
86
  # Change a user's password. To do this, you must have the user's current password. This does not change or rotate
@@ -20,7 +20,7 @@ module Conjur
20
20
  class API
21
21
  include QueryString
22
22
  include BuildObject
23
-
23
+
24
24
  #@!group Resources
25
25
 
26
26
  # Find a resource by its id.
@@ -84,7 +84,7 @@ module Conjur
84
84
  def resources options = {}
85
85
  options = { host: Conjur.configuration.core_url, credentials: credentials }.merge options
86
86
  options[:account] ||= Conjur.configuration.account
87
-
87
+
88
88
  host, credentials, account, kind = options.values_at(*[:host, :credentials, :account, :kind])
89
89
  fail ArgumentError, "host and account are required" unless [host, account].all?
90
90
  %w(host credentials account kind).each do |name|
@@ -8,18 +8,27 @@ module Conjur
8
8
 
9
9
  def authn_login account, username, password
10
10
  verify_account(account)
11
- RestClient::Resource.new(Conjur.configuration.authn_url, user: username, password: password)['users/login']
11
+ RestClient::Resource.new(
12
+ Conjur.configuration.authn_url,
13
+ Conjur.configuration.create_rest_client_options(
14
+ user: username,
15
+ password: password
16
+ )
17
+ )['users/login']
12
18
  end
13
19
 
14
20
  def authn_authenticate account, username
15
21
  verify_account(account)
16
- RestClient::Resource.new(Conjur.configuration.authn_url)['users'][fully_escape username]['authenticate']
22
+ RestClient::Resource.new(
23
+ Conjur.configuration.authn_url,
24
+ Conjur.configuration.rest_client_options
25
+ )['users'][fully_escape username]['authenticate']
17
26
  end
18
27
 
19
28
  # For v4, the authn-local message is the username.
20
29
  def authn_authenticate_local username, account, expiration, cidr, &block
21
30
  verify_account(account)
22
-
31
+
23
32
  raise "'expiration' is not supported for authn-local v4" if expiration
24
33
  raise "'cidr' is not supported for authn-local v4" if cidr
25
34
 
@@ -28,36 +37,51 @@ module Conjur
28
37
 
29
38
  def authn_rotate_api_key credentials, account, id
30
39
  verify_account(account)
31
- username = if id.kind == "user"
32
- id.identifier
33
- else
34
- [ id.kind, id.identifier ].join('/')
35
- end
36
- RestClient::Resource.new(Conjur.configuration.authn_url, credentials)['users']["api_key?id=#{username}"]
40
+ username = id.kind == "user" ? id.identifier : [id.kind, id.identifier].join('/')
41
+ RestClient::Resource.new(
42
+ Conjur.configuration.authn_url,
43
+ Conjur.configuration.create_rest_client_options(credentials)
44
+ )['users']["api_key?id=#{username}"]
37
45
  end
38
46
 
39
47
  def authn_rotate_own_api_key account, username, password
40
48
  verify_account(account)
41
- RestClient::Resource.new(Conjur.configuration.authn_url, user: username, password: password)['users']["api_key"]
49
+ RestClient::Resource.new(
50
+ Conjur.configuration.authn_url,
51
+ Conjur.configuration.create_rest_client_options(user: username, password: password)
52
+ )['users']["api_key"]
42
53
  end
43
54
 
44
55
  def host_factory_create_host token
45
56
  http_options = {
46
57
  headers: { authorization: %Q(Token token="#{token}") }
47
58
  }
48
- RestClient::Resource.new(Conjur.configuration.core_url, http_options)['host_factories']['hosts']
59
+ RestClient::Resource.new(
60
+ Conjur.configuration.core_url,
61
+ Conjur.configuration.create_rest_client_options(http_options)
62
+ )['host_factories']['hosts']
49
63
  end
50
64
 
51
65
  def host_factory_create_tokens credentials, id
52
- RestClient::Resource.new(Conjur.configuration.core_url, credentials)['host_factories'][id.identifier]['tokens']
66
+ RestClient::Resource.new(
67
+ Conjur.configuration.core_url,
68
+ Conjur.configuration.create_rest_client_options(credentials)
69
+ )['host_factories'][id.identifier]['tokens']
53
70
  end
54
71
 
55
72
  def host_factory_revoke_token credentials, token
56
- RestClient::Resource.new(Conjur.configuration.core_url, credentials)['host_factories']['tokens'][token]
73
+ RestClient::Resource.new(
74
+ Conjur.configuration.core_url,
75
+ Conjur.configuration.create_rest_client_options(credentials)
76
+ )['host_factories']['tokens'][token]
57
77
  end
58
78
 
59
79
  def resources_resource credentials, id
60
- RestClient::Resource.new(Conjur.configuration.core_url, credentials)['authz'][id.account]['resources'][id.kind][id.identifier]
80
+
81
+ RestClient::Resource.new(
82
+ Conjur.configuration.core_url,
83
+ Conjur.configuration.create_rest_client_options(credentials)
84
+ )['authz'][id.account]['resources'][id.kind][id.identifier]
61
85
  end
62
86
 
63
87
  def resources_check credentials, id, privilege, role
@@ -73,47 +97,80 @@ module Conjur
73
97
  end
74
98
 
75
99
  def resources_permitted_roles credentials, id, privilege
76
- RestClient::Resource.new(Conjur.configuration.core_url, credentials)['authz'][id.account]['roles']['allowed_to'][privilege][id.kind][id.identifier]
100
+ RestClient::Resource.new(
101
+ Conjur.configuration.core_url,
102
+ Conjur.configuration.create_rest_client_options(credentials)
103
+ )['authz'][id.account]['roles']['allowed_to'][privilege][id.kind][id.identifier]
77
104
  end
78
105
 
79
106
  def roles_role credentials, id
80
- RestClient::Resource.new(Conjur.configuration.core_url, credentials)['authz'][id.account]['roles'][id.kind][id.identifier]
107
+ RestClient::Resource.new(
108
+ Conjur.configuration.core_url,
109
+ Conjur.configuration.create_rest_client_options(credentials)
110
+ )['authz'][id.account]['roles'][id.kind][id.identifier]
81
111
  end
82
112
 
83
113
  def secrets_add credentials, id
84
114
  verify_account(id.account)
85
- RestClient::Resource.new(Conjur.configuration.core_url, credentials)['variables'][fully_escape id.identifier]['values']
115
+ RestClient::Resource.new(
116
+ Conjur.configuration.core_url,
117
+ Conjur.configuration.create_rest_client_options(credentials)
118
+ )['variables'][fully_escape id.identifier]['values']
86
119
  end
87
120
 
88
121
  def variable credentials, id
89
122
  verify_account(id.account)
90
- RestClient::Resource.new(Conjur.configuration.core_url, credentials)['variables'][fully_escape id.identifier]
123
+ RestClient::Resource.new(
124
+ Conjur.configuration.core_url,
125
+ Conjur.configuration.create_rest_client_options(credentials)
126
+ )['variables'][fully_escape id.identifier]
91
127
  end
92
128
 
93
129
  def secrets_value credentials, id, options
94
- RestClient::Resource.new(Conjur.configuration.core_url, credentials)['variables'][fully_escape id.identifier]['value'][options_querystring options]
130
+ RestClient::Resource.new(
131
+ Conjur.configuration.core_url,
132
+ Conjur.configuration.create_rest_client_options(credentials)
133
+ )['variables'][fully_escape id.identifier]['value'][options_querystring options]
95
134
  end
96
135
 
97
136
  def secrets_values credentials, variable_ids
98
137
  options = {
99
138
  vars: Array(variable_ids).map { |v| fully_escape(v.identifier) }.join(',')
100
139
  }
101
- RestClient::Resource.new(Conjur.configuration.core_url, credentials)['variables']['values'][options_querystring options]
140
+ RestClient::Resource.new(
141
+ Conjur.configuration.core_url,
142
+ Conjur.configuration.create_rest_client_options(credentials)
143
+ )['variables']['values'][options_querystring options]
102
144
  end
103
145
 
104
146
  def group_attributes credentials, resource, id
105
147
  verify_account(id.account)
106
- JSON.parse(RestClient::Resource.new(Conjur.configuration.core_url, credentials)['groups'][fully_escape id.identifier].get)
148
+ JSON.parse(
149
+ RestClient::Resource.new(
150
+ Conjur.configuration.core_url,
151
+ Conjur.configuration.create_rest_client_options(credentials)
152
+ )['groups'][fully_escape id.identifier].get
153
+ )
107
154
  end
108
155
 
109
156
  def variable_attributes credentials, resource, id
110
157
  verify_account(id.account)
111
- JSON.parse(RestClient::Resource.new(Conjur.configuration.core_url, credentials)['variables'][fully_escape id.identifier].get)
158
+ JSON.parse(
159
+ RestClient::Resource.new(
160
+ Conjur.configuration.core_url,
161
+ Conjur.configuration.create_rest_client_options(credentials)
162
+ )['variables'][fully_escape id.identifier].get
163
+ )
112
164
  end
113
165
 
114
166
  def user_attributes credentials, resource, id
115
167
  verify_account(id.account)
116
- JSON.parse(RestClient::Resource.new(Conjur.configuration.core_url, credentials)['users'][fully_escape id.identifier].get)
168
+ JSON.parse(
169
+ RestClient::Resource.new(
170
+ Conjur.configuration.core_url,
171
+ Conjur.configuration.create_rest_client_options(credentials)
172
+ )['users'][fully_escape id.identifier].get
173
+ )
117
174
  end
118
175
 
119
176
  def parse_group_gidnumber attributes
@@ -27,19 +27,34 @@ module Conjur
27
27
  extend self
28
28
 
29
29
  def authn_login account, username, password
30
- RestClient::Resource.new(Conjur.configuration.authn_url, user: username, password: password)[fully_escape account]['login']
30
+ RestClient::Resource.new(
31
+ Conjur.configuration.authn_url,
32
+ Conjur.configuration.create_rest_client_options(
33
+ user: username,
34
+ password: password
35
+ )
36
+ )[fully_escape account]['login']
31
37
  end
32
38
 
33
39
  def authn_authenticate account, username
34
- RestClient::Resource.new(Conjur.configuration.authn_url)[fully_escape account][fully_escape username]['authenticate']
40
+ RestClient::Resource.new(
41
+ Conjur.configuration.authn_url,
42
+ Conjur.configuration.rest_client_options
43
+ )[fully_escape account][fully_escape username]['authenticate']
35
44
  end
36
45
 
37
46
  def authenticator account, authenticator, service_id, credentials
38
- RestClient::Resource.new(Conjur.configuration.core_url, credentials)[fully_escape authenticator][fully_escape service_id][fully_escape account]
47
+ RestClient::Resource.new(
48
+ Conjur.configuration.core_url,
49
+ Conjur.configuration.create_rest_client_options(credentials)
50
+ )[fully_escape authenticator][fully_escape service_id][fully_escape account]
39
51
  end
40
52
 
41
53
  def authenticators
42
- RestClient::Resource.new(Conjur.configuration.core_url)['authenticators']
54
+ RestClient::Resource.new(
55
+ Conjur.configuration.core_url,
56
+ Conjur.configuration.rest_client_options
57
+ )['authenticators']
43
58
  end
44
59
 
45
60
  # For v5, the authn-local message is a JSON string with account, sub, and optional fields.
@@ -51,38 +66,68 @@ module Conjur
51
66
  end
52
67
 
53
68
  def authn_update_password account, username, password
54
- RestClient::Resource.new(Conjur.configuration.authn_url, user: username, password: password)[fully_escape account]['password']
69
+ RestClient::Resource.new(
70
+ Conjur.configuration.authn_url,
71
+ Conjur.configuration.create_rest_client_options(
72
+ user: username,
73
+ password: password
74
+ )
75
+ )[fully_escape account]['password']
55
76
  end
56
77
 
57
78
  def authn_rotate_api_key credentials, account, id
58
- RestClient::Resource.new(Conjur.configuration.core_url, credentials)['authn'][fully_escape account]["api_key?role=#{id}"]
79
+ RestClient::Resource.new(
80
+ Conjur.configuration.core_url,
81
+ Conjur.configuration.create_rest_client_options(credentials)
82
+ )['authn'][fully_escape account]["api_key?role=#{id}"]
59
83
  end
60
84
 
61
85
  def authn_rotate_own_api_key account, username, password
62
- RestClient::Resource.new(Conjur.configuration.authn_url, user: username, password: password)[fully_escape account]['api_key']
86
+ RestClient::Resource.new(
87
+ Conjur.configuration.authn_url,
88
+ Conjur.configuration.create_rest_client_options(
89
+ user: username,
90
+ password: password
91
+ )
92
+ )[fully_escape account]['api_key']
63
93
  end
64
94
 
65
95
  def host_factory_create_host token
66
96
  http_options = {
67
97
  headers: { authorization: %Q(Token token="#{token}") }
68
98
  }
69
- RestClient::Resource.new(Conjur.configuration.core_url, http_options)["host_factories"]["hosts"]
99
+ RestClient::Resource.new(
100
+ Conjur.configuration.core_url,
101
+ Conjur.configuration.create_rest_client_options(http_options)
102
+ )["host_factories"]["hosts"]
70
103
  end
71
104
 
72
105
  def host_factory_create_tokens credentials, id
73
- RestClient::Resource.new(Conjur.configuration.core_url, credentials)['host_factory_tokens']
106
+ RestClient::Resource.new(
107
+ Conjur.configuration.core_url,
108
+ Conjur.configuration.create_rest_client_options(credentials)
109
+ )['host_factory_tokens']
74
110
  end
75
111
 
76
112
  def host_factory_revoke_token credentials, token
77
- RestClient::Resource.new(Conjur.configuration.core_url, credentials)['host_factory_tokens'][token]
113
+ RestClient::Resource.new(
114
+ Conjur.configuration.core_url,
115
+ Conjur.configuration.create_rest_client_options(credentials)
116
+ )['host_factory_tokens'][token]
78
117
  end
79
118
 
80
119
  def policies_load_policy credentials, account, id
81
- RestClient::Resource.new(Conjur.configuration.core_url, credentials)['policies'][fully_escape account]['policy'][fully_escape id]
120
+ RestClient::Resource.new(
121
+ Conjur.configuration.core_url,
122
+ Conjur.configuration.create_rest_client_options(credentials)
123
+ )['policies'][fully_escape account]['policy'][fully_escape id]
82
124
  end
83
125
 
84
126
  def public_keys_for_user account, username
85
- RestClient::Resource.new(Conjur.configuration.core_url)['public_keys'][fully_escape account]['user'][fully_escape username]
127
+ RestClient::Resource.new(
128
+ Conjur.configuration.core_url,
129
+ Conjur.configuration.rest_client_options
130
+ )['public_keys'][fully_escape account]['user'][fully_escape username]
86
131
  end
87
132
 
88
133
  def resources credentials, account, kind, options
@@ -91,11 +136,17 @@ module Conjur
91
136
  path = "/resources/#{fully_escape account}"
92
137
  path += "/#{fully_escape kind}" if kind
93
138
 
94
- RestClient::Resource.new(Conjur.configuration.core_url, credentials)[path][options_querystring options]
139
+ RestClient::Resource.new(
140
+ Conjur.configuration.core_url,
141
+ Conjur.configuration.create_rest_client_options(credentials)
142
+ )[path][options_querystring options]
95
143
  end
96
144
 
97
145
  def resources_resource credentials, id
98
- RestClient::Resource.new(Conjur.configuration.core_url, credentials)['resources'][id.to_url_path]
146
+ RestClient::Resource.new(
147
+ Conjur.configuration.core_url,
148
+ Conjur.configuration.create_rest_client_options(credentials)
149
+ )['resources'][id.to_url_path]
99
150
  end
100
151
 
101
152
  def resources_permitted_roles credentials, id, privilege
@@ -114,22 +165,34 @@ module Conjur
114
165
  end
115
166
 
116
167
  def roles_role credentials, id
117
- RestClient::Resource.new(Conjur.configuration.core_url, credentials)['roles'][id.to_url_path]
168
+ RestClient::Resource.new(
169
+ Conjur.configuration.core_url,
170
+ Conjur.configuration.create_rest_client_options(credentials)
171
+ )['roles'][id.to_url_path]
118
172
  end
119
173
 
120
174
  def secrets_add credentials, id
121
- RestClient::Resource.new(Conjur.configuration.core_url, credentials)['secrets'][id.to_url_path]
175
+ RestClient::Resource.new(
176
+ Conjur.configuration.core_url,
177
+ Conjur.configuration.create_rest_client_options(credentials)
178
+ )['secrets'][id.to_url_path]
122
179
  end
123
180
 
124
181
  def secrets_value credentials, id, options
125
- RestClient::Resource.new(Conjur.configuration.core_url, credentials)['secrets'][id.to_url_path][options_querystring options]
182
+ RestClient::Resource.new(
183
+ Conjur.configuration.core_url,
184
+ Conjur.configuration.create_rest_client_options(credentials)
185
+ )['secrets'][id.to_url_path][options_querystring options]
126
186
  end
127
187
 
128
188
  def secrets_values credentials, variable_ids
129
189
  options = {
130
190
  variable_ids: Array(variable_ids).join(',')
131
191
  }
132
- RestClient::Resource.new(Conjur.configuration.core_url, credentials)['secrets'][options_querystring(options).gsub("%2C", ',')]
192
+ RestClient::Resource.new(
193
+ Conjur.configuration.core_url,
194
+ Conjur.configuration.create_rest_client_options(credentials)
195
+ )['secrets'][options_querystring(options).gsub("%2C", ',')]
133
196
  end
134
197
 
135
198
  def group_attributes credentials, resource, id
@@ -167,13 +230,16 @@ module Conjur
167
230
  end
168
231
 
169
232
  def ldap_sync_policy(credentials, config_name)
170
- RestClient::Resource.new(Conjur.configuration.core_url, credentials)['ldap-sync']["policy?config_name=#{fully_escape(config_name)}"]
233
+ RestClient::Resource.new(
234
+ Conjur.configuration.core_url,
235
+ Conjur.configuration.create_rest_client_options(credentials)
236
+ )['ldap-sync']["policy?config_name=#{fully_escape(config_name)}"]
171
237
  end
172
-
238
+
173
239
  private
174
240
 
175
241
  def resource_annotations resource
176
- resource.attributes['annotations'] || {}
242
+ resource.attributes['annotations']
177
243
  end
178
244
  end
179
245
  end
data/lib/conjur/api.rb CHANGED
@@ -50,24 +50,6 @@ require 'conjur/layer'
50
50
  require 'conjur/cache'
51
51
  require 'conjur-api/version'
52
52
 
53
- # Monkey patch RestClient::Request so it always uses
54
- # :ssl_cert_store. (RestClient::Resource uses Request to send
55
- # requests, so it sees :ssl_cert_store, too).
56
- # @api private
57
- class RestClient::Request
58
- alias_method :initialize_without_defaults, :initialize
59
-
60
- def default_args
61
- {
62
- ssl_cert_store: OpenSSL::SSL::SSLContext::DEFAULT_CERT_STORE
63
- }
64
- end
65
-
66
- def initialize args
67
- initialize_without_defaults default_args.merge(args)
68
- end
69
- end
70
-
71
53
  # @api private
72
54
  class RestClient::Resource
73
55
  include Conjur::Escape
data/lib/conjur/base.rb CHANGED
@@ -123,19 +123,21 @@ module Conjur
123
123
  #
124
124
  # @return [String] the api key, or nil if this instance was created from a token.
125
125
  attr_reader :api_key
126
-
126
+
127
127
  #@!attribute [r] remote_ip
128
128
  # An optional IP address to be recorded in the audit record for any actions performed by this API instance.
129
129
  attr_reader :remote_ip
130
130
 
131
131
  # The name of the user as which this api instance is authenticated. This is available whether the api
132
- # instance was created from credentials or an authentication token.
132
+ # instance was created from credentials or an authentication token. If the instance was created from
133
+ # credentials, we will use that value directly otherwise we will attempt to extract the username from
134
+ # the token (either the old-style data field or the new-style JWT `sub` field).
133
135
  #
134
136
  # @return [String] the login of the current user.
135
137
  def username
136
- @username || token['data']
138
+ @username || token['data'] || jwt_username(token)
137
139
  end
138
-
140
+
139
141
  # @api private
140
142
  # used to delegate to host providing subclasses.
141
143
  # @return [String] the host
@@ -213,7 +215,7 @@ module Conjur
213
215
  @account = account
214
216
  @username = username
215
217
  @api_key = api_key
216
-
218
+
217
219
  update_token_born
218
220
  end
219
221
 
@@ -323,6 +325,18 @@ module Conjur
323
325
 
324
326
  private
325
327
 
328
+ # Tries to get the username (subject) from a JWT API token by examining
329
+ # its content.
330
+ #
331
+ # @return [String] of the 'sub' payload field from the JWT if present,
332
+ # otherwise return nil
333
+ def jwt_username raw_token
334
+ return nil unless raw_token
335
+ return nil unless raw_token.include? 'payload'
336
+
337
+ JSON.parse(Base64.strict_decode64(raw_token["payload"]))["sub"]
338
+ end
339
+
326
340
  # Tries to refresh the token if possible.
327
341
  #
328
342
  # @return [Hash, false] false if the token couldn't be refreshed due to
@@ -20,9 +20,9 @@ module Conjur
20
20
  include LogSource
21
21
  include BuildObject
22
22
  include Routing
23
-
23
+
24
24
  attr_reader :id, :credentials
25
-
25
+
26
26
  def initialize id, credentials
27
27
  @id = Id.new id
28
28
  @credentials = credentials
@@ -34,10 +34,18 @@ module Conjur
34
34
  }
35
35
  end
36
36
 
37
- def account; id.account; end
38
- def kind; id.kind; end
39
- def identifier; id.identifier; end
40
-
37
+ def account
38
+ id.account
39
+ end
40
+
41
+ def kind
42
+ id.kind
43
+ end
44
+
45
+ def identifier
46
+ id.identifier
47
+ end
48
+
41
49
  def username
42
50
  credentials[:username] or raise "No username found in credentials"
43
51
  end
@@ -45,6 +53,5 @@ module Conjur
45
53
  def inspect
46
54
  "<#{self.class.name} id='#{id.to_s}'>"
47
55
  end
48
-
49
56
  end
50
57
  end