Skip to content

Commit

Permalink
Merge pull request #274 from slapcat/identity-platform
Browse files Browse the repository at this point in the history
add identity-platform bundle
  • Loading branch information
dosaboy authored Dec 12, 2024
2 parents 921ee98 + 03fc673 commit 649cad2
Show file tree
Hide file tree
Showing 15 changed files with 276 additions and 0 deletions.
4 changes: 4 additions & 0 deletions common/ch_channel_map/any_series
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,9 @@ for c in ${CEPH_CHARMS[@]}; do
CHARM_CHANNEL[$c]=$ceph_release/edge
done

for c in ${IAM_CHARMS[@]}; do
CHARM_CHANNEL[$c]=latest/edge
done

CHARM_CHANNEL[pacemaker-remote]=${series}/edge
CHARM_CHANNEL[microk8s]=1.28/stable
11 changes: 11 additions & 0 deletions common/charm_lists
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,14 @@ prometheus
ro
zookeeper
)

declare -a IAM_CHARMS=(
hydra
identity-platform-login-ui-operator
kratos
kratos-external-idp-integrator
oathkeeper
postgresql-k8s
self-signed-certificates
traefik-k8s
)
21 changes: 21 additions & 0 deletions identity-platform/authentik-values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
authentik:
secret_key: "my-secure-secret-key"
error_reporting:
enabled: false
postgresql:
password: "my-secure-psql-password"
bootstrap_token: "my-secure-bootstrap-token"
bootstrap_password: "Passw0rd"
server:
ingress:
ingressClassName: nginx
enabled: false
hosts:
- authentik.secloud
postgresql:
enabled: true
auth:
password: "my-secure-psql-password"
redis:
enabled: true

1 change: 1 addition & 0 deletions identity-platform/common
74 changes: 74 additions & 0 deletions identity-platform/configure
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#!/bin/bash

# Reset
if [[ "$1" == "reset" ]]; then
helm uninstall authentik -n authentik
kubectl delete pvc -n authentik data-authentik-postgresql-0 redis-data-authentik-redis-master-0
fi

# Check for kratos-external-idp-integrator
if [ "$(juju status --format json| jq -r '.applications["kratos-external-idp-integrator"].units|to_entries[]|select(.value["leader"])|.key' 2> /dev/null)" == "" ]; then
echo 'ERROR: Cannot configure OIDC without kratos-external-idp-integrator!'
exit 1
fi

# Install Helm
if ! snap list | grep -q helm; then
sudo snap install helm --classic
fi

# Install authentik
kubectl get ns authentik &> /dev/null || kubectl create ns authentik
https_proxy=http://squid.internal:3128 helm repo add authentik https://charts.goauthentik.io
https_proxy=http://squid.internal:3128 helm repo update
helm install authentik authentik/authentik -f ./authentik-values.yaml -n authentik --version 2024.10.1

timeout=0
echo 'Waiting for Authentik to start...'
up=0
while [[ "$up" != 1 ]]; do
up="$(kubectl get deploy -n authentik authentik-server -o json | jq '.status.readyReplicas')"
if [[ $timeout == 600 ]]; then
echo 'ERROR: Authentik failed to start.'
exit 1
fi
sleep 1
((timeout++))
done

# Prepare port for API calls and wait
kubectl patch svc -n authentik authentik-server -p '{"spec": {"type": "NodePort"}}' || exit 1
AUTH_PORT=$(kubectl get svc -n authentik authentik-server -o jsonpath='{.spec.ports[].nodePort}')
AUTH_IP=$(kubectl get po -n authentik -o json | jq -r '.items[] | select(.metadata.name | test("authentik-server-")) | .status.hostIP')

# Configure OIDC
## get default values
until [ -n "$AUTH_FLOW" ]; do AUTH_FLOW=$(curl -s -X GET -H "accept: application/json" -H "Authorization: Bearer my-secure-bootstrap-token" "http://${AUTH_IP}:${AUTH_PORT}/api/v3/flows/instances/?search=default-authentication-flow" | jq -r '.results[0].pk'); done
until [ -n "$AUTHZ_FLOW" ]; do AUTHZ_FLOW=$(curl -s -X GET -H "accept: application/json" -H "Authorization: Bearer my-secure-bootstrap-token" "http://${AUTH_IP}:${AUTH_PORT}/api/v3/flows/instances/?search=default-provider-authorization-implicit-consent" | jq -r '.results[0].pk'); done
until [ -n "$INVALID_FLOW" ]; do INVALID_FLOW=$(curl -s -X GET -H "accept: application/json" -H "Authorization: Bearer my-secure-bootstrap-token" "http://${AUTH_IP}:${AUTH_PORT}/api/v3/flows/instances/?search=default-invalidation-flow" | jq -r '.results[0].pk'); done
until [ -n "$SIGN_KEY" ]; do SIGN_KEY=$(curl -s -X GET -H "accept: application/json" -H "Authorization: Bearer my-secure-bootstrap-token" "http://${AUTH_IP}:${AUTH_PORT}/api/v3/crypto/certificatekeypairs/" | jq -r '.results[0].pk'); done
until [ -n "$SCOPE" ]; do SCOPE=$(curl -s -X GET -H "accept: application/json" -H "Authorization: Bearer my-secure-bootstrap-token" "http://${AUTH_IP}:${AUTH_PORT}/api/v3/propertymappings/provider/scope/?search=email" | jq -r '.results[0].pk'); done

## create provider
curl -X POST "http://${AUTH_IP}:${AUTH_PORT}/api/v3/providers/oauth2/" -H "Authorization: Bearer my-secure-bootstrap-token" -H "accept: application/json" -H "content-type: application/json" -d "{\"name\":\"oidc-provider\",\"authentication_flow\":\"$AUTH_FLOW\",\"authorization_flow\":\"$AUTHZ_FLOW\",\"invalidation_flow\":\"$INVALID_FLOW\",\"client_type\":\"confidential\",\"client_id\":\"canonical-support\",\"client_secret\":\"my-secure-oidc-secret\",\"access_code_validity\":\"hours=3\",\"access_token_validity\":\"hours=3\",\"refresh_token_validity\":\"hours=3\",\"include_claims_in_id_token\":true,\"redirect_uris\":\"*\",\"sub_mode\":\"hashed_user_id\",\"issuer_mode\":\"per_provider\",\"signing_key\":\"$SIGN_KEY\",\"property_mappings\":[\"$SCOPE\"]}"

## create app
curl -H "Authorization: Bearer my-secure-bootstrap-token" -X POST "http://${AUTH_IP}:${AUTH_PORT}/api/v3/core/applications/" -H "accept: application/json" -H "content-type: application/json" -d '{"name":"canonical-support","slug":"canonical-support","provider":1,"policy_engine_mode":"all"}'

# Configure kratos
juju config kratos-external-idp-integrator provider=generic
juju config kratos-external-idp-integrator client_id=canonical-support
juju config kratos-external-idp-integrator client_secret=my-secure-oidc-secret
juju config kratos-external-idp-integrator issuer_url=http://"${AUTH_IP}:${AUTH_PORT}"/application/o/canonical-support/

echo "
Configuration is complete! You can test a login with the following credentials:
Authentik Dashboard: http://${AUTH_IP}:${AUTH_PORT}
OIDC User: akadmin
Password: Passw0rd"

grafana_url="$(juju run grafana/0 get-admin-password 2> /dev/null | grep url | sed -e 's/url: //')"
if [[ -n $grafana_url ]]; then
echo "Grafana Dashboard: $grafana_url"
fi
1 change: 1 addition & 0 deletions identity-platform/generate-bundle.sh
72 changes: 72 additions & 0 deletions identity-platform/iam.yaml.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
---
bundle: kubernetes
name: identity-platform
website: https://github.com/canonical/iam-bundle
issues: https://github.com/canonical/iam-bundle/issues
applications:
hydra:
charm: __CHARM_STORE____CHARM_CS_NS____CHARM_CH_PREFIX__hydra
scale: 1
series: jammy
trust: true
identity-platform-login-ui-operator:
charm: __CHARM_STORE____CHARM_CS_NS____CHARM_CH_PREFIX__identity-platform-login-ui-operator
scale: 1
series: jammy
trust: true
kratos:
charm: __CHARM_STORE____CHARM_CS_NS____CHARM_CH_PREFIX__kratos
scale: 1
series: jammy
options:
enforce_mfa: false
trust: true
oathkeeper:
charm: __CHARM_STORE____CHARM_CS_NS____CHARM_CH_PREFIX__oathkeeper
scale: 1
series: jammy
trust: true
postgresql-k8s:
charm: __CHARM_STORE____CHARM_CS_NS____CHARM_CH_PREFIX__postgresql-k8s
scale: 1
series: jammy
options:
plugin_btree_gin_enable: true
plugin_pg_trgm_enable: true
storage:
pgdata: kubernetes,1,1024M
trust: true
self-signed-certificates:
charm: __CHARM_STORE____CHARM_CS_NS____CHARM_CH_PREFIX__self-signed-certificates
scale: 1
traefik-admin:
charm: __CHARM_STORE____CHARM_CS_NS____CHARM_CH_PREFIX__traefik-k8s
scale: 1
series: focal
storage:
configurations: kubernetes,1,1024M
trust: true
traefik-public:
charm: __CHARM_STORE____CHARM_CS_NS____CHARM_CH_PREFIX__traefik-k8s
scale: 1
series: focal
options:
enable_experimental_forward_auth: true
storage:
configurations: kubernetes,1,1024M
trust: true
relations:
- [hydra:pg-database, postgresql-k8s:database]
- [kratos:pg-database, postgresql-k8s:database]
- [kratos:hydra-endpoint-info, hydra:hydra-endpoint-info]
- [hydra:admin-ingress, traefik-admin:ingress]
- [hydra:public-ingress, traefik-public:ingress]
- [kratos:admin-ingress, traefik-admin:ingress]
- [kratos:public-ingress, traefik-public:ingress]
- [identity-platform-login-ui-operator:ingress, traefik-public:ingress]
- [identity-platform-login-ui-operator:hydra-endpoint-info, hydra:hydra-endpoint-info]
- [identity-platform-login-ui-operator:ui-endpoint-info, hydra:ui-endpoint-info]
- [identity-platform-login-ui-operator:ui-endpoint-info, kratos:ui-endpoint-info]
- [identity-platform-login-ui-operator:kratos-info, kratos:kratos-info]
- [traefik-admin:certificates, self-signed-certificates:certificates]
- [traefik-public:certificates, self-signed-certificates:certificates]
9 changes: 9 additions & 0 deletions identity-platform/module_defaults
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# This file must contain defaults for all variables used in bundles/overlays.
# They are used to render to final product in the event they are not provided
# elsewhere. It is inserted into the global context at the start of the
# pipeline.
#
# You can check that none are missing by running lint/check_var_defaults.sh
#
JUJU_DEPLOY_OPTS=" --trust"
CHARM_CHANNEL[postgresql-k8s]=14/stable
1 change: 1 addition & 0 deletions identity-platform/overlays
22 changes: 22 additions & 0 deletions identity-platform/pipeline/00setup
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/bin/bash

# Globals
export MOD_NAME=identity-platform
export MOD_BASE_TEMPLATE=iam.yaml.template
export MOD_SSL_STATE_DIR=${MOD_NAME}
[ -n "${MASTER_OPTS[BUNDLE_NAME]}" ] && \
MOD_SSL_STATE_DIR="${MOD_SSL_STATE_DIR}-${MASTER_OPTS[BUNDLE_NAME]}"

# opts that 02configure does not recognise that get passed to the generator
export -a MOD_PASSTHROUGH_OPTS=()

# Collection of messages to display at the end
export -A MOD_MSGS=()
# Use order 0 to ensure this is first displayed
MOD_MSGS[0_common.0]="Ensure a LoadBalancer (e.g. MetalLB or Cilium) is enabled on k8s"
MOD_MSGS[0_common.2]="Configure a local user: juju run kratos/0 create-admin-account [email protected] password=Passw0rd username=admin"

# Array list of overlays to use with this deployment.
export -a MOD_OVERLAYS=()

export -A MOD_PARAMS=()
2 changes: 2 additions & 0 deletions identity-platform/pipeline/01import-config-defaults
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Current module imports
. $MOD_DIR/module_defaults
33 changes: 33 additions & 0 deletions identity-platform/pipeline/02configure
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/bin/bash
# Global variables are first defined in 00setup and module
# dependencies are defined in 01import-config-defaults
#
# All overlay/bundle variables (MOD_PARAMS) defaults must go into
# the <module>/module_defaults file.

cloud="$(get_cloud_type)"
if [[ "$cloud" != "k8s" ]]; then
echo "ERROR: Must switch to a Kubernetes model first."
exit 1
fi

while (($# > 0))
do
case $1 in
--oidc)
MOD_OVERLAYS+=( "kubernetes/k8s-iam-oidc.yaml" )
MOD_MSGS[0_common.1]="Setup OIDC: ./configure"
;;
--grafana)
MOD_OVERLAYS+=( "kubernetes/k8s-iam-grafana.yaml" )
MOD_MSGS[grafana.0]="Get Grafana URL: juju run grafana/leader get-admin-password"
;;
*)
echo "ERROR: invalid input '$1'"
_usage
exit 1
;;
esac
shift
done

5 changes: 5 additions & 0 deletions identity-platform/pipeline/03build
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/bash
. $MOD_DIR/common/generate_bundle_base

print_msgs

11 changes: 11 additions & 0 deletions overlays/kubernetes/k8s-iam-grafana.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
applications:
grafana:
charm: __CHARM_STORE____CHARM_CS_NS____CHARM_CH_PREFIX__grafana-k8s
scale: 1
series: focal
storage:
database: kubernetes,1,1024M
relations:
- [grafana:ingress, traefik-public:traefik-route]
- [grafana:oauth, hydra:oauth]
- [grafana:receive-ca-cert, self-signed-certificates:send-ca-cert]
9 changes: 9 additions & 0 deletions overlays/kubernetes/k8s-iam-oidc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
applications:
kratos-external-idp-integrator:
charm: __CHARM_STORE____CHARM_CS_NS____CHARM_CH_PREFIX__kratos-external-idp-integrator
scale: 1
series: jammy
options:
provider: generic
relations:
- [kratos-external-idp-integrator:kratos-external-idp, kratos:kratos-external-idp]

0 comments on commit 649cad2

Please sign in to comment.