Compare commits
11 Commits
3f326b74d6
...
main
Author | SHA1 | Date | |
---|---|---|---|
dd2656e9dd | |||
12fc3ac359 | |||
a4f2149223 | |||
74280d6093 | |||
bae57efaa6 | |||
2835682455 | |||
d0d0a1871d | |||
ce9b07cf50 | |||
98c93ac279 | |||
f4ca0b3f1f | |||
99e968a587 |
@ -5,12 +5,12 @@ steps:
|
||||
- name: publish container
|
||||
image: plugins/docker
|
||||
settings:
|
||||
username:
|
||||
from_secret: docker_reg_username
|
||||
username: autono-bot
|
||||
password:
|
||||
from_secret: docker_reg_passwd
|
||||
repo: decentral1se/keycloak-collective-portal
|
||||
from_secret: git_autonomic_zone_token_autono-bot
|
||||
repo: git.autonomic.zone/autonomic-cooperative/keycloak-collective-portal
|
||||
auto_tag: true
|
||||
registry: git.autonomic.zone
|
||||
trigger:
|
||||
branch:
|
||||
- main
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
||||
*.pyc
|
||||
.env
|
||||
/__pycache__/
|
||||
|
@ -1,9 +1,10 @@
|
||||
FROM python:3.9 as builder
|
||||
FROM python:3.9 AS builder
|
||||
|
||||
COPY . /project
|
||||
WORKDIR /project
|
||||
|
||||
RUN pip install poetry
|
||||
RUN poetry self add poetry-plugin-export
|
||||
RUN poetry export --without-hashes -o requirements.txt -f requirements.txt
|
||||
RUN poetry build --format=wheel
|
||||
RUN cp dist/* /tmp
|
||||
|
36
README.md
36
README.md
@ -27,6 +27,7 @@ No Masters edition of Keycloak.
|
||||
- They are valid for 30 days by default (configurable via `INVITE_TIME_LIMIT`)
|
||||
- Anyone with an invite link can create an account on the Keycloak, so don't share publicly!
|
||||
- There is no access granularity on the account creation implemented yet, so the accounts are "global"
|
||||
- **New**: it is possible to only allow "admins" to log in, see [feature flags](#feature-flags)
|
||||
- Once the user fills in their name, email, password they will receive an email verification mail
|
||||
|
||||
If you want a feature implemented, please open an issue to discuss.
|
||||
@ -43,13 +44,14 @@ your technology stack.
|
||||
|
||||
- Ensure that your `admin-cli` client under your Client settings has the following config:
|
||||
- **Settings tab**:
|
||||
- **Access Type**: `confidential`
|
||||
- **Service Accounts Enabled**: `ON`
|
||||
- **Client authentication**: `ON`
|
||||
- **Service Accounts Roles**: `ON`
|
||||
- **Authentication flow**: Make sure "Standard flow" is checked
|
||||
- **Valid redirect URIs**: `https://{your keycloak-collective-portal domain}/auth/keycloak`
|
||||
- **Scope tab**:
|
||||
- **Full scope allowed**: `OFF`
|
||||
- **Client roles**: Under `realm-management` add `manage-users` and `view-users`
|
||||
- **Service Account Roles tab**:
|
||||
- **Client roles**: Under `realm-management` add `manage-users` and `view-users`
|
||||
- Click "To manage detail and group mappings, click on the username service-account-admin-cli", then "Role mappings", "Assign role", then change the dropdown to "Filter by clients", and add `realm-management:manage-users`, `realm-management:view-users`, `account:manage-account` and `account:view-profile`
|
||||
- Deploy using [`coop-cloud/keycloak-colective-portal`](https://git.autonomic.zone/coop-cloud/keycloak-collective-portal)
|
||||
- See the example [.env.sample](.env.sample) for the configuration available, more documentation will follow soon.
|
||||
|
||||
@ -59,6 +61,32 @@ your technology stack.
|
||||
- Log in with your usual login details
|
||||
- Follow the instructions on the web page to perform administrative actions
|
||||
|
||||
## Feature Flags
|
||||
|
||||
### Only admins can log in
|
||||
|
||||
#### Keycloak
|
||||
|
||||
- Create a new group under `Groups` called `Administrators` (case sensistive!)
|
||||
- Create a new scope under `Client scopes`
|
||||
- Name: `groups`
|
||||
- Type: `Optional`
|
||||
- Include in token scope: `yes`
|
||||
- Under the `Mappers` tab of this client scope, choose `Add mapper`
|
||||
- Mapper type/Name: `Groups Membership`
|
||||
- Token claim name: `groups`
|
||||
- Add to ID token: `yes`
|
||||
- Add to access token: `yes`
|
||||
- Add to userinfo: `yes`
|
||||
- Add this client scope to your `admin-cli` client as `Optional`
|
||||
- Add a test user to this group under `Users`
|
||||
|
||||
#### Keycloak Community Portal
|
||||
|
||||
- Set `FEATURE_FLAG_ADMINS_ONLY=True` in your `.env`
|
||||
- You may want to customise `KEYCLOAK_GROUPS_KEY` / `KEYCLOAK_ADMINS_GROUP` if
|
||||
you changed the value of `groups` / `Administrators` above
|
||||
|
||||
## Hacking
|
||||
|
||||
It's a [FastAPI](https://fastapi.tiangolo.com/) application (if you know
|
||||
|
@ -12,8 +12,10 @@ KEYCLOAK_CLIENT_ID = environ.get("KEYCLOAK_CLIENT_ID")
|
||||
KEYCLOAK_CLIENT_SECRET = environ.get("KEYCLOAK_CLIENT_SECRET")
|
||||
KEYCLOAK_DOMAIN = environ.get("KEYCLOAK_DOMAIN")
|
||||
KEYCLOAK_REALM = environ.get("KEYCLOAK_REALM")
|
||||
KEYCLOAK_SCOPES = environ.get("KEYCLOAK_SCOPES", "openid profile email")
|
||||
KEYCLOAK_BASE_URL = f"https://{KEYCLOAK_DOMAIN}/auth/realms/{KEYCLOAK_REALM}/protocol/openid-connect" # noqa
|
||||
KEYCLOAK_SCOPES = environ.get("KEYCLOAK_SCOPES", "openid profile email groups")
|
||||
KEYCLOAK_GROUPS_KEY = environ.get("KEYCLOAK_GROUPS_KEY", "groups")
|
||||
KEYCLOAK_ADMINS_GROUP = environ.get("KEYCLOAK_ADMINS_GROUP", "Administrators")
|
||||
KEYCLOAK_BASE_URL = f"https://{KEYCLOAK_DOMAIN}/realms/{KEYCLOAK_REALM}/protocol/openid-connect" # noqa
|
||||
|
||||
# Redis connection details, our main storage
|
||||
REDIS_DB = environ.get("REDIS_DB")
|
||||
@ -39,5 +41,15 @@ elif LOG_LEVEL == "debug":
|
||||
else:
|
||||
APP_LOG_LEVEL = logging.INFO
|
||||
|
||||
|
||||
def to_bool(env_var):
|
||||
"""Parse a bool from the environment."""
|
||||
return environ.get(env_var, "False").lower() in ("true", "1", "t")
|
||||
|
||||
|
||||
# Automatically log folks in or show the default log in page?
|
||||
AUTOMATICALLY_LOG_IN = environ.get("AUTOMATICALLY_LOG_IN", False)
|
||||
AUTOMATICALLY_LOG_IN = to_bool("AUTOMATICALLY_LOG_IN")
|
||||
|
||||
# Feature flags
|
||||
# Only admins can log in to the interface
|
||||
FEATURE_FLAG_ADMINS_ONLY = to_bool("FEATURE_FLAG_ADMINS_ONLY")
|
||||
|
@ -12,7 +12,7 @@ def init_keycloak():
|
||||
)
|
||||
|
||||
client = KeycloakAdmin(
|
||||
server_url=f"https://{KEYCLOAK_DOMAIN}/auth/",
|
||||
server_url=f"https://{KEYCLOAK_DOMAIN}",
|
||||
realm_name=KEYCLOAK_REALM,
|
||||
client_secret_key=KEYCLOAK_CLIENT_SECRET,
|
||||
verify=True,
|
||||
|
@ -15,7 +15,26 @@ router = APIRouter()
|
||||
async def home(
|
||||
request: Request, user=Depends(get_user), invites=Depends(get_invites)
|
||||
):
|
||||
from keycloak_collective_portal.config import (
|
||||
FEATURE_FLAG_ADMINS_ONLY,
|
||||
KEYCLOAK_ADMINS_GROUP,
|
||||
KEYCLOAK_GROUPS_KEY,
|
||||
)
|
||||
|
||||
context = {"request": request, "user": user, "invites": invites}
|
||||
|
||||
if FEATURE_FLAG_ADMINS_ONLY:
|
||||
context["message"] = "only admins can access this service"
|
||||
if KEYCLOAK_GROUPS_KEY not in user:
|
||||
return request.app.state.templates.TemplateResponse(
|
||||
"invalid.html", context=context
|
||||
)
|
||||
|
||||
if KEYCLOAK_ADMINS_GROUP not in user[KEYCLOAK_GROUPS_KEY]:
|
||||
return request.app.state.templates.TemplateResponse(
|
||||
"invalid.html", context=context
|
||||
)
|
||||
|
||||
return request.app.state.templates.TemplateResponse(
|
||||
"admin.html", context=context
|
||||
)
|
||||
|
Reference in New Issue
Block a user