Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Does not appear to support SSO based users #8

Open
ttripp opened this issue Jun 12, 2020 · 17 comments
Open

Does not appear to support SSO based users #8

ttripp opened this issue Jun 12, 2020 · 17 comments

Comments

@ttripp
Copy link

ttripp commented Jun 12, 2020

Based on the API documentation, the only way to retrieve an access token is by username and password. We've enabled morpheus with a SAML IDP. It does not look like SSO based access is supported via API and CLI:

Is there a way to get an access token for SSO users?

@jamesdickson6
Copy link
Contributor

@ttripp Can you try authenticating with a domain prefix that identifies the account?
The format of the username parameter value is: subdomain\username
This subdomain prefix is required when authenticating as a user in a sub tenant (account), meaning an account other than the master tenant, though it may also be required when a Identity Source is used with master tenant.

The subdomain can be set for each Morpheus tenant. The default subdomain value is the tenant ID, so if your identity source is for the master tenant, it will be 1 and the full username passed would be: 1\ttripp.
Alternatively. you can set the subdomain by editing the Tenant in the UI or the API.

Let me know if that resolves your problem.

Thanks!
-James

@ttripp
Copy link
Author

ttripp commented Jun 22, 2020

I tried, but this doesn't seem to resolve the problem. This issue is that this tenant has an identity source that is an external identity provider. E.g.

  • Administration -> Tenants -> -> Identity Sources -> Add Identity Source -> SAML SSO

When we log into this account via the UI, we provide the account in the URL. E.g. https:/<IP_ADDRESS>/login/account/2. This presents us a screen where we can choose the identity provider to login with "Login With". We see our SAML provider, click on it, it redirects us to the SAML based IDP where we login and then the IDP sends the SAML back to Morpheus which logs us in.

I don't see any similar kind of a flow happening with the CLI. Is this supported?

I tried setting subdomain of 2\username and I saw that in settings we had a name for the subdomain, so I tried that \username.

I also tried setting up a remote with that, but it didn't work.

   NAME                  | URL                                                        | STATUS     | VERSION |
------------------|--------------------------------------|------------|----------|
   saml-account-2 | https://<IP>/login/account/2 | HTTP ERROR |         |          | 
=> saml-direct    | https://<IP>                 | READY      | 4.2.1   |          | 

@jamesdickson6
Copy link
Contributor

I see. The remote URL in the CLI will always be formatted without any path, like the saml-direct one you are using there.
So, the username you specified, 2\username SHOULD work.
Can I see the CLI command you are running and the error you are getting?
Note that if you are passing the password as a command line argument, you need two baskslashes, since it is an escape character, like this: morpheus login "2\\username"

@ttripp
Copy link
Author

ttripp commented Jun 22, 2020

Note that our Morpheus install has several SAML identity sources if that makes a difference.

Here are a series of logins. The very first one is demonstrating that a local user (non SAML) user is able to login. Then I show using 2\ 2\ \ \

$ morpheus login --debug
establishing connection to remote [travis-saml-direct] https://<IP-REDACTED>
Enter Morpheus Credentials for [travis-saml-direct] https://<IP-REDACTED>
Username: | localuser
Password: |
POST "https://<IP-REDACTED>/oauth/token?grant_type=password&scope=write&client_id=morph-cli&username=localuser", "password=************", "Accept"=>"*/*", "Accept-Encoding"=>"gzip, deflate", "Content-Length"=>"21", "Content-Type"=>"application/x-www-form-urlencoded", "User-Agent"=>"morpheus-cli 4.2.15 (darwin19.4.0 x86_64) ruby/2.7.1p83"
# => 200 OK | application/json 170 bytes
Success! Logged in as localuser
$ morpheus logout
Logged out of travis-saml-direct. Goodbye localuser!

$ morpheus login
Enter Morpheus Credentials for [travis-saml-direct] https://<IP-REDACTED>
Username: | [email protected]
Password: |
Bad credentials


$ morpheus login --debug
establishing connection to remote [travis-saml-direct] https://<IP-REDACTED>
Enter Morpheus Credentials for [travis-saml-direct] https://<IP-REDACTED>
Username: | [email protected]
Password: |
POST "https://<IP-REDACTED>/oauth/token?grant_type=password&scope=write&client_id=morph-cli&username=saml-user%40redacted-domain.com", "password=************", "Accept"=>"*/*", "Accept-Encoding"=>"gzip, deflate", "Content-Length"=>"32", "Content-Type"=>"application/x-www-form-urlencoded", "User-Agent"=>"morpheus-cli 4.2.15 (darwin19.4.0 x86_64) ruby/2.7.1p83"
# => 400 BadRequest | application/json 63 bytes
Bad credentials

$ morpheus login --debug
establishing connection to remote [travis-saml-direct] https://<IP-REDACTED>
Enter Morpheus Credentials for [travis-saml-direct] https://<IP-REDACTED>
Username: | 2\[email protected]
Password: |
POST "https://<IP-REDACTED>/oauth/token?grant_type=password&scope=write&client_id=morph-cli&username=2%5Csaml-user%40redacted-domain.com", "password=************", "Accept"=>"*/*", "Accept-Encoding"=>"gzip, deflate", "Content-Length"=>"32", "Content-Type"=>"application/x-www-form-urlencoded", "User-Agent"=>"morpheus-cli 4.2.15 (darwin19.4.0 x86_64) ruby/2.7.1p83"
# => 400 BadRequest | application/json 63 bytes
Bad credentials

$ morpheus login --debug
establishing connection to remote [travis-saml-direct] https://<IP-REDACTED>
Enter Morpheus Credentials for [travis-saml-direct] https://<IP-REDACTED>
Username: | <redacted-subdomain>\[email protected]
Password: |
POST "https://<IP-REDACTED>/oauth/token?grant_type=password&scope=write&client_id=morph-cli&username=<redacted-subdomain>%5Csaml-user%40redacted-domain.com", "password=************", "Accept"=>"*/*", "Accept-Encoding"=>"gzip, deflate", "Content-Length"=>"32", "Content-Type"=>"application/x-www-form-urlencoded", "User-Agent"=>"morpheus-cli 4.2.15 (darwin19.4.0 x86_64) ruby/2.7.1p83"
# => 400 BadRequest | application/json 63 bytes
Bad credentials

$ morpheus login --debug  --"2\\[email protected]"
morpheus: invalid option: --2\[email protected]
Use -h to get help with this command.

$ morpheus login --debug  "2\\[email protected]"
establishing connection to remote [travis-saml-direct] https://<IP-REDACTED>
Enter Morpheus Credentials for [travis-saml-direct] https://<IP-REDACTED>
Username: | 2\[email protected]
Password: |
POST "https://<IP-REDACTED>/oauth/token?grant_type=password&scope=write&client_id=morph-cli&username=2%5Csaml-user%40redacted-domain.com", "password=************", "Accept"=>"*/*", "Accept-Encoding"=>"gzip, deflate", "Content-Length"=>"32", "Content-Type"=>"application/x-www-form-urlencoded", "User-Agent"=>"morpheus-cli 4.2.15 (darwin19.4.0 x86_64) ruby/2.7.1p83"
# => 400 BadRequest | application/json 63 bytes
Bad credentials

$ morpheus login --debug  "<redacted-subdomain>\\[email protected]"
establishing connection to remote [travis-saml-direct] https://<IP-REDACTED>
Enter Morpheus Credentials for [travis-saml-direct] https://<IP-REDACTED>
Username: | <redacted-subdomain>\[email protected]
Password: |
POST "https://<IP-REDACTED>/oauth/token?grant_type=password&scope=write&client_id=morph-cli&username=<redacted-subdomain>%5Csaml-user%40redacted-domain.com", "password=************", "Accept"=>"*/*", "Accept-Encoding"=>"gzip, deflate", "Content-Length"=>"32", "Content-Type"=>"application/x-www-form-urlencoded", "User-Agent"=>"morpheus-cli 4.2.15 (darwin19.4.0 x86_64) ruby/2.7.1p83"
# => 400 BadRequest | application/json 63 bytes
Bad credentials

I believe this should be doing a SAML redirect flow and opening a browser window where the user signs in and then redirects back to Morpheus to complete the login flow in order to work properly with an SSO provider. Instead, this is attempting to directly do the oauth with password grant flow where it expects to take in the user's password directly.

Here's an OIDC example:

https://medium.com/@balaajanthan/openid-flow-from-a-cli-ac45de876ead

@jamesdickson6
Copy link
Contributor

Ah ok. It sounds like requiring authentication with redirect is not going to work for API use. I thought that was only the case when the SAML 's forceAuthn=true was in use.
Also, just for the sake of sanity, note that you need not pass multiple backslashes when being prompted by Morpheus like in your example, only if you were passing the value in from bash or some other terminal. You probably already did but I would verify that your tenant does not have a subdomain set. morpheus get 2 will show Subdomain, in which case you must use that instead of 2 in your username prefix.

@jamesdickson6
Copy link
Contributor

jamesdickson6 commented Jun 22, 2020

@ttripp After looking closer at this, I think your use case (that authentication model) is one we don't yet support with the API. It should be available in a near future release though.

@ttripp
Copy link
Author

ttripp commented Jun 22, 2020

@jamesdickson6 The command you mentioned doesn't work:

$ morpheus get 2
morpheus: 'get' is not a morpheus command.
Use -h to get help with this command

@jamesdickson6
Copy link
Contributor

Oops! It should have read morpheus tenants get 2

@ttripp
Copy link
Author

ttripp commented Jun 22, 2020

Ok, here it is:

$ morpheus tenants get 2

Tenant Details
==================
       ID: 2
       Name: <redacted>
       Description: A tenant user
       Subdomain: <REDACTED>
       Currency: USD
       Created: 11/25/19 12:47 AM
       Updated: 01/02/20 12:09 AM
       Status: ACTIVE

Do you have a timeline when this will be supported? It seems that your API first needs to support it.

Also, do you have an OpenAPI 3.0 (Swagger) version of your API docs available instead of just the hosted HTML version?

@jamesdickson6
Copy link
Contributor

That's right, it will be an API enhancement first.
There's no swagger doc for the API right now. However that is something that gets asked for quite a lot and is on the roadmap to add.

I don't have an exact timeline for either of these, but I expect it might be done in the next release cycle or two (1-2months).
I'll remember to update this issue accordingly. Let me know if I can assist with anything in the meantime.

Cheers,
James

@ttripp
Copy link
Author

ttripp commented Jun 22, 2020

Another question, is there a way to supply an access token to the CLI instead of doing interactive login? My thought is that in the meantime, I could write a wrapper service that logs the user in via SSO, then generate an access token with a username and password I control and just supply the access token to the CLI rather than giving them direct access to the local account.

@jamesdickson6
Copy link
Contributor

jamesdickson6 commented Jun 22, 2020

That's a pretty good idea.
Yes, you create a CLI session with just a token like this: morpheus login --token YOUR_TOKEN.
In this case, the cli just validates the provided token by attempting a request to /api/whoami.
Though it's important to note that the morpheus access tokens do have an expiration, and will be invalid after 365 days.

@ttripp
Copy link
Author

ttripp commented Jun 22, 2020

Thanks @jamesdickson6 Is there an API to revoke / invalidate the token?

@jamesdickson6
Copy link
Contributor

jamesdickson6 commented Jun 22, 2020

No problem, happy to help.
Yes, there is a User Settings API that can be used to clear/regenerate tokens for each of the available client_ids. A master tenant user is able to do this for any user, but by default it operates on your own user.
This corresponding CLI command to clear the users' cli token looks like this: morpheus user-settings clear-access-token morph-cli --user-id ID.
The CLI and perhaps the API should be improved to allow the passing of a username in place of an ID here, just for the convenience. For now you can lookup the User ID with the users api like this: users list and users get jdoe. The users API is scoped by tenant so if it's a sub tenant user you need to pass the tenant the user is under, like this users list -A 2 and users get jdoe -A 2. I should note that 'account' is the same thing as 'tenant', as seen in the documentation and parameter names.

@jamesdickson6
Copy link
Contributor

@ttripp I did terrible proofreading on that last comment and had to edit a few things so, as always, just let me know if you have any questions or issues.

@ttripp
Copy link
Author

ttripp commented Jun 22, 2020

Thanks, @jamesdickson6 I'll look at this to see if it is a reasonable workaround in the short term. Looking forward to OpenAPI and true SSO login for the API.

@ttripp
Copy link
Author

ttripp commented Jun 15, 2021

Following up on this. Have there been any updates to morpheus API to support true SSO login for the API?

As a reminder, if we have a SAML or OIDC trust relationship from Morpheus to our IDP we would like to be able to get API tokens issued for morpheus that

  • have access rights for the SSO user based on that user's claims
  • are audited as that user

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants