PixarAnimationStudios / ruby-jss

ruby-jss provides native ruby access to the REST APIs of Jamf Pro, an enterprise/education tool for managing Apple devices, from jamf.com. The Jamf module provides access to both APIs. Jamf Pro objects are implemented as classes and interact with each other. Authentication tokens, data format and other details are handled under the hood to allow simpler, intuitive automation of Jamf-related tasks.
http://pixaranimationstudios.github.io/jss-api-gem/index.html
Other
99 stars 30 forks source link

[Request] Client Credentials support #95

Open nekrich opened 7 months ago

nekrich commented 7 months ago

Hi. In the v10.49.0 API, JAMF introduced the Classic API Authentication Changes a new authentication method with Client Credentials.

I looked into your implementation and didn't find any support.

I thought it would be easy, but the current JAMF::Connection::Token implementation with user/pw support and time/secs to refresh looks impossible to adapt easily, especially for me without wast knowledge of Ruby and first look into your great repo 😅.

I have two questions:

  1. Do you have any plans to support client credentials?
  2. If not, is there any workaround for the current implementation so I can fetch the token by myself and push it to the Jamf.cnx? Yes, it's a token with a short lifespan, but I don't need it to live for a long time.

Thanks.

glenfarclas17 commented 7 months ago

Hi there!

The first link you provided - Classic API Authentication Changes - is implemented and handled under the hood: when you use Jamf.cnx.connect it creates both a Jamf Pro and Classic API connection and uses the bearer token from the JP API to communicate with the Classic API as needed.

I have only done preliminary work on the newer "Client Credentials" stuff, but have had other projects taking priority over that work :-/

If you'd like to test what I have so far, I just published my APIRoles-Clients branch to github. From that branch, you only need the files

Grab them from that branch and replace them in your locallly-installed gem.

To use the changes in there, make a new connection using an API client, like this:

Jamf.cnx.connect host: 'myhost.jamfcloud.com', client_id: 'abccb7bc-5e60-4e5f-b894-5d63dca24367', client_secret: 'xyzxyzyxyzyxz'

Then use ruby-jss as normal.

In my early testing in IRB, it seems to be working, but the testing has been very limited.

Please let me know how it goes for you!

Thanks, -Chris

glenfarclas17 commented 6 months ago

This change has been rolled in to v4.0.0b1, which is now available on rubygems.org - Let me know if you have any issues to report!

I probably won't be able to release it until late Jan. since I'll be away for much of mid Jan. and don't want to release a new version just before leaving.

nekrich commented 5 months ago

Chris thanks a lot. I've just tested it, and oauth with client credentials works, but for a very short time. In about a minute or less, it fails with Connection token is not valid. I've prolonged the token lifetime. But is there any retry mechanism?

glenfarclas17 commented 5 months ago

Hmmm I know that API Clients have very short lifespans, usually 30seconds to a few minutes.

I just set my test client to an hour (3600 seconds)

Screenshot 2024-01-23 at 2 30 30 PM

and then did this in IRB:

> client_id = 'a-random-uuid' 
=> 'a-random-uuid' 

> client_sec = 'a-client-secret'
=> 'a-client-secret'

> Time.now
=> 2024-01-23 14:17:24.341632 -0800

> Jamf.cnx.connect client_id: client_id, client_secret: client_sec
=> "api-client-test (API Client)@jamfpro.company.com:8443, name: default"

> Jamf.cnx.token.creation_time
=> 2024-01-23 14:17:27.683233 -0800

> Jamf.cnx.token.expiration
=> 2024-01-23 15:17:25.604917 -0800

> Jamf.cnx.token.expired?
=> false

> Jamf.cnx.token.secs_remaining
=> 3329.19392

> Jamf.cnx.token.time_remaining
=> "55 minutes 24 seconds"

Its now been over 10 minutes since I created the connection and its still functional:

> Jamf::ComputerPrestage.all.size
=> 7

I'll check every few minutes, and I expect it to stay valid until the expiration time in about 50 minutes.

Can you give me any more details about how you're making the connection?

Cheers, -Chris

PS: Changes made to the client in the Jamf Web interface will not affect any existing connection tokens, only newly created ones via Jamf.cnx.connect (for the default connection object) or a_connection = Jamf::APIConnection.new (for individual connection objects)

glenfarclas17 commented 1 week ago

Hi @nekrich !

Just checking in - are you still having problems with this? I've been unable to reproduce what you descibed in your last message.

Cheers! -Chris