Adding authentication to Kubernetes app using Keycloak and the new oauth2-proxy

Configuring Keycloak

Go to the left-side menu item “Client Scopes” and click “Create”:

Deploying the application

Blablabla…

apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
- name: oauth2-proxy
image: carlosedp/oauth2-proxy:v7.0.0
imagePullPolicy: Always
args:
- --config=/etc/oauth2-proxy.cfg
ports:
- containerPort: 3000
name: web
volumeMounts:
- name: oauth2-proxy-config
mountPath: /etc/oauth2-proxy.cfg
subPath: oauth2-proxy.cfg
- name: oauth2-templates
mountPath: /templates
volumes:
- name: oauth2-proxy-config
configMap:
name: oauth2-proxy-config
- name: oauth2-templates
configMap:
name: oauth2-templates
---
apiVersion: v1
kind: ConfigMap
metadata:
name: oauth2-proxy-config
namespace: default
data:
oauth2-proxy.cfg: |+
# Provider config
provider="keycloak"
provider_display_name="Keycloak"
login_url="https://keycloak.192.168.1.170.nip.io:8443/auth/realms/Kubeapps/protocol/openid-connect/auth"
redeem_url="https://keycloak.192.168.1.170.nip.io:8443/auth/realms/Kubeapps/protocol/openid-connect/token"
validate_url="https://keycloak.192.168.1.170.nip.io:8443/auth/realms/Kubeapps/protocol/openid-connect/userinfo"
ssl_insecure_skip_verify=true
# Client config
client_id="kubernetes"
client_secret="f6c21649-9972-4da9-8f47-d66b64d207d1"
cookie_secret="OQINaROshtE9TcZkNAm5Zs2Pv3xaWytBmc5W7sPX7ws="
cookie_secure="false"
# Upstream config
http_address="0.0.0.0:3000"
upstreams="http://127.0.0.1:80/"
# Proxy Config
keycloak_group="/app1grp"
#user_id_claim="preferred_username"
skip_auth_routes=["/health.*"]
skip_provider_button="true"
reverse_proxy="true"
email_domains=["*"]
cookie_domains=[".nip.io"]
whitelist_domains=[".nip.io:*"]
custom_templates_dir="/templates"
---
apiVersion: v1
kind: ConfigMap
metadata:
name: oauth2-templates
namespace: default
data:
sign_in.html: |+
<!DOCTYPE html> <html lang="en" charset="utf-8"> <head> <title>Sign In</title> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> <style>body{font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; font-size: 14px; line-height: 1.42857143; color: #333; background: #f0f0f0;}.signin{display:block; margin:20px auto; max-width:400px; background: #fff; border:1px solid #ccc; border-radius: 10px; padding: 20px;}.center{text-align:center;}.btn{color: #fff; background-color: #428bca; border: 1px solid #357ebd; -webkit-border-radius: 4; -moz-border-radius: 4; border-radius: 4px; font-size: 14px; padding: 6px 12px; text-decoration: none; cursor: pointer;}.btn:hover{background-color: #3071a9; border-color: #285e8e; text-decoration: none;}label{display: inline-block; max-width: 100%; margin-bottom: 5px; font-weight: 700;}input{display: block; width: 100%; height: 34px; padding: 6px 12px; font-size: 14px; line-height: 1.42857143; color: #555; background-color: #fff; background-image: none; border: 1px solid #ccc; border-radius: 4px; -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075); box-shadow: inset 0 1px 1px rgba(0,0,0,.075); -webkit-transition: border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s; -o-transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s; transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s; margin:0; box-sizing: border-box;}footer{display:block; font-size:10px; color:#aaa; text-align:center; margin-bottom:10px;}footer a{display:inline-block; height:25px; line-height:25px; color:#aaa; text-decoration:underline;}footer a:hover{color:#aaa;}</style> </head> <body> <div class="signin center"> <form method="GET" action="{{.ProxyPrefix}}/start"> <input type="hidden" name="rd" value="{{.Redirect}}">{{if .SignInMessage}}<p>{{.SignInMessage}}</p>{{end}}<button type="submit" class="btn">Sign in with{{.ProviderName}}</button><br/> </form> </div>{{if .CustomLogin}}<div class="signin"> <form method="POST" action="{{.ProxyPrefix}}/sign_in"> <input type="hidden" name="rd" value="{{.Redirect}}"> <label for="username">Username:</label><input type="text" name="username" id="username" size="10"><br/> <label for="password">Password:</label><input type="password" name="password" id="password" size="10"><br/> <button type="submit" class="btn">Sign In</button> </form> </div>{{end}}<script>if (window.location.hash){(function(){var inputs=document.getElementsByName('rd'); for (var i=0; i < inputs.length; i++){// Add hash, but make sure it is only added once var idx=inputs[i].value.indexOf('#'); if (idx >=0){// Remove existing hash from URL inputs[i].value=inputs[i].value.substr(0, idx);}inputs[i].value +=window.location.hash;}})();}</script> <footer>{{if eq .Footer "-"}}{{else if eq .Footer ""}}Secured with <a href="https://github.com/oauth2-proxy/oauth2-proxy#oauth2_proxy">OAuth2 Proxy</a> version{{.Version}}{{else}}{{.Footer}}{{end}}</footer> </body> </html>
error.html: |+
<html lang="en"><head> <title>Access Forbidden</title><style>*{font-family: "Courier", "Courier New", "sans-serif"; margin:0; padding: 0;}body{background: #233142;}.whistle{width: 20%; fill: #f95959; margin: 100px 40%; text-align: left; transform: translate(-50%, -50%); transform: rotate(0); transform-origin: 80% 30%; animation: wiggle .2s infinite;}@keyframes wiggle{0%{transform: rotate(3deg);}50%{transform: rotate(0deg);}100%{transform: rotate(3deg);}}h1{margin-top: -100px; margin-bottom: 20px; color: #facf5a; text-align: center; font-size: 90px; font-weight: 800;}h2, a{color: #455d7a; text-align: center; font-size: 30px; text-transform: uppercase;}</style> </head><body> <use> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve" class="whistle"><g><g transform="translate(0.000000,511.000000) scale(0.100000,-0.100000)"><path d="M4295.8,3963.2c-113-57.4-122.5-107.2-116.8-622.3l5.7-461.4l63.2-55.5c72.8-65.1,178.1-74.7,250.8-24.9c86.2,61.3,97.6,128.3,97.6,584c0,474.8-11.5,526.5-124.5,580.1C4393.4,4001.5,4372.4,4001.5,4295.8,3963.2z"/><path d="M3053.1,3134.2c-68.9-42.1-111-143.6-93.8-216.4c7.7-26.8,216.4-250.8,476.8-509.3c417.4-417.4,469.1-463.4,526.5-463.4c128.3,0,212.5,88.1,212.5,224c0,67-26.8,97.6-434.6,509.3c-241.2,241.2-459.5,449.9-488.2,465.3C3181.4,3180.1,3124,3178.2,3053.1,3134.2z"/><path d="M2653,1529.7C1644,1445.4,765.1,850,345.8-32.7C62.4-628.2,22.2-1317.4,234.8-1960.8C451.1-2621.3,947-3186.2,1584.6-3500.2c1018.6-501.6,2228.7-296.8,3040.5,515.1c317.8,317.8,561,723.7,670.1,1120.1c101.5,369.5,158.9,455.7,360,553.3c114.9,57.4,170.4,65.1,1487.7,229.8c752.5,93.8,1392,181.9,1420.7,193.4C8628.7-857.9,9900,1250.1,9900,1328.6c0,84.3-67,172.3-147.4,195.3c-51.7,15.3-790.8,19.1-2558,15.3l-2487.2-5.7l-55.5-63.2l-55.5-61.3v-344.6V719.8h-411.7h-411.7v325.5c0,509.3,11.5,499.7-616.5,494C2921,1537.3,2695.1,1533.5,2653,1529.7z"/></g></g></svg></use><h1>403</h1><h2>Not this time, access forbidden!</h2><h2><a href="{{.ProxyPrefix}}/sign_out?rd=https://keycloak.192.168.1.170.nip.io:8443/auth/realms/Kubeapps/protocol/openid-connect/logout?redirect_uri=https://google.com">Logout</h2></body></html>
---
apiVersion: v1
kind: Service
metadata:
labels:
app: nginx
name: nginx
namespace: default
spec:
ports:
- name: http
port: 80
protocol: TCP
targetPort: web
selector:
app: nginx
type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx
namespace: default
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: test.192.168.1.170.nip.io
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx
port:
number: 80

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Carlos Eduardo

Carlos Eduardo

Writing everything cloud and all the tech behind it. If you like my projects and would like to support me, check my Patreon on https://www.patreon.com/carlosedp