Class: Jamf::Connection::Token

Inherits:
Object
  • Object
show all
Defined in:
lib/jamf/api/connection/token.rb

Overview

A token used for a JSS connection

Constant Summary collapse

JAMF_VERSION_RSRC =
'v1/jamf-pro-version'.freeze
AUTH_RSRC_VERSION =
'v1'.freeze
AUTH_RSRC =
'auth'.freeze
NEW_TOKEN_RSRC =
"#{AUTH_RSRC_VERSION}/#{AUTH_RSRC}/token".freeze
KEEP_ALIVE_RSRC =
"#{AUTH_RSRC_VERSION}/#{AUTH_RSRC}/keep-alive".freeze
INVALIDATE_RSRC =
"#{AUTH_RSRC_VERSION}/#{AUTH_RSRC}/invalidate-token".freeze
AUTH_TOKEN_PFX =

this string is prepended to the token data when used for transaction authorization.

'jamf-token '.freeze
JAMF_TRYITOUT_HOST =

Recognize the tryitout server, cuz its /auth endpoint is disabled, and it needs no tokens

"tryitout#{Jamf::Connection::JAMFCLOUD_DOMAIN}".freeze
JAMF_TRYITOUT_TOKEN_BODY =
{
  token: 'This is a fake token, tryitout.jamfcloud.com uses internal tokens',
  expires: 2_000_000_000_000
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(**params) ⇒ Token

Returns a new instance of Token.



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/jamf/api/connection/token.rb', line 88

def initialize(**params)
  @valid = false
  @user = params[:user]
  @base_url = params[:base_url].is_a?(String) ? URI.parse(params[:base_url]) : params[:base_url]
  @timeout = params[:timeout] || Jamf::Connection::DFT_TIMEOUT
  @ssl_options = params[:ssl_options] || {}

  if @base_url.host == JAMF_TRYITOUT_HOST
    init_jamf_tryitout
  elsif params[:pw]
    init_from_pw params[:pw]
  elsif params[:token_string]
    init_from_token_string params[:token_string]
  else
    raise ArgumentError, 'Must provide either pw: or token_string:'
  end
end

Instance Attribute Details

#auth_tokenString (readonly)

Returns The AUTH_TOKEN_PFX with the token data, used in the Authorization header of a request.

Returns:

  • (String)

    The AUTH_TOKEN_PFX with the token data, used in the Authorization header of a request



67
68
69
# File 'lib/jamf/api/connection/token.rb', line 67

def auth_token
  @auth_token
end

#base_urlURI (readonly)

Returns The base API url, e.g. myjamf.jamfcloud.com/uapi.

Returns:



70
71
72
# File 'lib/jamf/api/connection/token.rb', line 70

def base_url
  @base_url
end

#expiresJamf::Timestamp (readonly) Also known as: expiration

Returns:



62
63
64
# File 'lib/jamf/api/connection/token.rb', line 62

def expires
  @expires
end

#last_refresh_resultSymbol? (readonly)

What happened the last time we tried to refresh?

:expired_refreshed - token was expired, a new token was created with the pw
:expired_pw_failed - token was expired, pw failed to make a new token
:expired_no_pw - token was expired, but no pw was given to make a new one
:refreshed - the token refresh worked with no need for the pw
:refresh_failed - the token refresh failed, and no pw was given to make a new one
:refreshed_with_pw - the token refresh failed, pw worked to make a new token
:refresh_failed_no_pw - the token refresh failed, pw also failed to make a new token
nil - no refresh has been attempted for this token.

Returns:

  • (Symbol, nil)

    :refreshed, :pw, :expired,:failed, or nil if never refreshed



86
87
88
# File 'lib/jamf/api/connection/token.rb', line 86

def last_refresh_result
  @last_refresh_result
end

#login_timeJamf::Timestamp (readonly)

Returns when was this token created?.

Returns:



73
74
75
# File 'lib/jamf/api/connection/token.rb', line 73

def 
  @login_time
end

#userString (readonly)

Returns The user who generated this token.

Returns:

  • (String)

    The user who generated this token



59
60
61
# File 'lib/jamf/api/connection/token.rb', line 59

def user
  @user
end

Instance Method Details

#accountObject

the Jamf::Account object assciated with this token



203
204
205
206
207
208
209
210
# File 'lib/jamf/api/connection/token.rb', line 203

def 
  return @account if @account

  resp = token_connection(AUTH_RSRC, token: @auth_token).get
  return unless resp.success?

  @account = Jamf::APIAccount.new resp.body
end

#expired?Boolean

Returns:

  • (Boolean)


170
171
172
173
174
# File 'lib/jamf/api/connection/token.rb', line 170

def expired?
  return unless @expires

  Time.now >= @expires
end

#hostString

Returns:



148
149
150
# File 'lib/jamf/api/connection/token.rb', line 148

def host
  @base_url.host
end

#init_from_pw(pw) ⇒ Object

Initialize from password



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/jamf/api/connection/token.rb', line 116

def init_from_pw(pw)
  resp = token_connection(
    NEW_TOKEN_RSRC,
    pw: pw,
    timeout: @timeout,
    ssl_opts: @ssl_options
  ).post

  if  resp.success?
    parse_token_from_response resp
  elsif resp.status == 401
    raise Jamf::AuthenticationError, 'Incorrect name or password'
  else
    # TODO: better error reporting here
    raise Jamf::AuthenticationError, 'An error occurred while authenticating'
  end
end

#init_from_token_string(str) ⇒ Object

Initialize from token string



135
136
137
138
139
140
141
142
143
144
145
# File 'lib/jamf/api/connection/token.rb', line 135

def init_from_token_string(str)
  str = "#{AUTH_TOKEN_PFX}#{str}" unless str.start_with? AUTH_TOKEN_PFX
  resp = token_connection(AUTH_RSRC, token: str).get
  raise Jamf::InvalidDataError, 'Token string is not valid' unless resp.success?

  @auth_token = str
  @user = resp.body.dig :account, :username

  # use this token to get a fresh one with a known expiration
  refresh
end

#init_jamf_tryitoutObject

Initialize from password



107
108
109
110
111
112
113
# File 'lib/jamf/api/connection/token.rb', line 107

def init_jamf_tryitout
  @token_response_body = JAMF_TRYITOUT_TOKEN_BODY
  @auth_token = AUTH_TOKEN_PFX + @token_response_body[:token]
  @expires = Jamf::Timestamp.new @token_response_body[:expires]
  @login_time = Jamf::Timestamp.new Time.now
  @valid = true
end

#invalidateObject Also known as: destroy

Make this token invalid



249
250
251
# File 'lib/jamf/api/connection/token.rb', line 249

def invalidate
  @valid = !token_connection(INVALIDATE_RSRC, token: @auth_token).post.success?
end

#jamf_buildString

Returns:



164
165
166
167
# File 'lib/jamf/api/connection/token.rb', line 164

def jamf_build
  fetch_jamf_version unless @jamf_build
  @jamf_build
end

#jamf_versionString

Returns:



158
159
160
161
# File 'lib/jamf/api/connection/token.rb', line 158

def jamf_version
  fetch_jamf_version unless @jamf_version
  @jamf_version
end

#portInteger

Returns:

  • (Integer)


153
154
155
# File 'lib/jamf/api/connection/token.rb', line 153

def port
  @base_url.port
end

#refresh(pw = nil) ⇒ Jamf::Timestamp Also known as: keep_alive

Use this token to get a fresh one. If a pw is provided try to use it to get a new token if a proper refresh fails.

Parameters:

  • pw (String) (defaults to: nil)

    Optional password to use if token refresh fails. Must be the correct passwd or the token's user (obviously)

Returns:



220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
# File 'lib/jamf/api/connection/token.rb', line 220

def refresh(pw = nil)
  # gotta have a pw if expired
  if expired?
    # try the passwd
    return refresh_with_passwd(pw, :expired_refreshed, :expired_pw_failed) if pw

    # no passwd? no chance!
    @last_refresh_result = :expired_no_pw
    raise Jamf::InvalidTokenError, 'Token has expired'
  end

  # Now try a normal refresh of our non-expired token
  keep_alive_token_resp = token_connection(KEEP_ALIVE_RSRC, token: @auth_token).post
  if keep_alive_token_resp.success?
    parse_token_from_response keep_alive_token_resp
    @last_refresh_result = :refreshed
    return expires
  end

  # if we're here, the normal refresh failed, so try the pw
  return refresh_with_passwd(pw, :refreshed_with_pw, :refresh_failed_no_pw) if pw

  # if we're here, no pw? no chance!
  @last_refresh_result = :refresh_failed
  raise 'An error occurred while refreshing the token' unless pw
end

#secs_remainingFloat

Returns:

  • (Float)


177
178
179
180
181
# File 'lib/jamf/api/connection/token.rb', line 177

def secs_remaining
  return unless @expires

  @expires - Time.now
end

#time_remainingString

Returns e.g. “1 week 6 days 23 hours 49 minutes 56 seconds”.

Returns:

  • (String)

    e.g. “1 week 6 days 23 hours 49 minutes 56 seconds”



184
185
186
187
188
# File 'lib/jamf/api/connection/token.rb', line 184

def time_remaining
  return unless @expires

  Jamf.humanize_secs secs_remaining
end

#valid?Boolean

Returns:

  • (Boolean)


191
192
193
194
195
196
197
198
199
200
# File 'lib/jamf/api/connection/token.rb', line 191

def valid?
  @valid =
    if expired?
      false
    elsif !@auth_token
      false
    else
      token_connection(AUTH_RSRC, token: @auth_token).get.success?
    end
end