mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-09-20 13:30:46 +02:00
add keycloak integration
@@ -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/<realm>`
|
||||
- JWKS (certs): `https://KEYCLOAK/realms/<realm>/protocol/openid-connect/certs`
|
||||
- UserInfo: `https://KEYCLOAK/realms/<realm>/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": "<optional-if-confidential>",
|
||||
"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.
|
||||
+1
@@ -91,6 +91,7 @@
|
||||
### AWS IAM
|
||||
* [[Amazon IAM API]]
|
||||
* [[AWS IAM CLI]]
|
||||
* [[Keycloak Integration]]
|
||||
|
||||
### Machine Learning
|
||||
* [[TensorFlow with SeaweedFS]]
|
||||
|
||||
Reference in New Issue
Block a user