diff --git a/README.md b/README.md index 0e6afb1..de7bd18 100644 --- a/README.md +++ b/README.md @@ -26,21 +26,19 @@ The Grafana Organizations Operator does not differentiate between organization a This information is translated into Grafana organizations, users and organization users ("permissions" a user has on an organization). -The Grafana Organizations Operator only cares about organizations present in Keycloak (plus `auto_assign_org_id`). This allows other Organizations in Grafana to exist without being touched; but it also means that it will not clean up organizations in Grafana which have been deleted in Keycloak. - -### Issues with the Keycloak API - -* The Keycloak LDAP integration is [buggy when it comes to listing members of a group](https://github.com/keycloak/keycloak/issues/10348) (API endpoint `/auth/admin/realms/[REALM]/groups/[ID]/members`). This would not be an issue for the organization users but it is an issue for the `KEYCLOAK_ADMIN_GROUP_PATH` which may come from LDAP. As a workaround we fetch the group memberships of users instead, however this means one HTTP call per user (easily 100s of HTTP calls). -* The operator assumes that all Grafana organizations are in the root group `/organizations` +The Grafana Organizations Operator deletes all Grafana organizations that aren't present Keycloak (except `auto_assign_org_id`). ### Issues with Grafana -* When a user is created in Grafana, Grafana's `auto_assign_org` "feature" automatically gives the user permission to some organization (whichever is configured). This is almost never what we want. To work around this: +* Grafana likes to wipe all organization permissions of the user upon OAuth login. There is a configuration which prevents this: + * `role_attribute_path: Deny` to not give the user signing in any permissions + * `role_attribute_strict: false` to allow users without permissions to log in + * `skip_org_role_sync: true` to make it possible to configure permissions via the UI (may not be absolutely required since we change permissions via API, but we set this for good measure). +* When a user is created in Grafana, Grafana's `auto_assign_org` "feature" automatically gives the user permission to the configured organization. This is almost never what we want. To work around this: * It would be possible to disable `auto_assign_org`, but then Grafana would create a new organization for every new user, which would be even worse. - * We can't create the user and assign the correct permissions before the user logs in for the first time, because upon oauth login Grafana resets all permissions. + * We could create the user and assign the correct permissions before the user logs in for the first time, but that would mean having 1000s of users in Grafana which are never used. * Therefore we just fix permissions after the user has been created by Grafana. This leaves a time gap during which the user can have permissions he shouldn't have, but there isn't much we can do against that. * A possible improvement would be to configure Grafana such that `auto_assign_org_id` points to a completely empty org, that way the invalid permissions wouldn't matter, but this isn't something this operator can configure. -* Grafana may make it impossible in the future to change permissions of OAuth users via the API. Today it is already impossible via the UI. This would break the operator in its current form entirely. * Because the `grafana-api-golang-client` implementation is incomplete we are wrapping it in the GrafanaClient type and add some functionality. * The Grafana API often ignores the OrgID JSON field. The only workaround for this is to set the HTTP header `x-grafana-org-id`. The GrafanaClient wrapper takes care of this. @@ -65,7 +63,7 @@ You can run the `gen-dev-env.sh` to set up an environment file (`env`) with the Once that's done you can source the env file (`. ./env`) and run the operator on your local machine using `go run .`. -Note that by default the operator will not sync any users, as it expects the users to be created by Grafana first. You can simulate this by manually creating a user in Grafana using the `admin` account. +Note that by default the operator will not sync any users, as it expects the users to be created by Grafana first. ## License