Skip to content

Commit

Permalink
fix: keycloak installation
Browse files Browse the repository at this point in the history
Change-Id: I3f002cf0b31b715974a6de9594e44182a5ce34d0
  • Loading branch information
mtlljm committed Apr 23, 2024
1 parent 42bc59d commit 2d407b2
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 75 deletions.
51 changes: 25 additions & 26 deletions install/grafana.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,20 @@ spec:
requests:
storage: 1Gi
---
kind: Service
apiVersion: v1
metadata:
name: grafana
spec:
selector:
app: grafana
ports:
- name: grafana
protocol: TCP
targetPort: 3000
port: 80
type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
Expand Down Expand Up @@ -77,20 +91,6 @@ spec:
defaultMode: 420
name: grafana-ini
---
kind: Service
apiVersion: v1
metadata:
name: grafana
spec:
selector:
app: grafana
ports:
- name: grafana
protocol: TCP
targetPort: 3000
port: 80
type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
Expand All @@ -103,17 +103,16 @@ metadata:
spec:
ingressClassName: nginx
rules:
- host: TEMPLATE_ESP_DOMAIN
http:
paths:
- path: /grafana
pathType: Prefix
backend:
service:
name: grafana
port:
- host: TEMPLATE_ESP_DOMAIN
http:
paths:
- path: /grafana
pathType: Prefix
backend:
service:
name: grafana
port:
name: grafana
tls:
- hosts:
- "TEMPLATE_ESP_DOMAIN"
secretName: TEMPLATE_OAUTH_CLIENT_SECRET
- hosts:
- "TEMPLATE_ESP_DOMAIN"
135 changes: 86 additions & 49 deletions install/remove-oauth-keycloak.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,48 @@

set -e -o pipefail -o nounset

ESP_NAMESPACE="${1}"
KEYCLOAK_SUBPATH="${KEYCLOAK_SUBPATH:-auth}"

ESP_NAMESPACE="${1}"
function usage() {
echo "Usage: ${0} <esp-namespace> " >&2
exit 1
}

function check_requirements() {
[ -z "${KUBECONFIG-}" ] && {
echo "KUBECONFIG environment variable unset." >&2
exit 1
}

[ -z "${ESP_NAMESPACE-}" ] && {
echo "Usage: ${0} <esp-namespace> <grafana-namespace>" >&2
exit 1
}

[ -z "${KUBECONFIG-}" ] && {
echo "KUBECONFIG environment variable unset." >&2
ESP_DOMAIN=$(kubectl -n "${ESP_NAMESPACE}" get ingress/sas-event-stream-manager-app --output json | jq -r '.spec.rules[0].host')

function check_keycloak_deployment() {
if ! kubectl -n "${ESP_NAMESPACE}" get deployment keycloak-deployment 2>/dev/null 1>&2; then
echo >&2 "ERROR: No Keycloak deployment found under namespace ${ESP_NAMESPACE}."
exit 1
}
fi

[ -z "${ESP_NAMESPACE-}" ] && {
echo "Usage: ${0} <esp-namespace> <grafana-namespace>" >&2
_kc_pod=$(kubectl -n "${ESP_NAMESPACE}" get pods -o json |
jq -r '.items[] | select(.metadata.name | test("^keycloak-deployment-")) | .metadata.name')
[ -n "${_kc_pod}" ] || {
echo >&2 "ERROR: No keycloak-deployment-* pod found under namespace ${ESP_NAMESPACE}."
exit 1
}

if ! kubectl get namespace "${ESP_NAMESPACE}" 2>/dev/null 1>&2; then
echo >&2 "ERROR: Namespace ${ESP_NAMESPACE} not found."
_kc_ready=$(kubectl -n "${ESP_NAMESPACE}" get pod "${_kc_pod}" -o json |
jq -r '.status.conditions[] | select(.type == "Ready") | .status')
[ "${_kc_ready}" == 'True' ] || {
echo >&2 "ERROR: Keycloak deployment exists but is not ready. Try again later."
exit 1
fi
}
}

function check_requirements() {

if ! kubectl -n "${ESP_NAMESPACE}" get secret keycloak-admin-secret 2>/dev/null 1>&2; then
echo >&2 "ERROR: No Keycloak admin secret found under namespace ${ESP_NAMESPACE}."
Expand All @@ -32,71 +54,86 @@ function check_requirements() {
echo >&2 "ERROR: No OAuth2 Proxy client secret found under namespace ${ESP_NAMESPACE}."
exit 1
fi

check_keycloak_deployment
}

# Fetch access token to perform admin tasks:
function fetch_keycloak_admin_token() {
_resp=$(curl "https://${ESP_DOMAIN}/${KEYCLOAK_SUBPATH}/realms/master/protocol/openid-connect/token" -s -k -X POST \
_resp=$(curl "https://${ESP_DOMAIN}/${KEYCLOAK_SUBPATH}/realms/master/protocol/openid-connect/token" -k -X POST \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'Accept: application/json' \
-d "client_id=admin-cli&grant_type=password&username=${KEYCLOAK_ADMIN}&password=${KEYCLOAK_SECRET}")
-d "client_id=admin-cli" \
-d "grant_type=password" \
-d "username=${KEYCLOAK_ADMIN}" \
--data-urlencode "password=${KEYCLOAK_SECRET}")

echo "${_resp}" | jq -r '.access_token'
}

function delete_role() {
function create_role() {
_role_name="${1}"
curl -s -k -X DELETE \
"https://${ESP_DOMAIN}/${KEYCLOAK_SUBPATH}/admin/realms/sas-esp/clients/${_client_id}/roles/${_role_name}" \
-H "Authorization: Bearer ${_token}"
_role_repr="{\"name\": \"${_role_name}\", \"clientRole\": true}"
curl "https://${ESP_DOMAIN}/${KEYCLOAK_SUBPATH}/admin/realms/sas-esp/clients/${_client_id}/roles" -k -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${_token}" \
-d "${_role_repr}"
}

function remove_protocol_mapper() {
# Get mapper id:
_mappers=$(curl -s -k -X GET "https://${ESP_DOMAIN}/${KEYCLOAK_SUBPATH}/admin/realms/sas-esp/clients/${_client_id}/protocol-mappers/models" -H "Authorization: Bearer ${_token}")
_mapper_id=$(echo "${_mappers}" | jq -r '.[] | select(.name == "GrafanaRoles") | .id')
# Delete mapper:
curl -s -k -X DELETE "https://${ESP_DOMAIN}/${KEYCLOAK_SUBPATH}/admin/realms/sas-esp/clients/${_client_id}/protocol-mappers/models/${_mapper_id}" -H "Authorization: Bearer ${_token}"
function add_protocol_mapper() {
_mapper_repr=$(echo -e "
{
\"name\": \"GrafanaRoles\",
\"protocol\": \"openid-connect\",
\"protocolMapper\": \"oidc-usermodel-client-role-mapper\",
\"consentRequired\": false,
\"config\": {
\"claim.name\": \"grafana_roles\",
\"usermodel.clientRoleMapping.clientId\": \"${OAUTH_CLIENT_ID}\",
\"jsonType.label\": \"String\",
\"multivalued\": \"true\",
\"access.token.claim\": \"true\",
\"userinfo.token.claim\": \"false\",
\"id.token.claim\": \"true\"
}
}")
_mapper_body=$(echo "${_mapper_repr}" | jq -r -c)
curl -k -X POST \
"https://${ESP_DOMAIN}/${KEYCLOAK_SUBPATH}/admin/realms/sas-esp/clients/${_client_id}/protocol-mappers/models" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${_token}" \
-d "${_mapper_body}"
}

function remove_keycloak_roles() {
function prepare_keycloak_roles() {
_token="$(fetch_keycloak_admin_token)"
# Get sas-esp realm clients:
_kc_clients=$(curl -s -k -X GET "https://${ESP_DOMAIN}/${KEYCLOAK_SUBPATH}/admin/realms/sas-esp/clients" -H "Authorization: Bearer ${_token}")
_kc_clients=$(curl -k -X GET "https://${ESP_DOMAIN}/${KEYCLOAK_SUBPATH}/admin/realms/sas-esp/clients" -H "Authorization: Bearer ${_token}")
# Get OAuth2 Proxy client ID:
_client_id=$(echo "${_kc_clients}" | jq -r --arg opid "${OAUTH_CLIENT_ID}" '.[] | select(.clientId == $opid) | .id')
# Delete Grafana roles:
delete_role "grafana-admin"
delete_role "admin"
delete_role "editor"
# Remove Grafana role protocol mapper:
remove_protocol_mapper
# Create Grafana roles:
create_role "grafana-admin"
create_role "admin"
create_role "editor"
# Create Grafana role protocol mapper:
add_protocol_mapper
}

# Fail fast on missing requirements:
check_requirements

echo "Fetching required deployment information..."
ESP_DOMAIN=$(kubectl -n "${ESP_NAMESPACE}" get ingress/sas-event-stream-manager-app --output json | jq -r '.spec.rules[0].host')
export ESP_DOMAIN
_keycloak_admin_secret=$(kubectl -n "${ESP_NAMESPACE}" get secret keycloak-admin-secret --output json)
KEYCLOAK_ADMIN=$(echo "${_keycloak_admin_secret}" | jq -r '.data.username | @base64d')
KEYCLOAK_SECRET=$(echo "${_keycloak_admin_secret}" | jq -r '.data.password | @base64d')

_oauth2_proxy_secret=$(kubectl -n "${ESP_NAMESPACE}" get secret oauth2-proxy-client-secret --output json)
OAUTH_CLIENT_ID=$(echo "${_oauth2_proxy_secret}" | jq -r '.data.OAUTH2_PROXY_CLIENT_ID | @base64d')
export OAUTH_CLIENT_ID

_keycloak_admin_secret=$(kubectl -n "${ESP_NAMESPACE}" get secret keycloak-admin-secret --output json)
KEYCLOAK_ADMIN=$(echo "${_keycloak_admin_secret}" | jq -r '.data.username | @base64d')
export KEYCLOAK_ADMIN
KEYCLOAK_SECRET=$(echo "${_keycloak_admin_secret}" | jq -r '.data.password | @base64d')
export KEYCLOAK_SECRET
OAUTH_CLIENT_SECRET=$(echo "${_oauth2_proxy_secret}" | jq -r '.data.OAUTH2_PROXY_CLIENT_SECRET | @base64d')
export OAUTH_CLIENT_SECRET

cat <<EOF
Deployment details:
ESP domain: ${ESP_DOMAIN}
Keycloak admin user: ${KEYCLOAK_ADMIN}
Keycloak admin secret: ****
OAuth client ID: ${OAUTH_CLIENT_ID}
OAuth details:
ESP Domain: ${ESP_DOMAIN}
OAuth client ID: ${OAUTH_CLIENT_ID}
OAuth client secret: ${OAUTH_CLIENT_SECRET}
EOF

echo "Removing Grafana roles and mapper from Keycloak client..."
remove_keycloak_roles
prepare_keycloak_roles

0 comments on commit 2d407b2

Please sign in to comment.