Skip to content

Instantly share code, notes, and snippets.

@iul1an
Created July 17, 2024 21:36
Show Gist options
  • Save iul1an/ea0fc2125ae70fcc6a6e071a754503e1 to your computer and use it in GitHub Desktop.
Save iul1an/ea0fc2125ae70fcc6a6e071a754503e1 to your computer and use it in GitHub Desktop.
POC - Dex with LDAP connector - not meant for production, only for testing purposes
---
apiVersion: v1
kind: Namespace
metadata:
name: dex
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: dex
namespace: dex
---
apiVersion: v1
kind: ConfigMap
metadata:
name: ldap-ldif
namespace: dex
data:
ldap.ldif: |
# Users definitions.
dn: ou=People,dc=example,dc=org
objectClass: organizationalUnit
ou: People
dn: cn=bob,ou=People,dc=example,dc=org
objectClass: person
objectClass: inetOrgPerson
sn: bob
cn: bob
mail: bob@example.com
userpassword: bob
dn: cn=alice,ou=People,dc=example,dc=org
objectClass: person
objectClass: inetOrgPerson
sn: alice
cn: alice
mail: alice@example.com
userpassword: alice
# Group definitions.
dn: ou=Groups,dc=example,dc=org
objectClass: organizationalUnit
ou: Groups
dn: cn=developers,ou=Groups,dc=example,dc=org
objectClass: groupOfNames
cn: developers
member: cn=bob,ou=People,dc=example,dc=org
dn: cn=devops,ou=Groups,dc=example,dc=org
objectClass: groupOfNames
cn: devops
member: cn=alice,ou=People,dc=example,dc=org
---
apiVersion: v1
kind: Secret
metadata:
name: dex
namespace: dex
type: Opaque
stringData:
config.yaml: |-
connectors:
- type: ldap
name: OpenLDAP
id: ldap
config:
host: localhost:389
insecureNoSSL: true
bindDN: cn=admin,dc=example,dc=org
bindPW: admin
usernamePrompt: Email Address
userSearch:
baseDN: ou=People,dc=example,dc=org
filter: "(objectClass=person)"
username: mail
idAttr: DN
emailAttr: mail
nameAttr: cn
groupSearch:
baseDN: ou=Groups,dc=example,dc=org
filter: "(objectClass=groupOfNames)"
userMatchers:
- userAttr: DN
groupAttr: member
nameAttr: cn
issuer: http://dex.example.com/api/dex
oauth2:
responseTypes:
- code
- id_token
- token
skipApprovalScreen: true
staticClients:
- id: test
name: test
redirectURIs:
- http://localhost:5000/callback
secret: test
storage:
type: memory
---
apiVersion: v1
kind: Service
metadata:
name: dex
namespace: dex
spec:
type: ClusterIP
ports:
- name: http
port: 5956
targetPort: http
protocol: TCP
appProtocol: http
- name: grpc
port: 5957
targetPort: grpc
protocol: TCP
appProtocol: http
- name: telemetry
port: 5958
targetPort: telemetry
protocol: TCP
appProtocol: http
selector:
app.kubernetes.io/name: dex
app.kubernetes.io/instance: dex
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: dex
labels:
app.kubernetes.io/name: dex
app.kubernetes.io/instance: dex
namespace: dex
spec:
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
app.kubernetes.io/name: dex
app.kubernetes.io/instance: dex
template:
metadata:
annotations: {}
labels:
app.kubernetes.io/name: dex
app.kubernetes.io/instance: dex
spec:
serviceAccountName: dex
enableServiceLinks: false
containers:
- name: dex
image: "ghcr.io/dexidp/dex:v2.40.0"
imagePullPolicy: IfNotPresent
args:
- dex
- serve
- --web-http-addr
- 0.0.0.0:5956
- --grpc-addr
- 0.0.0.0:5957
- --telemetry-addr
- 0.0.0.0:5958
- /etc/dex/config.yaml
env:
ports:
- name: http
containerPort: 5956
protocol: TCP
- name: grpc
containerPort: 5957
protocol: TCP
- name: telemetry
containerPort: 5958
protocol: TCP
livenessProbe:
httpGet:
path: /healthz/live
port: telemetry
readinessProbe:
httpGet:
path: /healthz/ready
port: telemetry
volumeMounts:
- name: dex-config
mountPath: /etc/dex
readOnly: true
- name: ldap
image: osixia/openldap:1.5.0
args:
- "--copy-service"
- "--loglevel"
- "debug"
env:
- name: LDAP_TLS_VERIFY_CLIENT
value: "try"
ports:
- containerPort: 389
name: ldap
volumeMounts:
- name: ldap-ldif
mountPath: /container/service/slapd/assets/config/bootstrap/ldif/ldap.ldif
subPath: ldap.ldif
readOnly: true
volumes:
- name: dex-config
secret:
secretName: dex
- name: ldap-ldif
configMap:
name: ldap-ldif
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: dex
namespace: dex
spec:
ingressClassName: nginx
rules:
- host: "dex.example.com"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: dex
port:
name: http
import os
import json
import webbrowser
from authlib.integrations.requests_client import OAuth2Session
from flask import Flask, request, redirect
import jwt
# Replace these values with your client ID and client secret
CLIENT_ID = 'test'
CLIENT_SECRET = 'test'
AUTHORIZATION_ENDPOINT = 'http://dex.example.com/api/dex/auth'
TOKEN_ENDPOINT = 'http://dex.example.com/api/dex/token'
USERINFO_ENDPOINT = 'http://dex.example.com/api/dex/userinfo'
REDIRECT_URI = 'http://localhost:5000/callback'
SCOPE = 'openid profile email groups'
app = Flask(__name__)
session = OAuth2Session(CLIENT_ID, CLIENT_SECRET, redirect_uri=REDIRECT_URI, scope=SCOPE)
@app.route('/')
def homepage():
claims = {
"id_token": {
"auth_time": {"essential": True},
"acr": {"values": ["urn:mace:incommon:iap:silver"]},
"groups": {"essential": True} # Replace with actual claim needed
},
"userinfo": {
"given_name": {"essential": True},
"family_name": {"essential": True}
}
}
uri, state = session.create_authorization_url(AUTHORIZATION_ENDPOINT, claims=json.dumps(claims))
webbrowser.open(uri)
return f'<h1>Please authorize: <a href="{uri}">Click here to authorize</a></h1>'
@app.route('/callback')
def callback():
token = session.fetch_token(TOKEN_ENDPOINT, authorization_response=request.url)
id_token = token['id_token']
# Decode the ID token
decoded_id_token = jwt.decode(id_token, options={"verify_signature": False})
pretty_id_token = json.dumps(decoded_id_token, indent=4)
userinfo = session.get(USERINFO_ENDPOINT).json()
return f'<h1>Welcome {userinfo["name"]}</h1><p>ID Token: <pre>{pretty_id_token}</pre></p>'
if __name__ == '__main__':
os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1' # Only for development, do not use in production
app.run(debug=True)
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: kind-dex
nodes:
- role: control-plane
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
node-labels: "ingress-ready=true"
extraPortMappings:
- containerPort: 80
hostPort: 80
protocol: TCP
- containerPort: 443
hostPort: 443
protocol: TCP
Authlib==1.3.1
PyJWT==2.8.0
#!/bin/bash
set -eup pipefail
kind create cluster --config=kind-config.yaml
sleep 30
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
kubectl apply -f deployment.yaml
sudo bash -c "echo '127.0.0.1 dex.example.com' >> /etc/hosts"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment