Skip to content

Commit

Permalink
Merge pull request #293 from Progress1/keycloak_secrets
Browse files Browse the repository at this point in the history
Docker secrets - Keycloak
  • Loading branch information
Progress1 authored May 24, 2024
2 parents 9a09fdf + 065183e commit 47f08b7
Show file tree
Hide file tree
Showing 8 changed files with 70 additions and 52 deletions.
4 changes: 2 additions & 2 deletions docker/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,8 @@ VUE_APP_TARANIS_NG_LOCALE=""
# Taranis-NG now supports Docker secrets. Use this in production! More here: https://docs.docker.com/compose/use-secrets/
# These variables bellow are only for testing purposes and cannot be mixed with use of Docker secrets!
# POSTGRES_PASSWORD=supersecret
# POSTGRES_KEYCLOAK_PASSWORD=supersecret
# JWT_SECRET_KEY=supersecret
# COLLECTOR_PRESENTER_PUBLISHER_API_KEY=supersecret
# KEYCLOAK_PASSWORD=supersecret

# Paths
CVE_UPDATE_FILE=/data/cve_dictionary.xml
Expand All @@ -45,3 +43,5 @@ PRESENTER_PORT=5002
# Standalone Keycloak
KEYCLOAK_VERSION=16.1.1
KEYCLOAK_USER=admin
KEYCLOAK_PASSWORD=supersecret
POSTGRES_KEYCLOAK_PASSWORD=supersecret
15 changes: 1 addition & 14 deletions docker/docker-compose-keycloak-serv.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ services:
environment:
POSTGRES_DB: "taranis-ng-keycloak"
POSTGRES_USER: "taranis-ng-keycloak"
POSTGRES_PASSWORD: /run/secrets/keycloak_postgres_password
POSTGRES_PASSWORD: "${POSTGRES_KEYCLOAK_PASSWORD}"
command: ["postgres", "-c", "shared_buffers=${DB_SHARED_BUFFERS}", "-c", "max_connections=${DB_MAX_CONNECTIONS}"]
volumes:
- "keycloak_db_data:/var/lib/postgresql/data"
Expand All @@ -16,8 +16,6 @@ services:
options:
max-size: "200k"
max-file: "10"
secrets:
- keycloak_postgres_password

keycloak:
image: "skcert/taranis-ng-keycloak:${TARANIS_NG_TAG}"
Expand All @@ -34,12 +32,10 @@ services:
DB_DATABASE: taranis-ng-keycloak
DB_USER: taranis-ng-keycloak
DB_PASSWORD: "${POSTGRES_KEYCLOAK_PASSWORD}"
DB_PASSWORD_FILE: /run/secrets/keycloak_postgres_password
KEYCLOAK_IMPORT: "/opt/jboss/keycloak/realm-export.json"
KEYCLOAK_FRONTEND_URL: "${TARANIS_NG_HTTPS_URI}/api/v1/keycloak/auth"
KEYCLOAK_USER: "${KEYCLOAK_USER}"
KEYCLOAK_PASSWORD: "${KEYCLOAK_PASSWORD}"
KEYCLOAK_PASSWORD_FILE: /run/secrets/keycloak_password
KEYCLOAK_DEFAULT_THEME: "taranis-ng"
PROXY_ADDRESS_FORWARDING: "false"
JAVA_OPTS: "-Dkeycloak.profile.feature.upload_scripts=enabled"
Expand All @@ -61,15 +57,6 @@ services:
traefik.http.routers.taranis-keycloak-443.tls.domains[0].main: "${TARANIS_NG_HOSTNAME}"
traefik.http.routers.taranis-keycloak-443.middlewares: "taranis-keycloak-stripprefix"
traefik.http.routers.taranis-keycloak-443.service: "taranis-keycloak"
secrets:
- keycloak_postgres_password
- keycloak_password

secrets:
postgres_keycloak_password:
file: secrets/keycloak_postgres_password.txt
keycloak_password:
file: secrets/keycloak_password.txt

volumes:
keycloak_db_data:
Expand Down
26 changes: 14 additions & 12 deletions docker/docker-compose-keycloak.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,28 @@ services:
TARANIS_NG_AUTHENTICATOR: "keycloak"

OPENID_LOGOUT_URL: "${TARANIS_NG_HTTPS_URI}/api/v1/keycloak/auth/realms/taranis-ng/protocol/openid-connect/logout?redirect_uri=GOTO_URL"
TARANIS_NG_KEYCLOAK_INTERNAL_URL: "http://keycloak:8080"
TARANIS_NG_KEYCLOAK_REALM: "taranis-ng"
# CLIENT (external Keycloak)
TARANIS_NG_KEYCLOAK_URL: "https://keycloak.example.com"
TARANIS_NG_KEYCLOAK_INTERNAL_URL: "https://keycloak.int.example.com"
TARANIS_NG_KEYCLOAK_CLIENT_ID: "taranis-ng"
TARANIS_NG_KEYCLOAK_CLIENT_SECRET: "supersecret"
KEYCLOAK_USER_MANAGEMENT: "true"
KEYCLOAK_SERVER_URL: "http://keycloak:8080"
KEYCLOAK_ADMIN_USERNAME: "admin"
KEYCLOAK_ADMIN_PASSWORD: "${KEYCLOAK_PASSWORD}"
KEYCLOAK_ADMIN_PASSWORD_FILE: /run/secrets/keycloak_password
KEYCLOAK_REALM_NAME: "taranis-ng"
KEYCLOAK_CLIENT_SECRET_KEY: "supersecret"
KEYCLOAK_CLIENT_SECRET_KEY_FILE: /run/secrets/keycloak_client_secret_key
KEYCLOAK_USER_MANAGEMENT: "false"
# needed if KEYCLOAK_USER_MANAGEMENT = true
KEYCLOAK_ADMIN_USERNAME: "admin"
KEYCLOAK_ADMIN_PASSWORD_FILE: /run/secrets/keycloak_admin_password
KEYCLOAK_VERIFY: "true"
secrets:
- keycloak_password
- keycloak_client_secret_key
- keycloak_admin_password

gui:
environment:
VUE_APP_TARANIS_NG_LOGOUT_URL: "${TARANIS_NG_HTTPS_URI}/api/v1/auth/logout?gotoUrl=TARANIS_GUI_URI"
VUE_APP_TARANIS_NG_LOGIN_URL: "${TARANIS_NG_HTTPS_URI}/api/v1/keycloak/auth/realms/taranis-ng/protocol/openid-connect/auth?response_type=code&client_id=taranis-ng&redirect_uri=TARANIS_GUI_URI"

secrets:
keycloak_password:
file: secrets/keycloak_password.txt
keycloak_client_secret_key:
file: ./secrets/keycloak_client_secret_key.txt
keycloak_admin_password:
file: ./secrets/keycloak_admin_password.txt
22 changes: 18 additions & 4 deletions src/core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,23 +43,37 @@ Keycloak is not needed to run test version of TaranisNG at the moment. You can u
VUE_APP_TARANIS_NG_LOGOUT_URL=http://127.0.0.1:5000/api/auth/logout
```

## Keycloak example of docker-compose.yml for taranis-ng-core:
## Keycloak client example of docker-compose.yml:

**taranis-ng-core** section:
```
TARANIS_NG_AUTHENTICATOR: "keycloak"
OPENID_LOGOUT_URL: "https://keycloak.example.com/auth/realms/jiskb/protocol/openid-connect/logout?redirect_uri=GOTO_URL"
TARANIS_NG_KEYCLOAK_URL: "https://keycloak.example.com"
TARANIS_NG_KEYCLOAK_INTERNAL_URL: "https://keycloak.int.example.com"
TARANIS_NG_KEYCLOAK_CLIENT_ID: "taranis-ng"
TARANIS_NG_KEYCLOAK_CLIENT_SECRET: "XXXXXX"
TARANIS_NG_AUTHENTICATOR: "keycloak"
KEYCLOAK_REALM_NAME: "taranis-ng"
KEYCLOAK_USER_MANAGEMENT: "false"
```

update Keycloak CLIENT_SECRET_KEY value inside keycloak_client_secret_key.txt file. Path is defined in this section:
```
secrets:
keycloak_client_secret_key:
file: ./secrets/keycloak_client_secret_key.txt
```

**taranis-ng-gui** section:
```
VUE_APP_TARANIS_NG_LOGOUT_URL: "${TARANIS_NG_HTTPS_URI}/api/v1/auth/logout?gotoUrl=TARANIS_GUI_URI"
VUE_APP_TARANIS_NG_LOGIN_URL: "${TARANIS_NG_HTTPS_URI}/api/v1/keycloak/auth/realms/taranis-ng/protocol/openid-connect/auth?response_type=code&client_id=taranis-ng&redirect_uri=TARANIS_GUI_URI"
```

You can use and modify the existing `docker-compose-keycloak.yml` example in the repository and
run with ```docker-compose -f docker-compose.yml -f docker-compose-keycloak.yml```


# **LDAP authentication**
# **LDAP setup**
If you prefer to authenticate users with LDAP, you need to set environment variables similarly to this:
```
TARANIS_NG_AUTHENTICATOR: "ldap"
Expand Down
4 changes: 2 additions & 2 deletions src/core/auth/keycloak_authenticator.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from requests import post
from requests.auth import HTTPBasicAuth

from managers import log_manager
from managers import log_manager, external_auth_manager
from auth.base_authenticator import BaseAuthenticator


Expand All @@ -27,7 +27,7 @@ def authenticate(self, credentials):
# original redirect_uri (host needs to match)
},
auth=HTTPBasicAuth(environ.get('TARANIS_NG_KEYCLOAK_CLIENT_ID'),
environ.get('TARANIS_NG_KEYCLOAK_CLIENT_SECRET')),
external_auth_manager.get_keycloak_client_secret_key()),
# do not forget credentials
proxies={'http': None, 'https': None},
allow_redirects=False, verify=False)
Expand Down
51 changes: 33 additions & 18 deletions src/core/managers/external_auth_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
Functions:
- keycloak_user_management_enabled(): Check if Keycloak user management is enabled.
- get_keycloak_password(): Get the Keycloak admin password.
- get_keycloak_client_secret_key(): Get the Keycloak client_secret_key.
- get_keycloak_admin_password(): Get the Keycloak admin password.
- get_keycloak_admin(): Return an instance of KeycloakAdmin.
- create_user(user_data): Create a user in the external authentication system.
- update_user(user_data, original_username): Update user information in the external authentication system.
Expand All @@ -30,26 +31,40 @@ def keycloak_user_management_enabled():
return False


def get_keycloak_password():
def get_keycloak_client_secret_key():
"""Get the Keycloak client_secret_key.
This function retrieves the Keycloak client_secret_key from the file
specified by the environment variable KEYCLOAK_CLIENT_SECRET_KEY_FILE.
Returns:
str: The Keycloak client_secret_key.
"""
try:
with open(os.getenv("KEYCLOAK_CLIENT_SECRET_KEY_FILE"), "r") as file:
client_secret_key = file.read()
except FileNotFoundError:
print("KEYCLOAK_CLIENT_SECRET_KEY_FILE not found. Please check this variable and verify the path of the file containing the secret.", flush=True)
client_secret_key = "not-really-a-secret"
return client_secret_key


def get_keycloak_admin_password():
"""Get the Keycloak admin password.
This function retrieves the Keycloak admin password from the environment variable
KEYCLOAK_ADMIN_PASSWORD. If the environment variable is not set, it reads the password
from the file specified by the environment variable KEYCLOAK_ADMIN_PASSWORD_FILE.
This function retrieves the Keycloak admin password from the file
specified by the environment variable KEYCLOAK_ADMIN_PASSWORD_FILE.
Returns:
str: The Keycloak admin password.
"""
try:
with open(os.getenv("KEYCLOAK_ADMIN_PASSWORD_FILE"), "r") as file:
keycloak_password = file.read()
keycloak_admin_password = file.read()
except FileNotFoundError:
print(
"KEYCLOAK_ADMIN_PASSWORD_FILE not found. Please set the KEYCLOAK_ADMIN_PASSWORD_FILE environment variable to the path of "
"the file containing the Keycloak admin password."
)
keycloak_password = os.getenv("KEYCLOAK_ADMIN_PASSWORD")
return keycloak_password
print("KEYCLOAK_ADMIN_PASSWORD_FILE not found. Please check this variable and verify the path of the file containing the Keycloak admin password.", flush=True)
keycloak_admin_password = "not-really-a-password"
return keycloak_admin_password


def get_keycloak_admin():
Expand All @@ -62,12 +77,12 @@ def get_keycloak_admin():
KeycloakAdmin: An instance of the KeycloakAdmin class.
"""
return KeycloakAdmin(
server_url=os.getenv("KEYCLOAK_SERVER_URL"),
username=os.getenv("KEYCLOAK_ADMIN_USERNAME"),
password=get_keycloak_password(),
realm_name=os.getenv("KEYCLOAK_REALM_NAME"),
client_secret_key=os.getenv("KEYCLOAK_CLIENT_SECRET_KEY"),
verify=(os.getenv("KEYCLOAK_VERIFY").lower() == "true"),
server_url = os.getenv("TARANIS_NG_KEYCLOAK_INTERNAL_URL"),
username = os.getenv("KEYCLOAK_ADMIN_USERNAME"),
password = get_keycloak_admin_password(),
realm_name = os.getenv("KEYCLOAK_REALM_NAME"),
client_secret_key = get_keycloak_client_secret_key(),
verify = (os.getenv("KEYCLOAK_VERIFY").lower() == "true"),
)


Expand Down

0 comments on commit 47f08b7

Please sign in to comment.