Skip to content

Commit

Permalink
0.0.4 move secret generation to the scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
LReg committed Sep 11, 2024
1 parent ad0316e commit 46f3e88
Show file tree
Hide file tree
Showing 7 changed files with 159 additions and 43 deletions.
28 changes: 14 additions & 14 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,30 @@ TRAEFIK_ENTRYPOINT=YourHttpsEntryPoint
TRAEFIK_EMAIL=[email protected]

### Authelia
AUTHELIA_RESET_PASSWORD_SECRET=super-secret-password
AUTHELIA_SESSION_REDIS_PASSWORD=redis-password
AUTHELIA_SESSION_SECRET=super-secret-session
AUTHELIA_RESET_PASSWORD_SECRET=!SECRET
AUTHELIA_SESSION_REDIS_PASSWORD=!SECRET
AUTHELIA_SESSION_SECRET=!SECRET

### Authelia authentication backend (FreeIPA)
LLDAP_JWT_SECRET=super-secret-jwt
LLDAP_KEY_SEED=super-secret-seed
### Authelia authentication backend (LLDAP)
LLDAP_JWT_SECRET=!SECRET
LLDAP_KEY_SEED=!SECRET
LLDAP_USERNAME=authelia
LLDAP_PASSWORD=secret-password
LLDAP_PASSWORD=!SECRET

### Authelia storage (postgres)
POSTGRES_PASSWORD=super-secret-password
POSTGRES_ENCRYPTION_KEY=super-secret-encryption-key
POSTGRES_PASSWORD=!SECRET
POSTGRES_ENCRYPTION_KEY=!SECRET

### OIDC
OIDC_HMAC_SECRET=super-secret-hmac
OIDC_CLIENT_ID=your-client-id
OIDC_HMAC_SECRET=!SECRET
OIDC_CLIENT_ID=!SECRET
OIDC_CLIENT_NAME=your-client-name

### Database
DB_ROOT_USERNAME=root
DB_ROOT_PASSWORD=root-password
DB_ROOT_PASSWORD=!SECRET
DB_USERNAME=db-username
DB_PASSWORD=db-password
DB_PASSWORD=!SECRET

## SMTP
SMTP_USERNAME=user
Expand All @@ -50,4 +50,4 @@ SMTP_HOST=smtp://smtp.gmail.com:587
SMTP_SENDER=[email protected]
SMTP_DISABLE_REQUIRE_TLS=false
SMTP_DISABLE_STARTTLS=false
SMTP_SKIP_TLS_VERIFY=false
SMTP_SKIP_TLS_VERIFY=false
2 changes: 1 addition & 1 deletion .env.local
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ DB_USERNAME=db-username
DB_PASSWORD=db-password

AUTH_DOMAIN=auth.yourdomain.com
OIDC_CLIENT_ID=you-client-id
OIDC_CLIENT_ID=your-client-id
2 changes: 1 addition & 1 deletion .github/workflows/deploy-testserver.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ jobs:
script: |
cd AutheliaBlueprint
git pull
echo "${{ secrets.KEY }}" | sudo -S -E ./setup.sh
echo "${{ secrets.KEY }}" | sudo -S -E ./setup.sh server
docker compose -f no-traefik.docker-compose.yml build
docker compose -f no-traefik.docker-compose.yml down
docker compose -f no-traefik.docker-compose.yml up -d --force-recreate
82 changes: 56 additions & 26 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,48 @@ As DB mongodb is configured.
Everything is dockerized.

# Setup
## General Idea
Everything should be configurable in the .env file OR in the environment variables. The environment variables will overwrite the .env file.

Authelia and the database need config file and startup script. They are written with placeholders. The setup.sh script will replace them with the values from the .env file.

After executing the setup.sh script you can consider all values in your .env and envvars to be set as "global config".

The setup needs to be done before the build because the frontend needs values at buildtime.

You can think of your .env and envvars as a global config, which will be used in diffrent places:
docker-compose file, authelia config, database startup script, frontend build, backend envvars.

The idea of the local setup will be to only have the frontend, backend and db running locally and to use the remote authelia.
## Setup.sh
The setup.sh script is used to generate secrets and to replace placeholders in the authelia configuration file and the database startup script.
You will need to work on you .env file anyway tho.
Usage:
``` sh
chmod +x ./setup.sh
# server or local | generateSecrets is optional
./setup.sh <server|local> [generateSecrets]
```

In more detail the setup script does the following:
- copies either the .env.example or the .env.local file to the .env file
- copies the authelia template configuration file
- generates secrets for the .env file (optional on generate secrets)
- generates a rsa key for the authelia configuration (optional on generate secrets)
- replaces the placeholders in the authelia configuration with the values from the .env file
- replaces the placeholders in the database startup script with the values from the .env file
### Pitfalls with setup.sh
The setup.sh takes the authelia config template and replaces the placeholders with the values from the .env file.

After the first start the config file is owned by root. So you need to call the setup.sh with sudo.
Maybe I will find a better solution for this in the future.

If you are not planning on changing any of the configuration values anymore,
you can also extract the setup.sh script to another pipeline and remove it from the main deploy pipeline.
Tho it is important to still have the env vars because they are read in the docker-compose file.
## First startup
Important to note:
On the first startup the lldap user that authelia will want to use will not exsist. This will lead to the authelia container to be unhealthy and restarting.
On the first startup the lldap user that authelia will want to use will not exist. This will lead to the authelia container to be unhealthy and restarting.

So you will need to login to lldap on you lldap.youdomain.com (LLDAP_DOMAIN) and login with admin:password and then create the user you defined in your .env File.

Expand All @@ -22,46 +61,43 @@ The user should have the group ldap_password_manager. And of course change the a
``` sh
git clone project
cd project
cp .env.example .env # update accordingly or write envvars via pipeline or so
chmod +x ./setup.sh
./setup.sh
docker run -u "$(id -u):$(id -g)" -v "$(pwd)":/keys authelia/authelia:latest authelia crypto pair rsa generate --bits 4096 --directory /keys
copy the content of the private.pem key to `docker/volumes/authelia/config/secrets/oidc/jwks/rsa.4096.key`
./setup.sh server generateSecrets
# update the .env file
docker compose up -d
```

### Traefik is already configured what should I do?
If you already have traefik running and blocking your ports you can user the no-traefik.docker-compose.yml.
````bash
docker compose -f no-traefik.docker-compose.yml up -d
````
You have to put in the correct valuees in the .env file for Entrypoint, Network and Certresolver.
You have to put in the correct values in the .env file for Entrypoint, Network and CertResolver.
### Pipeline usage
In the folder .github/workflows there is a github Actions pipeline predefined. It leverages the Action secrets to pull alle configuration values.
In the folder .github/workflows there is a github Actions pipeline predefined. It leverages the Action secrets to pull all configuration values.

The example pipeline uses some bad practices by building on the server it will run on. This is because I personally don't consider it that bad for a small project.

Before the first running of the pipeline you need to:
- create a user on your server
- give the user access to: docker, (sudo), ssh -> sudo see pitfalls with setup.sh
- clone the repository on the server
- cp the .env file from .env.example (values will be overwritten anyway but the keys are needed)
- give the ./setup.sh script execution rights
- generate the rsa key with the command above and copy the content of the private.pem to the rsa.4096.key file
### Pitfalls with setup.sh
The setup.sh takes the authelia config template and replaces the placeholders with the values from the .env file.
- execute the setup.sh script with the generateSecrets argument
- depending on weather you want to use envvars or the .env file you will need to update the .env file or your pipeline

After the first start the config file is owned by root. So you need to call the setup.sh with sudo.
Maybe I will find a better solution for this in the future.

If you are not planning on changing any of the configuration values anymore,
you can also extract the setup.sh script to another pipeline and remove it from the main deploy pipeline.
Tho it is important to still have the env vars because they are read in the docker-compose file.
After that the setup.sh will only need to run when you have changes in your .env or environment variables.
But if your pipeline should react to such variable changes then it would make sense to run it.
But you should not add the generateSecrets to the setup.sh script because it would regenerate all secrets and break your system.
## Local setup
### Database
For the local configuration, I configured it in a way to only run frontend backend and db locally. And access your database.
For the local configuration, I configured it in a way to only run frontend backend and db locally. And access your authelia running on your server.
``` sh
git clone project
cd project
cp .env.local .env # some values need to be filled for the backend (clientId and auth-domain)
chmod +x ./localSetup.sh
./localSetup.sh # needed to fill the mongdb script placeholders
./localSetup.sh local # needed to fill the mongdb script placeholders
docker compose -f local.docker-compose.yml up -d mongodb # only starts the db
```
### frontend
Expand All @@ -78,14 +114,9 @@ since the backend is relying on environment variables I would recommend to run i
docker compose -f local.docker-compose.yml build backend
docker compose -f local.docker-compose.yml up backend
```
### Change values in the .env file
When calling the setup.sh script some of the env variables will get copied to the authelia configuration file.
First the templatefile is copied to the config file and then the placholders will be replaced.

After the first Application start, it is necessary to call it with sudo, because authelia changes permissions to the file.
# Configuration in .env file
There will be some secrets that you need to generate and copy to the .env file.
Here is a helper page from authelia you can use https://www.authelia.com/reference/guides/generating-secure-values/#generating-a-random-alphanumeric-string
Here is a helper page from authelia you can use to generate secrets in case you dont want to do it with the setup.sh script: https://www.authelia.com/reference/guides/generating-secure-values/#generating-a-random-alphanumeric-string
### General
- APP_NAME=YourAppName : Used to avoid nameconflics, added for example to container names

Expand All @@ -95,7 +126,6 @@ example for https://app.yourdomain.com
- AUTH_SUBDOMAIN=auth : Subdomain for authelia -> https://auth.yourdomain.com
- LDAP_SUBDOMAIN=ldap : Subdomain for you ldap (user management) -> https://ldap.yourdomain.com


- CALLBACK_PATH=home : The path where the frontend will redirect to after login (must fit exactly with that you program in the frontend)

### Traefik (mainly to avoid name conflicts)
Expand Down
15 changes: 15 additions & 0 deletions docker/scripts/setJWTPrivateKey.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash

set -e

if [ "$#" -ne 1 ]; then
echo "Usage: $0 <Destination file>"
exit 1
fi

DESTINATION_FILE="$1"

# RSA-Schlüssel generieren und in Datei speichern
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 2>/dev/null > "$DESTINATION_FILE"

echo "Private key successfully written to $DESTINATION_FILE"
34 changes: 34 additions & 0 deletions docker/scripts/setSecrets.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/bin/bash

# generates secrets for each "SECRET" string in the given .env file
# Syntax has to be: VARNAME=SECRET
# Requirement: openssl
# Fehlerbehandlung: Beendet das Skript, wenn ein Befehl fehlschlägt

set -e

# Überprüfen, ob genügend Argumente übergeben wurden
if [ "$#" -ne 1 ]; then
echo "Usage: $0 <ENV_FILE>"
exit 1
fi

# Dateien
ENV_FILE="$1"
LINE_NUMBER=0

while IFS= read -r line; do
LINE_NUMBER=$((LINE_NUMBER+1))
if [[ "$line" =~ ^[A-Z_]+=[^\"]+ ]]; then
VAR_NAME=$(echo "$line" | cut -d'=' -f1)
ENV_FILE_VAR_VALUE=$(echo "$line" | cut -d'=' -f2-)

if [ "$ENV_FILE_VAR_VALUE" == "!SECRET" ]; then
SECRET=$(openssl rand -base64 48 | tr -dc 'a-zA-Z0-9' | head -c 64)
VAR_VALUE="${!VAR_NAME}"
sed -i "${LINE_NUMBER}s/!SECRET/${SECRET}/" $ENV_FILE
fi
fi
done < "$ENV_FILE"

echo "Secrets wurden in die Datei $ENV_FILE geschrieben."
39 changes: 38 additions & 1 deletion setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,32 @@

# Fehlerbehandlung: Beendet das Skript, wenn ein Befehl fehlschlägt
set -e
if [ "$#" -eq 0 ] || [ "$#" -gt 2 ]; then
echo "Usage: $0 <local|server> [generateSecrets]"
exit 1
fi

if [ "$1" == "server" ]; then
SERVER=true
else
SERVER=false
fi

if [ "$2" == "generateSecrets" ]; then
GENERATE_SECRETS=true
else
GENERATE_SECRETS=false
fi

if [ "$SERVER" = true ]; then
ENV_FILE="./.env.example"
echo "Kopiere die server setup Datei nach .env"
else
ENV_FILE="./.env.local"
echo "Kopiere die local setup Datei nach .env"
fi

cp "$ENV_FILE" "./.env"
ENV_FILE="./.env"

# Prüfen, ob die env-Datei existiert
Expand All @@ -11,8 +36,20 @@ if [[ ! -f "$ENV_FILE" ]]; then
exit 1
fi

chmod +x ./docker/scripts/setSecrets.sh
chmod +x ./docker/scripts/changeEnvVars.sh
./docker/scripts/changeEnvVars.sh "$ENV_FILE" "./docker/volumes/authelia/config/configuration.template.yml" "./docker/volumes/authelia/config/configuration.yml"
chmod +x ./docker/scripts/setJWTPrivateKey.sh

if [ "$GENERATE_SECRETS" = true ]; then
./docker/scripts/setSecrets.sh "$ENV_FILE"
fi

if [ "$SERVER" = true ]; then
./docker/scripts/changeEnvVars.sh "$ENV_FILE" "./docker/volumes/authelia/config/configuration.template.yml" "./docker/volumes/authelia/config/configuration.yml"
if [ "$GENERATE_SECRETS" = true ]; then
./docker/scripts/setJWTPrivateKey.sh "./docker/volumes/authelia/config/secrets/oidc/jwks/rsa.4096.key"
fi
fi
./docker/scripts/changeEnvVars.sh "$ENV_FILE" "./docker/scripts/mongo-init.template.js" "./docker/scripts/mongo-init.js"


Expand Down

0 comments on commit 46f3e88

Please sign in to comment.