Skip to content

Conversation

@KavanPrice
Copy link
Contributor

This adds an OAuth mechanism to ACS with Kerberos integration.

  • Defines "OpenID" deployment and service
  • Defines IngressRoute for the service
  • Creates a ConfigMap for a basic startup realm
    • Realm name: "factory_plus"
    • Realm clients:
      • grafana-oauth
    • Realm user federation:
      • Kerberos
  • Adds the auth.generic_oauth section to grafana.ini

Only the client for the Grafana service is implemented here.

@KavanPrice
Copy link
Contributor Author

  • Removed secret lookup and helm templating from Values
  • Add service setup step for
    • Blank realm creation with Kerberos support
    • Dynamic client creation for clients defined in Values
  • Remove realm-config monolith

client_representation.redirectHost,
);
const content = await fs.readFile(secret_path, "utf8");
const client_secret = content.trim();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any way to configure Keycloak to read the secret from its own filesystem at runtime, rather than reading the file contents here? This would be more reliable against the secret being updated. (In principle we should rotate all our secrets regularly.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A second container on the keycloak pod that called into the API to update the secrets every hour would also be a reasonable solution.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm looking at this. There are apparently ways of making it read a secret from a vault. Simplest solution might be, as you suggested, a container that just updates the secrets

@amrc-benmorrow amrc-benmorrow linked an issue Mar 31, 2025 that may be closed by this pull request
KavanPrice and others added 26 commits April 1, 2025 00:16
The code was becoming very tangled and difficult to follow with
duplicated retry logic everywhere.
The list might have changed from last time. We don't attempt to delete
old roles at this point, this is for the user to handle if necessary.
This is a client secret like any other; it needs to be preserved across
ACS upgrades, and so needs to come from a LocalSecret.
I'm getting weird 400 errors from this method and I wasn't sure if this was
the cause. But apparently not...
This was giving a really unhelpful (and incorrect) 400 error.
Because a Request can contain a ReadableStream body we need to clone it
to reuse it.
I am having a lot of trouble creating the admin@ user account; Keycloak
keeps returning 409 even though it later denies the account exists. I am
wondering if this is because of a conflict with the initial 'temporary'
bootstrap account username. Rename to avoid this; at the same time
change the password, this isn't linked to admin@ any more.
The Keycloak user-create endpoint is consistently returning 409 when we
attempt to create an account for the admin user. I think this may be
because we have federation set up to Kerberos and Keycloak refuses to
support non-Kerberos users in this realm. IMHO this is desirable in any
case.

We don't have a real human driving to perform the first-login flow, so
go round the houses a bit. First we request a token 'on behalf of'
admin@; this will fail because we haven't set up the profile, but will
create the user on the Keycloak side. Then we can go in with our user
management credentials and finish the setup.
The `available` endpoint only returns roles which the user is not
already assigned to. We need to check existing assignments first.
This should now be configured via OpenID.
If we don't specify an admin account secret Grafana generates one with
the username `admin`, which conflicts with the Kerberos account we are
trying to use via OpenID. Replace the Secret but change the username and
give it a password. It won't be possible to log in as this user in any
case as the login dialog is disabled.
It seems like the only way to have the default install set up admin@ as
a Grafana admin is for Grafana to defer to Keycloak completely for role
information. This means that admin@ must also be able to manage the
roles assigned to other OpenID users; this information can no longer be
managed in Grafana.

* Allow assigning multiple default and admin roles.
* Allow assigning roles within builtin clients.
* Assign admin@ the roles needed to be a realm admin in Keycloak.
* Consistently use the key in openidClients as client ID.
I'm guessing at this point; none of this appears to be documented. The
Grafana documentation doesn't mention needing this but it's not working
without, so try changing `claim.name` to the `roles` which I think
Grafana is expecting.
Confusingly, this is not the `clientId` field but the `id` field. This
is a generated UUID for `realm-management`.
@amrc-benmorrow amrc-benmorrow changed the title Kp/add oauth Deploy Keycloak as an OAuth provider Apr 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Proposal: Add OAuth2 Support to Auth Service

4 participants