Skip to content
This repository was archived by the owner on Feb 16, 2024. It is now read-only.

Commit 5748894

Browse files
fhennigsbernauer
andauthored
OpenID & OPA PoC Demo (#283)
* WIP, it somehow works wuhu :) * Added trino * Added druid * got it working * Some cleanup * renamed stack, added description, fixed trino policy * Added resource requests * Added more desc. * checked namespaces * incorporate review: opa, zk * switched druid to psql * some druid cleanup, keycloak comments * don't create druid_sytem user in keycloak * Enable TLS in druid * changes * Update stacks/keycloak-opa-poc/policies.yaml Co-authored-by: Sebastian Bernauer <[email protected]> * Update stacks/keycloak-opa-poc/policies.yaml Co-authored-by: Sebastian Bernauer <[email protected]> --------- Co-authored-by: Sebastian Bernauer <[email protected]>
1 parent b84eec8 commit 5748894

File tree

11 files changed

+698
-0
lines changed

11 files changed

+698
-0
lines changed

stacks/keycloak-opa-poc/druid.yaml

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
---
2+
apiVersion: druid.stackable.tech/v1alpha1
3+
kind: DruidCluster
4+
metadata:
5+
name: druid
6+
spec:
7+
image:
8+
productVersion: 26.0.0
9+
stackableVersion: 23.7.0
10+
clusterConfig:
11+
listenerClass: external-unstable
12+
deepStorage:
13+
hdfs:
14+
configMapName: hdfs
15+
directory: /data
16+
metadataStorageDatabase:
17+
dbType: postgresql
18+
connString: jdbc:postgresql://postgresql-druid/druid
19+
host: postgresql-druid
20+
port: 5432
21+
user: druid
22+
password: druid
23+
zookeeperConfigMapName: druid-znode
24+
authorization:
25+
opa:
26+
configMapName: opa
27+
package: druid
28+
brokers:
29+
roleGroups:
30+
default:
31+
replicas: 1
32+
podOverrides: &pod-overrides
33+
spec:
34+
containers:
35+
- name: druid
36+
env:
37+
- name: KEYCLOAK_DISCOVERY_URL
38+
valueFrom:
39+
configMapKeyRef:
40+
name: keycloak
41+
key: KEYCLOAK_DISCOVERY_URL
42+
- name: DRUID_CLIENT_SECRET
43+
valueFrom:
44+
secretKeyRef:
45+
name: keycloak-client-secrets
46+
key: druid
47+
- name: DRUID_COOKIE_PASSPHRASE
48+
valueFrom:
49+
secretKeyRef:
50+
name: keycloak-client-secrets
51+
key: druidCookiePassphrase
52+
- name: DRUID_SYSTEM_USER_PASSWORD
53+
valueFrom:
54+
secretKeyRef:
55+
name: keycloak-client-secrets
56+
key: druidSystemUserPassword
57+
configOverrides:
58+
runtime.properties: &runtime-properties
59+
druid.extensions.loadList: >-
60+
["postgresql-metadata-storage",
61+
"simple-client-sslcontext",
62+
"druid-kafka-indexing-service",
63+
"druid-datasketches",
64+
"prometheus-emitter",
65+
"druid-basic-security",
66+
"druid-opa-authorizer",
67+
"druid-hdfs-storage",
68+
"druid-pac4j"]
69+
70+
# basic authenticator needed for internal authentication among Druid processes
71+
# Trying to use the pac4j authenticator in the escalator below leads to 302 errors,
72+
# it seems like the Druid processes cannot handle the OIDC authentication flow.
73+
druid.auth.authenticator.MyBasicMetadataAuthenticator.type: basic
74+
druid.auth.authenticator.MyBasicMetadataAuthenticator.initialInternalClientPassword: '${env:DRUID_SYSTEM_USER_PASSWORD}' # Default password for internal 'druid_system' user
75+
druid.auth.authenticator.MyBasicMetadataAuthenticator.skipOnFailure: "true" # for any non system user, skip to the pac4j authenticator
76+
druid.auth.authenticator.MyBasicMetadataAuthenticator.authorizerName: OpaAuthorizer
77+
78+
# pac4j authenticator
79+
druid.auth.authenticator.pac4j.type: pac4j
80+
druid.auth.authenticator.pac4j.authorizerName: OpaAuthorizer
81+
# pac4j common config
82+
druid.auth.pac4j.cookiePassphrase: '${env:DRUID_COOKIE_PASSPHRASE}'
83+
# OIDC common config
84+
druid.auth.pac4j.oidc.clientID: druid
85+
druid.auth.pac4j.oidc.clientSecret: '{"type":"environment","variable":"DRUID_CLIENT_SECRET"}'
86+
druid.auth.pac4j.oidc.discoveryURI: '${env:KEYCLOAK_DISCOVERY_URL}'
87+
# druid.auth.pac4j.oidc.oidcClaim: preferred_username # setting doesn't work, but should?
88+
89+
druid.auth.authenticatorChain: '["MyBasicMetadataAuthenticator","pac4j"]'
90+
91+
druid.escalator.type: basic
92+
druid.escalator.internalClientUsername: druid_system
93+
druid.escalator.internalClientPassword: '{"type":"environment","variable":"DRUID_SYSTEM_USER_PASSWORD"}'
94+
druid.escalator.authorizerName: OpaAuthorizer
95+
coordinators:
96+
roleGroups:
97+
default:
98+
replicas: 1
99+
podOverrides: *pod-overrides
100+
configOverrides:
101+
runtime.properties: *runtime-properties
102+
historicals:
103+
roleGroups:
104+
default:
105+
replicas: 1
106+
podOverrides: *pod-overrides
107+
configOverrides:
108+
runtime.properties: *runtime-properties
109+
middleManagers:
110+
roleGroups:
111+
default:
112+
replicas: 1
113+
podOverrides: *pod-overrides
114+
configOverrides:
115+
runtime.properties: *runtime-properties
116+
routers:
117+
roleGroups:
118+
default:
119+
replicas: 1
120+
podOverrides: *pod-overrides
121+
configOverrides:
122+
runtime.properties: *runtime-properties

stacks/keycloak-opa-poc/hdfs.yaml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
apiVersion: hdfs.stackable.tech/v1alpha1
3+
kind: HdfsCluster
4+
metadata:
5+
name: hdfs
6+
spec:
7+
image:
8+
productVersion: 3.3.4
9+
stackableVersion: 23.7.0
10+
clusterConfig:
11+
dfsReplication: 1
12+
zookeeperConfigMapName: hdfs-znode
13+
nameNodes:
14+
roleGroups:
15+
default:
16+
replicas: 2
17+
dataNodes:
18+
roleGroups:
19+
default:
20+
replicas: 1
21+
journalNodes:
22+
roleGroups:
23+
default:
24+
replicas: 1

stacks/keycloak-opa-poc/keycloak.yaml

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
---
2+
apiVersion: apps/v1
3+
kind: Deployment
4+
metadata:
5+
name: keycloak
6+
labels:
7+
app: keycloak
8+
spec:
9+
replicas: 1
10+
selector:
11+
matchLabels:
12+
app: keycloak
13+
template:
14+
metadata:
15+
labels:
16+
app: keycloak
17+
spec:
18+
containers:
19+
- name: keycloak
20+
image: quay.io/keycloak/keycloak:22.0.3
21+
# Keycloak is running in development mode: https://www.keycloak.org/server/configuration#_starting_keycloak
22+
# production mode disables HTTP and requires a TLS configuration, which is currently very difficult to configure
23+
# given that we're running on a NodePort
24+
args: ["start-dev"]
25+
env:
26+
- name: KEYCLOAK_ADMIN
27+
value: admin
28+
- name: KEYCLOAK_ADMIN_PASSWORD
29+
valueFrom:
30+
secretKeyRef:
31+
name: keycloak-admin-credentials
32+
key: admin
33+
ports:
34+
- name: http
35+
containerPort: 8080
36+
readinessProbe:
37+
httpGet:
38+
path: /realms/master
39+
port: 8080
40+
---
41+
apiVersion: v1
42+
kind: Service
43+
metadata:
44+
name: keycloak
45+
labels:
46+
app: keycloak
47+
spec:
48+
type: NodePort
49+
selector:
50+
app: keycloak
51+
ports:
52+
- name: http
53+
port: 8080
54+
targetPort: 8080
55+
---
56+
apiVersion: v1
57+
kind: Secret
58+
metadata:
59+
name: keycloak-admin-credentials
60+
stringData:
61+
admin: "{{ keycloakAdminPassword }}"
62+
---
63+
# This job creates a ConfigMap with connection info for Keycloak
64+
apiVersion: batch/v1
65+
kind: Job
66+
metadata:
67+
name: propagate-keycloak-address
68+
spec:
69+
template:
70+
spec:
71+
containers:
72+
- name: propagate-keycloak-address
73+
image: docker.stackable.tech/stackable/testing-tools:0.2.0-stackable0.0.0-dev # We need 0.0.0-dev, so we get kubectl
74+
command:
75+
- bash
76+
- -x
77+
- -euo
78+
- pipefail
79+
- -c
80+
- |
81+
echo "Determining Keycloak public reachable address"
82+
KEYCLOAK_ADDRESS=$(kubectl get svc keycloak -o json | jq -r --argfile endpoints <(kubectl get endpoints keycloak -o json) --argfile nodes <(kubectl get nodes -o json) '($nodes.items[] | select(.metadata.name == $endpoints.subsets[].addresses[].nodeName) | .status.addresses | map(select(.type == "ExternalIP" or .type == "InternalIP")) | min_by(.type) | .address | tostring) + ":" + (.spec.ports[] | select(.name == "http") | .nodePort | tostring)')
83+
echo "Found Keycloak running at $KEYCLOAK_ADDRESS"
84+
85+
echo "Writing Keycloak address to ConfigMap keycloak"
86+
kubectl create configmap keycloak --from-literal="KEYCLOAK=$KEYCLOAK_ADDRESS" --from-literal="KEYCLOAK_DISCOVERY_URL=http://$KEYCLOAK_ADDRESS/realms/master/.well-known/openid-configuration" -o yaml --dry-run | kubectl apply -f -
87+
serviceAccountName: demo-serviceaccount
88+
restartPolicy: OnFailure
89+
backoffLimit: 20 # give some time for the Keycloak to be available

stacks/keycloak-opa-poc/opa.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
apiVersion: opa.stackable.tech/v1alpha1
3+
kind: OpaCluster
4+
metadata:
5+
name: opa
6+
spec:
7+
image:
8+
productVersion: "0.51.0"
9+
stackableVersion: "23.7.0"
10+
servers:
11+
roleGroups:
12+
default: {}

stacks/keycloak-opa-poc/policies.yaml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
---
2+
apiVersion: v1
3+
kind: ConfigMap
4+
metadata:
5+
name: opa-bundle-trino
6+
labels:
7+
opa.stackable.tech/bundle: "true"
8+
data:
9+
trino.rego: |
10+
package trino
11+
import future.keywords.in
12+
13+
default allow = false
14+
15+
allow {
16+
input.context.identity.user in ["alice", "admin"]
17+
}
18+
19+
allow {
20+
input.action.operation == "ImpersonateUser"
21+
input.action.resource.user.name == input.context.identity.user
22+
}
23+
---
24+
apiVersion: v1
25+
kind: ConfigMap
26+
metadata:
27+
name: opa-bundle-druid
28+
labels:
29+
opa.stackable.tech/bundle: "true"
30+
data:
31+
druid.rego: |
32+
package druid
33+
import data.bundles.opagroups.admins
34+
import future.keywords.in
35+
import future.keywords.if
36+
37+
default allow = false
38+
39+
allow if input.user in admins
40+
41+
allow if input.user == "druid_system"
42+
# A CM like this is created by the setup keycloak Job
43+
# It is used for Druid roles, as we currently need to write them based on the user uuids.
44+
# ---
45+
# apiVersion: v1
46+
# kind: ConfigMap
47+
# metadata:
48+
# name: opagroups
49+
# labels:
50+
# opa.stackable.tech/bundle: "true"
51+
# data:
52+
# data.json: |
53+
# {
54+
# "admins": [
55+
# "57d3b407-ecc0-4cc1-aaaf-45a63f43b96b",
56+
# "170b4130-ca4d-417b-b229-f2917d5ab3d1"
57+
# ]
58+
# }
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
---
2+
apiVersion: v1
3+
kind: ServiceAccount
4+
metadata:
5+
name: demo-serviceaccount
6+
namespace: default
7+
---
8+
apiVersion: rbac.authorization.k8s.io/v1
9+
kind: ClusterRoleBinding
10+
metadata:
11+
name: demo-clusterrolebinding
12+
subjects:
13+
- kind: ServiceAccount
14+
name: demo-serviceaccount
15+
namespace: default
16+
roleRef:
17+
kind: ClusterRole
18+
name: demo-clusterrole
19+
apiGroup: rbac.authorization.k8s.io
20+
---
21+
apiVersion: rbac.authorization.k8s.io/v1
22+
kind: ClusterRole
23+
metadata:
24+
name: demo-clusterrole
25+
rules:
26+
- apiGroups:
27+
- ""
28+
resources:
29+
- nodes
30+
- services
31+
- endpoints
32+
verbs:
33+
- get
34+
- list
35+
- watch
36+
- apiGroups:
37+
- ""
38+
resources:
39+
- configmaps
40+
verbs:
41+
- get
42+
- list
43+
- watch
44+
- create
45+
- patch

0 commit comments

Comments
 (0)