sebadob / rauthy

OpenID Connect Single Sign-On Identity & Access Management
https://sebadob.github.io/rauthy/
Apache License 2.0
297 stars 15 forks source link

feedback: Bootstrap permissions #540

Open polarathene opened 3 weeks ago

polarathene commented 3 weeks ago

I have been meaning to write up an issue about this, but still caught up with my backlog elsewhere. I may come back to revise this, but I did want to provide feedback on the current implementation of BOOTSTRAP_API_KEY.

The base64 approach makes sense as an ENV value, but becomes a bit clunky the larger the JSON to encode. Adjusting it while experimenting (due to defaults not being sufficient) also adds a bit of friction.

I was curious if the JSON could be provided directly as a file. In some projects an ENV has a __FILE suffix or detects the value as a filepath to support reading contents from a file instead. Usually it's for secrets that you would prefer to restrict access to (instead of visibility to all processes that can check the ENV).

In this case it's also preferable to not have such a file required to be base64 encoded. While not a major DX issue (I can use the base64 command with a shell script to update an ENV file each time), considering how the feature is limited to only the bootstrap feature, it would be nicer if tweaking the permissions was more seamless to iterate without the base64 roundtrip?

The other feedback I had for this was that the ENV name BOOTSTRAP_API_KEY itself didn't quite reflect what the value represented. In actual usage with the Authorization header we use bootstrap$<secret>. It is more like BOOTSTRAP_API_ACL?

sebadob commented 3 weeks ago

Adjusting it while experimenting (due to defaults not being sufficient) also adds a bit of friction.

What exactly do you mean with it, adjusting / experimenting? Do you mean adjust the proper access rights you need to set to be able to do everything you need, or are you having issues with the JSON structure itself?

I was curious if the JSON could be provided directly as a file. In some projects an ENV has a __FILE suffix or detects the value as a filepath to support reading contents from a file instead. Usually it's for secrets that you would prefer to restrict access to (instead of visibility to all processes that can check the ENV).

That would be very easy of course. It was never necessary so far.

The other feedback I had for this was that the ENV name BOOTSTRAP_API_KEY itself didn't quite reflect what the value represented. In actual usage with the Authorization header we use bootstrap$. It is more like BOOTSTRAP_API_ACL?

The bootstrap$ in front comes from the API Key name itself. This only works, if you actually name the key bootstrap like in the examples. Appending the name to the actual key itself is necessary to be able to do an efficient lookup when you access the API. I had the API Keys inside a custom header in the beginning, which was a bit more clear, but had less compatibility. Sometimes you can only easily modify the Authentication header but not add custom ones.

Also, it is not an ACL. The access rights you are setting there are only valid for this very key. Each key has its own list of fine-grained access rights.


If you want to experiment with it, because you are unsure about the rights you need to set, I suggest to use the Admin UI to do this until you are happy with it. It's a lot easier to modify the values with just the click of a button:
https://sebadob.github.io/rauthy/work/api_keys.html#creating-a-new-api-key

polarathene commented 3 weeks ago

What exactly do you mean with it, adjusting / experimenting? Do you mean adjust the proper access rights you need to set to be able to do everything you need, or are you having issues with the JSON structure itself?

My memory on the concern is a bit vague, it was 2 weeks or so ago. I remember getting the demo setup how I wanted it and then automating the UI steps away via API calls, but those needed additional permissions. There was no export via the UI, nor could I modify the bootstrap permissions IIRC, so I just edited the JSON, base64 encoded again and restarted the container.

I only did that a few times iteratively, I don't have a strong use-case for direct file support avoiding any extra base64 dance if I want to include the JSON as a separate file for an example, rather than commit a large base64 blob in an .env file or compose.yaml.

Feel free to close this issue 👍


The example setup will be intended as minimal reproduction to demonstrate integrating with an IdP, rather than a production guide for rauthy.

For reference, the compose.yaml setup is fairly minimal for rauthy, and besides the BOOTSTRAP_API_KEY value, the only real verbosity/friction for getting a minimal integration demonstrated is the API calls below (which I can minimize further).

These are how I have them presently, when I return to wrap it up I'll share the full reference to my original discussion (where your guidance was much appreciated ❤️ )

Create client ```bash curl --silent --request POST \ --url "${BASE_URL}/auth/v1/clients" \ --header 'Authorization: API-Key bootstrap$twUA2M7RZ8H3FyJHbti2AcMADPDCxDqUKbvi8FDnm3nYidwQx57Wfv6iaVTQynMh' \ --header 'Content-Type: application/json' \ --data '{ "confidential": true, "id": "roundcube", "name": "Webmail Roundcube", "redirect_uris": [ "https://rc.example.localhost/index.php/login/oauth" ] }' ```
Adjust the client config Opt-out of PKCE challenge (not supported) + add `client_credentials` flow: ```bash # Could probably simply with a GET + jq to modify the JSON body to send: curl --silent --request PUT \ --url "${BASE_URL}/auth/v1/clients/roundcube" \ --header 'Authorization: API-Key bootstrap$twUA2M7RZ8H3FyJHbti2AcMADPDCxDqUKbvi8FDnm3nYidwQx57Wfv6iaVTQynMh' \ --header 'Content-Type: application/json' \ --data '{ "id": "roundcube", "name": "Webmail Roundcube", "enabled": true, "confidential": true, "redirect_uris": [ "https://rc.example.localhost/index.php/login/oauth" ], "flows_enabled": [ "authorization_code", "client_credentials", "refresh_token" ], "access_token_alg": "EdDSA", "id_token_alg": "EdDSA", "auth_code_lifetime": 60, "access_token_lifetime": 1800, "scopes": [ "openid", "email", "profile", "groups" ], "default_scopes": [ "openid" ], "force_mfa": false, "client_uri": null, "contacts": null, "challenges": null }' ```
Get client secret ```bash # Slightly awkward way to update client secret for app to query rauthy, # since rauthy does not support providing an externally generated secret. # Non-issue with a real production setup. curl --silent --request POST \ --url "${BASE_URL}/auth/v1/clients/roundcube/secret" \ --header 'Authorization: API-Key bootstrap$twUA2M7RZ8H3FyJHbti2AcMADPDCxDqUKbvi8FDnm3nYidwQx57Wfv6iaVTQynMh' \ | jq -r .secret \ | sed -i -r "s|^(RC_OAUTH2__CLIENT_SECRET=).*|\1$(cat -)|" ./secrets.env ```
sebadob commented 3 weeks ago

My memory on the concern is a bit vague, it was 2 weeks or so ago. I remember getting the demo setup how I wanted it and then automating the UI steps away via API calls, but those needed additional permissions. There was no export via the UI, nor could I modify the bootstrap permissions IIRC, so I just edited the JSON, base64 encoded again and restarted the container.

Okay, got it.
In the docs, the API Key being bootstrapped is just an example, not a default by any means. Which access rights you add in the JSON array heavily depends on what you need to do with it. So from your example, you would want create, read and update for clients. But I guess you figured that out by now, because Rauthy will mention the missing access rights in the error response when they are not sufficient with your currently used API Key.

There is no export function in the UI, that's true. That could be a nice feature in the future. I have a "prettify UI" on the TODO which is one of the bigger leftover TODOs before I can release v1.0.0. Originally I wanted to rebuild the whole UI using Leptos, but I am not absolutely sure yet if it is actually worth all the time, because the current Svelte UI is super efficient and works pretty good. Fine-tuning the current UI and probably migrating to Svelte 5 would be a lot less work. I will do the UI part as soon as I have stabilized and integrated Hiqlite into Rauthy. I can add an export easily, even both in a plain and b64 encoded version.

Btw you don't need to include null values in your PUT client JSON above. If they do not exist at all, Rauthy will assume they are null by default.


edit:

If you are bootstrapping with your API Key and you don't want to use it long term later on, you could simply enable everything for the key and let it expire just 1 hour after the creation. This get's rid of the hassle of setting access rights, but needs a modification of the base64 value with each bootstrap to update the expiry timestamp.
API Keys are forbidden to modify other keys or themselves to prevent things like priviledge escalation, so you would not be able to create a key that can do everything and delete itself. You would need to use the auto-expiry.