feat: Bootstrapping admin password and API key, and API commands #16
21
.env.sample
@ -28,3 +28,24 @@ SECRET_HQL_API_VERSION=v1
|
||||
#SMTP_USERNAME=
|
||||
#SECRET_SMTP_PASSWORD_VERSION=v1
|
||||
#SMTP_STARTTLS_ONLY=true
|
||||
|
||||
# Bootstrap admin account (only on first deploy)
|
||||
# Generate admin bootstrap hash: abra app cmd --local generate_bootstrap_admin_password
|
||||
#COMPOSE_FILE="$COMPOSE_FILE:compose.bootstrapadmin.yml"
|
||||
#SECRET_ADMIN_PWHASH_VERSION=v1 # generate=false
|
||||
|
||||
# API key
|
||||
# When set before first deploy, rauthy will bootstrap an API key with the Base64 encoded JSON access rights.
|
||||
|
decentral1se marked this conversation as resolved
Outdated
|
||||
# After first deploy, api_secret is also used by abra.sh functions (create_clients, create_groups)
|
||||
#COMPOSE_FILE="$COMPOSE_FILE:compose.api.yml"
|
||||
#SECRET_API_SECRET_VERSION=v1 # length=64
|
||||
|
||||
|
dannygroenewegen marked this conversation as resolved
Outdated
decentral1se
commented
I would do I would do `BOOTSTRAP_API_KEY=` to drop the example which just needs to be deleted by every operator in the `.env` who uses it? If you want to include an example of a encoded key, that can be done in the `README.md`?
dannygroenewegen
commented
I used the same naming as Rauthy internally uses and API_KEY is a bit confusing since it's not really a key. From your comment, I'm not sure if you might also be assuming it's a secret, so ignore the following if you got that part: The value in API_KEY is a Base64 encoded JSON with the access rights that should be given to the API key that will be bootstrapped. The value I put here is Base64 of api.key.example.json, which is read and create rights for clients, groups and roles. Basically, the minimal access rights you need for using the provided abra.sh functions. I feel that's a fair value to put as default? But also happy to put it in the readme if it's confusing to have something here that looks like a secret? Another option would be to rename this to e.g. API_BASE64_ACCESS_RIGHTS. Maybe that avoids the confusion of thinking it's a default key? Then it's named differently from Rauthy's own naming, but if you get to that layer, you can probably unconfuse yourself with the docs. I used the same naming as Rauthy internally uses and API_KEY is a bit confusing since it's not really a key. From your comment, I'm not sure if you might also be assuming it's a secret, so ignore the following if you got that part: The value in API_KEY is a Base64 encoded JSON with the access rights that should be given to the API key that will be bootstrapped.
The value I put here is Base64 of api.key.example.json, which is read and create rights for clients, groups and roles. Basically, the minimal access rights you need for using the provided abra.sh functions. I feel that's a fair value to put as default? But also happy to put it in the readme if it's confusing to have something here that looks like a secret?
Another option would be to rename this to e.g. API_BASE64_ACCESS_RIGHTS. Maybe that avoids the confusion of thinking it's a default key? Then it's named differently from Rauthy's own naming, but if you get to that layer, you can probably unconfuse yourself with the docs.
3wordchant
commented
@dannygroenewegen I think moving the explanatory comment one line down could help clarify that
This also seems fine; maybe putting a comment that it's set to Fine with whichever solution though really. @dannygroenewegen I think moving the explanatory comment one line down could help clarify that `ewog...` _is_ the "read and create rights…" default.
> Another option would be to rename this to e.g. API_BASE64_ACCESS_RIGHTS.
This also seems fine; maybe putting a comment that it's set to `BOOTSTRAP_API_KEY` could help avoid the naming-change confusion?
Fine with whichever solution though really.
dannygroenewegen
commented
Good ideas. I will move the comment and rename the env. And want to test again afterwards, might take one or two weeks because of holidays. Good ideas. I will move the comment and rename the env. And want to test again afterwards, might take one or two weeks because of holidays.
|
||||
# Default value for API_BASE64_ACCESS (ewog...) is read and create rights on Clients, Roles and Groups. See file api.key.example.json and https://sebadob.github.io/rauthy/config/bootstrap.html#api-key
|
||||
# In rauthy this value is stored in the config as API_KEY
|
||||
#API_BASE64_ACCESS_RIGHTS="ewogICJuYW1lIjoiYm9vdHN0cmFwIiwKICAiZXhwIjpudWxsLAogICJhY2Nlc3MiOlt7CiAgICAgICJncm91cCI6IkNsaWVudHMiLAogICAgICAiYWNjZXNzX3JpZ2h0cyI6WyJyZWFkIiwiY3JlYXRlIl0KICAgIH0sewogICAgICAiZ3JvdXAiOiJSb2xlcyIsCiAgICAgICJhY2Nlc3NfcmlnaHRzIjpbInJlYWQiLCJjcmVhdGUiXQogICAgfSx7CiAgICAgICJncm91cCI6ICJHcm91cHMiLAogICAgICAiYWNjZXNzX3JpZ2h0cyI6WyJyZWFkIiwiY3JlYXRlIl0KICAgIH0sewogICAgICAiZ3JvdXAiOiAiU2VjcmV0cyIsCiAgICAgICJhY2Nlc3NfcmlnaHRzIjpbInJlYWQiXQogICAgfQogIF0KfQo="
|
||||
|
||||
# Nextcloud OIDC integration
|
||||
#COMPOSE_FILE="$COMPOSE_FILE:compose.nextcloud.yml"
|
||||
#SECRET_NEXTCLOUD_SEC_VERSION=v1 # length=5 prefix=Empty- This needs a value before deployment, but it will be set to the actual secret after the OIDC client is created.
|
||||
#NEXTCLOUD_CLIENT_NAME="Nextcloud"
|
||||
#NEXTCLOUD_REDIRECT_URI="https://nextcloud.example.com/apps/user_oidc/code"
|
||||
|
||||
80
README.md
@ -38,6 +38,86 @@ mistakenly rate limited based on internal ipv4 addresses (e.g. `10.0.0.6`).
|
||||
COMPOSE_FILE="$COMPOSE_FILE:compose.host.yml"
|
||||
```
|
||||
|
||||
### Bootstrap admin password
|
||||
|
||||
By default, rauthy generates a random admin password and prints it to the logs on first deploy. If you want to set a known password upfront, you can bootstrap it before the first deploy.
|
||||
|
||||
Requires `argon2` on your local machine.
|
||||
|
||||
1. With `abra app config <app>`, configure the following envs:
|
||||
```
|
||||
COMPOSE_FILE="$COMPOSE_FILE:compose.bootstrapadmin.yml"
|
||||
SECRET_ADMIN_PWHASH_VERSION=v1
|
||||
```
|
||||
2. Generate and insert the admin password hash:
|
||||
```
|
||||
abra app cmd --local <app> generate_bootstrap_admin_password
|
||||
```
|
||||
3. Deploy: `abra app deploy <app>`
|
||||
|
||||
Rauthy will use the bootstrapped hash instead of generating a password.
|
||||
|
||||
### API key
|
||||
|
||||
The API key allows access to the Rauthy API, used for creating OIDC clients, groups, and roles.
|
||||
|
||||
#### Setup
|
||||
|
||||
1. With `abra app config <app>`, configure the following envs:
|
||||
```
|
||||
COMPOSE_FILE="$COMPOSE_FILE:compose.api.yml"
|
||||
SECRET_API_SECRET_VERSION=v1
|
||||
```
|
||||
2. Generate the secret:
|
||||
```
|
||||
abra app secret generate <app> api_secret v1
|
||||
```
|
||||
3. When `API_BASE64_ACCESS_RIGHTS` and `api_secret` are set before first deployment, Rauthy will bootstrap an API key with the access rights as configured in `API_BASE64_ACCESS_RIGHTS`. The default value in `.env.sample` grants read and create rights on Clients, Roles, and Groups. See the [rauthy bootstrap docs](https://sebadob.github.io/rauthy/config/bootstrap.html#api-key) for the JSON schema. If `API_BASE64_ACCESS_RIGHTS` is empty or set after first deployment, no API key is bootstrapped and you'll need to create one manually in the admin UI with secret `api_secret` to be used by the abra.sh functions.
|
||||
|
||||
#### Available commands
|
||||
|
||||
All commands require the API key to be set up and the app to be running.
|
||||
|
||||
**`create_client <client_id> [insertsecret]`** — Creates a confidential OIDC client. Reads configuration from env vars prefixed with the uppercased client ID:
|
||||
|
||||
| Variable | Required | Default |
|
||||
|---|---|---|
|
||||
| `<ID>_CLIENT_NAME` | yes | — |
|
||||
| `<ID>_REDIRECT_URI` | yes | — |
|
||||
| `<ID>_ALLOWED_SCOPES` | no | `email openid profile groups` |
|
||||
|
||||
Without `insertsecret`, prints the generated client secret. With `insertsecret`, it inserts Rauthy's client secret in the app secret `<ID>_sec` (undeploying and redeploying the app automatically).
|
||||
|
||||
**`create_groups <group> [<group> ...]`** — Creates one or more groups.
|
||||
|
||||
**`create_roles <role> [<role> ...]`** — Creates one or more roles.
|
||||
|
||||
#### Example: Nextcloud OIDC integration
|
||||
|
||||
This sets up rauthy as an OIDC provider for a Nextcloud app. Requires the API key to be set up first.
|
||||
|
||||
1. With `abra app config <app>`, configure the following envs:
|
||||
```
|
||||
COMPOSE_FILE="$COMPOSE_FILE:compose.nextcloud.yml"
|
||||
SECRET_NEXTCLOUD_SEC_VERSION=v1
|
||||
NEXTCLOUD_CLIENT_NAME="Nextcloud"
|
||||
NEXTCLOUD_REDIRECT_URI="https://nextcloud.example.com/apps/user_oidc/code"
|
||||
```
|
||||
2. Generate a placeholder secret (required before deploy; it will be replaced after client creation):
|
||||
```
|
||||
abra app secret generate <app> nextcloud_sec v1
|
||||
```
|
||||
3. Deploy: `abra app deploy <app>`
|
||||
4. Create the OIDC client in rauthy and insert the generated client secret:
|
||||
```
|
||||
abra app cmd <app> create_client nextcloud insertsecret
|
||||
```
|
||||
This undeploys the app, replaces the `nextcloud_sec` Docker secret with the real client secret, and redeploys.
|
||||
5. Configure Nextcloud's OIDC provider (via the `user_oidc` app, see [Nextcloud user_oidc docs](https://git.coopcloud.tech/coop-cloud/nextcloud#how-do-i-enable-openid-connect-oidc-providers)) with:
|
||||
- **Discovery endpoint**: `https://<rauthy-domain>/.well-known/openid-configuration`
|
||||
- **Client ID**: `nextcloud`
|
||||
- **Client secret**: the value inserted above (can also be view in Rauthy Admin UI)
|
||||
|
||||
### Encryption key rotation
|
||||
|
||||
This recipe supports encryption key rotation as described in [the docs](https://sebadob.github.io/rauthy/config/encryption.html). To rotate keys the first time:
|
||||
|
||||
232
abra.sh
@ -1,6 +1,26 @@
|
||||
set -e
|
||||
|
||||
export CONFIG_TOML_VERSION=v4
|
||||
export CONFIG_TOML_VERSION=v5
|
||||
|
||||
generate_bootstrap_admin_password() {
|
||||
if ! command -v argon2 &> /dev/null; then
|
||||
echo "ERROR: 'argon2' CLI not found. Install it (e.g. 'apt install argon2')"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PASSWORD="$(openssl rand -base64 24)"
|
||||
SALT="$(openssl rand -base64 24)"
|
||||
HASH="$(echo -n "$PASSWORD" | argon2 "$SALT" -id -t 3 -m 16 -p 2 -l 32 -e)"
|
||||
|
||||
if abra app secret insert -C "$APP_NAME" admin_pwhash v1 "$HASH"; then
|
||||
echo "Generated admin password:"
|
||||
echo "$PASSWORD"
|
||||
echo "WARNING: password is NOT shown again, please save it NOW"
|
||||
else
|
||||
echo "Failed to insert admin hash."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
generate_enc_keys() {
|
||||
KEY_A="$(openssl rand -base64 32)"
|
||||
@ -11,3 +31,213 @@ generate_enc_keys() {
|
||||
echo " enc_keys_a $KEY_A"
|
||||
echo " enc_keys_b $KEY_B"
|
||||
}
|
||||
|
||||
# Reads a Docker Swarm secret value from the running container
|
||||
# Requires jq locally and SSH access to the server.
|
||||
# Usage: get_secret <secret_name>
|
||||
get_secret() {
|
||||
|
decentral1se marked this conversation as resolved
Outdated
decentral1se
commented
It's crazy how much work we have to do to work around swarm secrets 🤯 (Feel free to resolve this, just a passing reflection 🙃) It's crazy how much work we have to do to work around swarm secrets 🤯
(Feel free to resolve this, just a passing reflection 🙃)
|
||||
local SECRET_NAME="$1"
|
||||
|
||||
if ! command -v jq &>/dev/null; then
|
||||
echo "ERROR: jq is required. Install with: apt install jq" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local SERVER
|
||||
SERVER=$(abra app ls -m | jq -r --arg domain "$APP_NAME" '[.[].apps[] | select(.domain == $domain) | .server] | first' 2>/dev/null)
|
||||
|
||||
if [ -z "$SERVER" ] || [ "$SERVER" = "null" ]; then
|
||||
echo "ERROR: could not determine server for app '$APP_NAME'" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local MATCH
|
||||
MATCH=$(ssh "$SERVER" "
|
||||
docker stack services ${STACK_NAME} --format '{{.Name}}' | while read svc; do
|
||||
CID=\$(docker ps --no-trunc -q --filter \"name=\${svc}\" | head -1)
|
||||
[ -z \"\$CID\" ] && continue
|
||||
docker service inspect \"\$svc\" --format '{{json .Spec.TaskTemplate.ContainerSpec.Secrets}}' | jq -r --arg cid \"\$CID\" '.[]? | .SecretID + \" \" + \$cid + \" \" + .SecretName'
|
||||
done
|
||||
" 2>/dev/null | grep " ${STACK_NAME}_${SECRET_NAME}_" | head -1)
|
||||
|
||||
if [ -z "$MATCH" ]; then
|
||||
echo "ERROR: secret '$SECRET_NAME' not found in stack '$STACK_NAME'" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local SECRET_ID CID
|
||||
SECRET_ID=$(echo "$MATCH" | awk '{print $1}')
|
||||
CID=$(echo "$MATCH" | awk '{print $2}')
|
||||
|
||||
local VALUE
|
||||
VALUE=$(ssh "$SERVER" "cat /var/lib/docker/containers/${CID}/mounts/secrets/${SECRET_ID} 2>/dev/null || sudo cat /var/lib/docker/containers/${CID}/mounts/secrets/${SECRET_ID} 2>/dev/null")
|
||||
|
||||
if [ -z "$VALUE" ]; then
|
||||
echo "ERROR: could not read value for secret '$SECRET_NAME'" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
printf '%s' "$VALUE"
|
||||
}
|
||||
|
||||
# Usage: rauthy_api_request <method> <path> [json_body]
|
||||
# Sets globals API_HTTP_STATUS and API_BODY.
|
||||
rauthy_api_request() {
|
||||
local METHOD="$1" ENDPOINT="$2" PAYLOAD="${3:-}"
|
||||
if [ -z "$API_SECRET" ]; then
|
||||
API_SECRET=$(get_secret api_secret)
|
||||
fi
|
||||
local AUTH_HEADER
|
||||
AUTH_HEADER=$(printf 'Authorization: API-Key bootstrap$%s' "$API_SECRET")
|
||||
local ARGS=(-s -w "\n%{http_code}" -X "$METHOD" -H "$AUTH_HEADER")
|
||||
[ -n "$PAYLOAD" ] && ARGS+=(-H "Content-Type: application/json" -d "$PAYLOAD")
|
||||
local RESPONSE
|
||||
RESPONSE=$(curl "${ARGS[@]}" "https://${DOMAIN}/auth/v1${ENDPOINT}")
|
||||
API_HTTP_STATUS=$(echo "$RESPONSE" | tail -1)
|
||||
API_BODY=$(echo "$RESPONSE" | sed '$d')
|
||||
}
|
||||
|
||||
# Creates an OIDC client in Rauthy and prints the client secret.
|
||||
# Usage: create_client <client_id> [insertsecret]
|
||||
# Reads config from env vars prefixed with uppercased client_id:
|
||||
# <ID>_CLIENT_NAME (required)
|
||||
# <ID>_REDIRECT_URI (required)
|
||||
# <ID>_ALLOWED_SCOPES (optional, default: 'email openid profile groups')
|
||||
# With 'insertsecret': undeploys APP_NAME, replaces the Docker secret, then redeploys.
|
||||
# Example: NEXTCLOUD_CLIENT_NAME="Nextcloud" NEXTCLOUD_REDIRECT_URI="https://..." create_client nextcloud
|
||||
create_client() {
|
||||
local CLIENT_ID="$1"
|
||||
local MODE="$2"
|
||||
|
||||
if [ -z "$CLIENT_ID" ]; then
|
||||
echo "ERROR: no client_id; Usage: create_client <client_id> [insertsecret]" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local PREFIX
|
||||
PREFIX=$(echo "$CLIENT_ID" | tr '[:lower:]' '[:upper:]')
|
||||
|
||||
local CLIENT_NAME REDIRECT_URI ALLOWED_SCOPES
|
||||
CLIENT_NAME=$(eval "echo \"\${${PREFIX}_CLIENT_NAME}\"")
|
||||
REDIRECT_URI=$(eval "echo \"\${${PREFIX}_REDIRECT_URI}\"")
|
||||
ALLOWED_SCOPES=$(eval "echo \"\${${PREFIX}_ALLOWED_SCOPES:-email openid profile groups}\"")
|
||||
|
||||
if [ -z "$CLIENT_NAME" ] || [ -z "$REDIRECT_URI" ]; then
|
||||
echo "ERROR: ${PREFIX}_CLIENT_NAME and ${PREFIX}_REDIRECT_URI must be set" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v jq &>/dev/null; then
|
||||
echo "ERROR: jq is required. Install with: apt install jq" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rauthy_api_request GET "/clients/${CLIENT_ID}"
|
||||
if [ "$API_HTTP_STATUS" = "200" ]; then
|
||||
echo "Client '${CLIENT_ID}' already exists, skipping creation."
|
||||
else
|
||||
local PAYLOAD
|
||||
PAYLOAD=$(jq -n \
|
||||
--arg id "$CLIENT_ID" \
|
||||
--arg name "$CLIENT_NAME" \
|
||||
--arg redirect_uris "$REDIRECT_URI" \
|
||||
--arg allowed_scopes "$ALLOWED_SCOPES" \
|
||||
'$ARGS.named | .redirect_uris = [.redirect_uris] | .allowed_scopes = (.allowed_scopes | split(" ")) | .confidential = true')
|
||||
|
||||
rauthy_api_request POST "/clients" "$PAYLOAD"
|
||||
if [ "$API_HTTP_STATUS" != "200" ] && [ "$API_HTTP_STATUS" != "201" ]; then
|
||||
echo "ERROR: failed to create client '${CLIENT_ID}' (HTTP ${API_HTTP_STATUS}): ${API_BODY}" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
rauthy_api_request POST "/clients/${CLIENT_ID}/secret"
|
||||
if [ "$API_HTTP_STATUS" != "200" ] && [ "$API_HTTP_STATUS" != "201" ]; then
|
||||
echo "ERROR: failed to fetch secret for client '${CLIENT_ID}' (HTTP ${API_HTTP_STATUS}): ${API_BODY}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local CLIENT_SECRET
|
||||
CLIENT_SECRET=$(echo "$API_BODY" | jq -r '.secret // empty')
|
||||
|
||||
if [ -z "$CLIENT_SECRET" ]; then
|
||||
echo "ERROR: no secret in API response for '${CLIENT_ID}'" >&2
|
||||
echo "Response was: ${API_BODY}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$MODE" = "insertsecret" ]; then
|
||||
echo "Undeploying '${APP_NAME}' to replace secret '${CLIENT_ID}_sec'"
|
||||
abra --no-input app undeploy "$APP_NAME" || true
|
||||
abra app secret remove -C "$APP_NAME" "${CLIENT_ID}_sec" || true
|
||||
if printf '%s' "$CLIENT_SECRET" | abra app secret insert -C "$APP_NAME" "${CLIENT_ID}_sec" v1; then
|
||||
echo "Secret '${CLIENT_ID}_sec' inserted, redeploying '${APP_NAME}'..."
|
||||
else
|
||||
echo "ERROR: failed to insert secret '${CLIENT_ID}_sec'; redeploying app" >&2
|
||||
fi
|
||||
abra --no-input app deploy -C "$APP_NAME" || true
|
||||
#rauthy doesn't have a healthcheck, wait 5 seconds for startup
|
||||
sleep 5
|
||||
|
||||
else
|
||||
echo "Client '${CLIENT_ID}' created. Secret: ${CLIENT_SECRET}"
|
||||
fi
|
||||
}
|
||||
|
||||
# Creates one or more groups in Rauthy.
|
||||
# Usage: create_groups <group_name> [<group_name> ...]
|
||||
create_groups() {
|
||||
if ! command -v jq &>/dev/null; then
|
||||
echo "ERROR: jq is required. Install with: apt install jq" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rauthy_api_request GET "/groups"
|
||||
local EXISTING_GROUPS
|
||||
if [ "$API_HTTP_STATUS" = "200" ]; then
|
||||
EXISTING_GROUPS=$(echo "$API_BODY" | jq -r '.[].name // empty')
|
||||
fi
|
||||
|
||||
for GROUP_NAME in "$@"; do
|
||||
if echo "$EXISTING_GROUPS" | grep -qx "$GROUP_NAME"; then
|
||||
echo "Group '${GROUP_NAME}' already exists, skipping"
|
||||
continue
|
||||
fi
|
||||
|
||||
rauthy_api_request POST "/groups" "$(jq -n --arg group "$GROUP_NAME" '$ARGS.named')"
|
||||
if [ "$API_HTTP_STATUS" != "200" ] && [ "$API_HTTP_STATUS" != "201" ]; then
|
||||
echo "ERROR: failed to create group '${GROUP_NAME}' (HTTP ${API_HTTP_STATUS}): ${API_BODY}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Created group '${GROUP_NAME}'"
|
||||
done
|
||||
}
|
||||
|
||||
# Creates one or more roles in Rauthy.
|
||||
# Usage: create_roles <role_name> [<role_name> ...]
|
||||
create_roles() {
|
||||
if ! command -v jq &>/dev/null; then
|
||||
echo "ERROR: jq is required. Install with: apt install jq" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rauthy_api_request GET "/roles"
|
||||
local EXISTING_ROLES
|
||||
EXISTING_ROLES=$(echo "$API_BODY" | jq -r '.[].name // empty')
|
||||
|
||||
for ROLE_NAME in "$@"; do
|
||||
if echo "$EXISTING_ROLES" | grep -qx "$ROLE_NAME"; then
|
||||
echo "Role '${ROLE_NAME}' already exists, skipping"
|
||||
continue
|
||||
fi
|
||||
|
||||
rauthy_api_request POST "/roles" "$(jq -n --arg role "$ROLE_NAME" '$ARGS.named')"
|
||||
if [ "$API_HTTP_STATUS" != "200" ] && [ "$API_HTTP_STATUS" != "201" ]; then
|
||||
echo "ERROR: failed to create role '${ROLE_NAME}' (HTTP ${API_HTTP_STATUS}): ${API_BODY}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Created role '${ROLE_NAME}'"
|
||||
done
|
||||
}
|
||||
|
||||
10
alaconnect.yml
Normal file
@ -0,0 +1,10 @@
|
||||
nextcloud:
|
||||
uncomment:
|
||||
- compose.nextcloud.yml
|
||||
- SECRET_NEXTCLOUD_SEC_VERSION
|
||||
- NEXTCLOUD_REDIRECT_URI
|
||||
- NEXTCLOUD_CLIENT_NAME
|
||||
initial-hooks:
|
||||
- local create_client nextcloud insertsecret
|
||||
shared_secrets:
|
||||
user_oidc_secret: nextcloud_sec
|
||||
18
api.key.example.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"name":"bootstrap",
|
||||
"exp":null,
|
||||
"access":[{
|
||||
"group":"Clients",
|
||||
"access_rights":["read","create"]
|
||||
},{
|
||||
"group":"Roles",
|
||||
"access_rights":["read","create"]
|
||||
},{
|
||||
"group": "Groups",
|
||||
"access_rights":["read","create"]
|
||||
},{
|
||||
"group": "Secrets",
|
||||
"access_rights":["read"]
|
||||
}
|
||||
]
|
||||
}
|
||||
11
compose.api.yml
Normal file
@ -0,0 +1,11 @@
|
||||
services:
|
||||
app:
|
||||
environment:
|
||||
- API_KEY
|
||||
secrets:
|
||||
- api_secret
|
||||
|
||||
secrets:
|
||||
api_secret:
|
||||
name: ${STACK_NAME}_api_secret_${SECRET_API_SECRET_VERSION}
|
||||
external: true
|
||||
9
compose.bootstrapadmin.yml
Normal file
@ -0,0 +1,9 @@
|
||||
services:
|
||||
app:
|
||||
secrets:
|
||||
- admin_pwhash
|
||||
|
||||
secrets:
|
||||
admin_pwhash:
|
||||
name: ${STACK_NAME}_admin_pwhash_${SECRET_ADMIN_PWHASH_VERSION}
|
||||
external: true
|
||||
9
compose.nextcloud.yml
Normal file
@ -0,0 +1,9 @@
|
||||
services:
|
||||
app:
|
||||
secrets:
|
||||
- nextcloud_sec
|
||||
|
||||
secrets:
|
||||
nextcloud_sec:
|
||||
name: ${STACK_NAME}_nextcloud_sec_${SECRET_NEXTCLOUD_SEC_VERSION}
|
||||
external: true
|
||||
@ -3,6 +3,9 @@
|
||||
|
||||
[bootstrap]
|
||||
admin_email = '{{ env "ADMIN_EMAIL" }}'
|
||||
pasword_argon2id = '{{ secret "admin_pwhash" }}'
|
||||
api_key = '{{ env "API_BASE64_ACCESS_RIGHTS" }}'
|
||||
api_key_secret = '{{ secret "api_secret" }}'
|
||||
|
||||
[cluster]
|
||||
node_id = 1
|
||||
|
||||
4
release/next
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
* Added bootstrapping admin password and API key
|
||||
* Added abra.sh functions for creating clients, groups and roles with the Rauthy API
|
||||
* Documentation and example for Nextcloud integration
|
||||
We generally have a convention of
X_ENABLED=1/0to turn stuff on/off. See other recipes for how that is handled. It is a more explicit way of configuring the recipe which I appreciate. Up to you if you want to go that route.I've seen that, but it's not applied everywhere. I feel that's a bit redundant with uncommenting compose.x.yml (also because uncommenting .yml and setting X_ENABLED=0 doesn't always fully disable in every implementation), but no strong preference. It makes sense to at least be consistent within a recipe and compose.smtp.yml in this recipe also uses it. So I add an X_ENABLED env for every compose.x.yml, right?
Ah, in my mind the
X_ENABLEDwas per-feature, not per-compose variant 😖Maybe we can just slowly back away from this and leave it as-is 🙃
Agreed, fine to drop
X_ENABLEDin general, certainly fine to not do it with this change.