diff --git a/Keycloak-Integration.md b/Keycloak-Integration.md new file mode 100644 index 0000000..645375e --- /dev/null +++ b/Keycloak-Integration.md @@ -0,0 +1,187 @@ +# Keycloak Integration (OIDC) with SeaweedFS S3 Gateway + +This guide shows how to integrate Keycloak (OpenID Connect) with SeaweedFS S3 Gateway using the advanced IAM and STS configuration. It supports both: + +- Direct OIDC authentication to S3 with Bearer tokens +- OIDC to STS role assumption using trust policies and role mapping + +## Prerequisites + +- A running Keycloak server and a realm (e.g. `seaweedfs`) +- A Keycloak client (e.g. `seaweedfs-s3`) created in that realm +- SeaweedFS with advanced IAM enabled via `-iam.config` + +## Step 1: Configure Keycloak + +1) Create a client +- Client ID: `seaweedfs-s3` +- Access Type: public or confidential (confidential requires a client secret) +- Standard Flow: enabled (for browser login flows) + +2) Add role/group claims to tokens +- Add a mapper of type "Group Membership" or "User Realm Role" that puts roles/groups into a top-level claim: + - Claim name: `groups` (recommended) or `roles` + - Add to ID token: true + - Add to Access token: true + +3) Confirm OIDC discovery +- Open your realm discovery document and note the issuer and certs endpoints (Keycloak Quarkus defaults): + - Issuer: `https://KEYCLOAK/realms/` + - JWKS (certs): `https://KEYCLOAK/realms//protocol/openid-connect/certs` + - UserInfo: `https://KEYCLOAK/realms//protocol/openid-connect/userinfo` + +Note: For older Keycloak distributions, issuer may include `/auth` in the path. + +## Step 2: Prepare SeaweedFS IAM config + +Create an IAM configuration JSON file (e.g. `/etc/seaweed/iam_keycloak.json`) and reference it with `weed s3 -iam.config=...`. + +Minimal example with Keycloak OIDC provider, role mapping, roles, and policies: + +```json +{ + "sts": { + "tokenDuration": "1h", + "maxSessionLength": "12h", + "issuer": "seaweedfs-sts", + "signingKey": "c2Vhd2VlZGZzLXNpZ25pbmcta2V5LTMyLWNoYXJzLWxvbmc=" + }, + "providers": [ + { + "name": "keycloak", + "type": "oidc", + "enabled": true, + "config": { + "issuer": "https://KEYCLOAK/realms/seaweedfs", + "clientId": "seaweedfs-s3", + "clientSecret": "", + "jwksUri": "https://KEYCLOAK/realms/seaweedfs/protocol/openid-connect/certs", + "userInfoUri": "https://KEYCLOAK/realms/seaweedfs/protocol/openid-connect/userinfo", + "scopes": ["openid", "profile", "email", "roles", "groups"], + "roleMapping": { + "rules": [ + { "claim": "groups", "value": "admins", "role": "arn:seaweed:iam::role/S3AdminRole" }, + { "claim": "groups", "value": "developers", "role": "arn:seaweed:iam::role/S3WriteRole" } + ], + "defaultRole": "arn:seaweed:iam::role/S3ReadOnlyRole" + } + } + } + ], + "policies": [ + { + "name": "S3ReadOnlyPolicy", + "document": { + "Version": "2012-10-17", + "Statement": [ + { "Effect": "Allow", "Action": ["s3:List*", "s3:Get*"], "Resource": ["*"] } + ] + } + }, + { + "name": "S3WritePolicy", + "document": { + "Version": "2012-10-17", + "Statement": [ + { "Effect": "Allow", "Action": ["s3:List*", "s3:Get*", "s3:Put*", "s3:DeleteObject"], "Resource": ["*"] } + ] + } + }, + { + "name": "S3AdminPolicy", + "document": { + "Version": "2012-10-17", + "Statement": [ + { "Effect": "Allow", "Action": ["s3:*"] , "Resource": ["*"] } + ] + } + } + ], + "roles": [ + { + "roleName": "S3ReadOnlyRole", + "roleArn": "arn:seaweed:iam::role/S3ReadOnlyRole", + "attachedPolicies": ["S3ReadOnlyPolicy"], + "trustPolicy": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { "Federated": "*" }, + "Action": ["sts:AssumeRoleWithWebIdentity"], + "Condition": { + "StringEquals": { "seaweed:Issuer": "https://KEYCLOAK/realms/seaweedfs" } + } + } + ] + } + }, + { + "roleName": "S3WriteRole", + "roleArn": "arn:seaweed:iam::role/S3WriteRole", + "attachedPolicies": ["S3WritePolicy"], + "trustPolicy": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { "Federated": "*" }, + "Action": ["sts:AssumeRoleWithWebIdentity"], + "Condition": { + "StringEquals": { "seaweed:Issuer": "https://KEYCLOAK/realms/seaweedfs" } + } + } + ] + } + }, + { + "roleName": "S3AdminRole", + "roleArn": "arn:seaweed:iam::role/S3AdminRole", + "attachedPolicies": ["S3AdminPolicy"], + "trustPolicy": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { "Federated": "*" }, + "Action": ["sts:AssumeRoleWithWebIdentity"], + "Condition": { + "StringEquals": { "seaweed:Issuer": "https://KEYCLOAK/realms/seaweedfs" } + } + } + ] + } + } + ] +} +``` + +Notes: +- Set `signingKey` to a strong random secret (base64-encoded 32+ bytes). All S3 gateway instances must share the same STS `issuer` and `signingKey`. +- Explicit `jwksUri` and `userInfoUri` are recommended for Keycloak. +- Ensure your Keycloak mappers populate a top-level `groups` (or `roles`) claim. + +## Step 3: Start the S3 Gateway + +```bash +weed s3 -filer=filer:8888 -port=8333 -iam.config=/etc/seaweed/iam_keycloak.json +``` + +For multi-instance deployments, use the same IAM config on each instance. + +## Using It + +- Direct OIDC to S3 (Bearer): obtain a Keycloak access or ID token for client `seaweedfs-s3` and call S3 with: + +```bash +curl -H "Authorization: Bearer $KEYCLOAK_TOKEN" http://s3-gateway:8333/ +``` + +- Role selection: SeaweedFS maps OIDC claims via `roleMapping`. With the example above, users in `admins` get `S3AdminRole`, `developers` get `S3WriteRole`, others default to `S3ReadOnlyRole`. + +## Troubleshooting + +- Invalid token: verify token `iss` equals the configured provider `issuer` and `aud` or `azp` equals the client ID. +- JWKS errors: ensure `jwksUri` is reachable from the S3 gateway. For Keycloak, use the `.../protocol/openid-connect/certs` endpoint. +- No roles applied: confirm Keycloak mapper emits `groups` (or `roles`) at top-level in the token, and adjust `roleMapping` rules accordingly. +- Trust policy denied: ensure `seaweed:Issuer` in the trust policy matches your Keycloak realm issuer exactly. diff --git a/_Sidebar.md b/_Sidebar.md index 609f078..9d0656e 100644 --- a/_Sidebar.md +++ b/_Sidebar.md @@ -91,6 +91,7 @@ ### AWS IAM * [[Amazon IAM API]] * [[AWS IAM CLI]] +* [[Keycloak Integration]] ### Machine Learning * [[TensorFlow with SeaweedFS]]