Skip to content

Commit

Permalink
Istio and OAuth2-Proxy as a layer in front of an app to authenticate…
Browse files Browse the repository at this point in the history
… through OIDC in K8s
  • Loading branch information
seifrajhi committed Jan 24, 2024
1 parent 8d7c4bd commit c19d505
Show file tree
Hide file tree
Showing 305 changed files with 47,912 additions and 12 deletions.
1 change: 1 addition & 0 deletions Istio-Samples/security/psp/sidecar-psp.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# PSP PodSecurityPolicy are removed as of kubernetes v1.25
apiVersion: policy/v1
kind: PodSecurityPolicy
metadata:
Expand Down
131 changes: 131 additions & 0 deletions istio-oauth2-proxy-oidc/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
## Installation

### Installing base application
```
# install namespaces
kubectl apply -f namespaces.yaml
# Install application
kubectl apply -f httpbin-deploy.yaml
```
Now the application should be installed and accessible only through the cluster. Check installation with.
```
kubectl get pods -n demo
kubectl port-forward -n demo svc/httpbin 8000:8000
```
There should be one pod deployed in demo with only 1/1 containers ready. When installing istio there will be a
sidecar added here. Access the application on localhost:8000

### Installing Istio

In this guide I was using Azures AKS which has the option to use the LoadBalancer service type with a static Ip.
If you also use Azure replace the ips in `istio-controlplane.yaml` with your public IP. If you are not using a
provider with support for LoadBalancers you can replace this with NodePorts. An example of this is commented in
the `istio-controlplane.yaml` file. After the config is ready install istio with:

```
kubectl apply -f istio-1.12.1/manifests/charts/base/crds/crd-all.gen.yaml
./istio-1.12.1/bin/istioctl operator init
kubectl apply -f istio-controlplane.yaml
./istio-1.12.1/bin/istioctl verify-install
```


### Installing cert-manager

```
helm repo add jetstack https://charts.jetstack.io
helm repo update
helm install \
cert-manager jetstack/cert-manager \
--namespace cert-manager \
--version v1.4.0 \
--set installCRDs=true \
--set startupapicheck.enabled=false
```

### Create gateways and certificates
Replace `email` in `cluster-issuer.yaml` then replace the occurrences of `httpbin.example.com` with the url
you want to use for your httpbin-app. Do this in both `httpbin-istio-gw.yaml` and `httpbin-tls-cert.yaml`
```
kubectl apply -f cluster-issuer.yaml
kubectl apply -f httpbin-istio-gw.yaml
kubectl apply -f httpbin-tls-cert.yaml
```

### Validate

```
# check pods
kubectl get pods -n cert-manager
kubectl get pods -n demo
# Both should have sidecars and be ready.
kubectl get certificate -n istio-system
```
Visit url.

### Installing Dex

replace `issuer` with the url for your dex and `redirectURIs:` with the url for your app in `dex-values.yaml`.
Then run:

```
helm repo add dex https://charts.dexidp.io
helm repo update
helm install \
--namespace demo \
--values dex-values.yaml \
--version 0.6.5 \
dex dex/dex
```

Replace the occurrences of `dex.example.com` with the url
you want to use for dex. Do this in both `dex-istio-gw.yaml` and `dex-tls-cert.yaml` Then apply with:
```
kubectl apply -f dex-istio-gw.yaml
kubectl apply -f dex-tls-cert.yaml
```

For authentication we can use any IDP which supports OIDC. In this example Dex is installed
which can in turn be connected to other AD sources see our blog post on
[how to connect dex to google](https://elastisys.com/elastisys-engineering-how-to-use-dex-with-google-accounts-to-manage-access-in-kubernetes/)
for more information. In this post we will only use Dex static user as an example.

### Installing oauth2-proxy
Replace `oidc_issuer_url` and `cookie_domains` from `oauth2-proxy-values.yaml` with your domain name then apply with:

```
helm repo add oauth2-proxy https://oauth2-proxy.github.io/manifests
helm repo update
helm install \
--namespace demo \
--values oauth2-proxy-values.yaml \
--version 5.0.6 \
oauth2-proxy oauth2-proxy/oauth2-proxy
```

### Apply authorization policy
Replace `httpbin.example.com` with you app url in `authorization-policy.yaml` then apply with:
```
kubectl apply -f authorization-policy.yaml
```

The authorization policy will trigger when trying to access the hostname configured.
When the policy is triggered it will use the extensionProvider from the `istio-controlplane.yaml` config.
This will cause a redirect to the oauth2-proxy which in turn will go to dex for authentication. Authenticate
with:
```
Username: admin
Password: password
```

### Verify

You should now be able to access the httpbin application again which is now protected by the authentication service.
You can see that the application have received the access_token by going to your app-url and /headers `httpbin.example.com/headers`.
This should now include the `Authorization` header with a jwt-token. You can decode this token to see the information stored there.

### Final words

This guide will make all applications behind the authorization policy have to go through the Oauth2 authentication flow to access these applications.
This provides the security that the user will have to be able to login to your IDP service to access the apps. OBS that this does NOT include authorization which the applications themselves will still have to support.
18 changes: 18 additions & 0 deletions istio-oauth2-proxy-oidc/authorization-policy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: oauth-policy
namespace: istio-system
spec:
selector:
matchLabels:
istio: ingressgateway
action: CUSTOM
provider:
name: "oauth2-proxy"
rules:
# The rules specify when to trigger the external authorizer.
- to:
- operation:
hosts:
- "httpbin.example.com"
18 changes: 18 additions & 0 deletions istio-oauth2-proxy-oidc/cluster-issuer.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt
spec:
acme:
email: "[email protected]"
privateKeySecretRef:
name: letsencrypt
server: https://acme-v02.api.letsencrypt.org/directory
solvers:
# An empty selector will 'match' all Certificate resources that
# reference this Issuer.
- selector: {}
http01:
ingress:
class: istio

46 changes: 46 additions & 0 deletions istio-oauth2-proxy-oidc/dex-istio-gw.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: dex-gateway
namespace: demo
spec:
selector:
istio: ingressgateway # use Istio default gateway implementation
servers:
- port:
number: 80
name: http
protocol: HTTP
# tls:
# httpsRedirect: true
hosts:
- "dex.example.com"
- port:
number: 443
name: https
protocol: HTTPS
hosts:
- "dex.example.com"
tls:
mode: SIMPLE
credentialName: dex-tls-cert
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
namespace: demo
name: dex-vsvc
spec:
hosts:
- "dex.example.com"
gateways:
- dex-gateway
http:
- match:
- uri:
prefix: /
route:
- destination:
port:
number: 5556
host: dex.demo.svc.cluster.local
21 changes: 21 additions & 0 deletions istio-oauth2-proxy-oidc/dex-tls-cert.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: dex-tls-cert
namespace: istio-system
spec:
# Secret names are always required.
secretName: dex-tls-cert
privateKey:
algorithm: RSA
encoding: PKCS1
size: 4096
# At least one of a DNS Name, URI, or IP address is required.
dnsNames:
- dex.example.com
# Issuer references are always required.
issuerRef:
name: letsencrypt
# We can reference ClusterIssuers by changing the kind here.
# The default value is Issuer (i.e. a locally namespaced Issuer)
kind: ClusterIssuer
60 changes: 60 additions & 0 deletions istio-oauth2-proxy-oidc/dex-values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
https:
# -- Enable the HTTPS endpoint.
enabled: false

# -- Application configuration.
# See the [official documentation](https://dexidp.io/docs/).
config:
storage:
type: memory
issuer: https:/dex.example.com
staticClients:
- id: oauth2-proxy
name: oauth2-proxy
redirectURIs:
- 'https://httpbin.example.com/oauth2/callback'
- 'http://httpbin.example.com/oauth2/callback'
secret: proxy
enablePasswordDB: true
staticPasswords:
- email: "[email protected]"
# bcrypt hash of the string "password"
hash: $2a$10$2b2cU8CPhOTaGrs1HRQuAueS7JTT5ZHsHSzYiFPm1leZck7Mc8T4W
username: "admin"
userID: "08a8684b-db88-4b73-90a9-3cd1661f5466"

service:
# -- Annotations to be added to the service.
annotations: {}

# -- Kubernetes [service type](https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types).
type: ClusterIP

# -- Internal cluster service IP (when applicable)
clusterIP: ""

ports:
http:
# -- HTTP service port
port: 5556

# -- (int) HTTP node port (when applicable)
nodePort:

https:
# -- HTTPS service port
port: 5554

# -- (int) HTTPS node port (when applicable)
nodePort:

grpc:
# -- gRPC service port
port: 5557

# -- (int) gRPC node port (when applicable)
nodePort:

ingress:
# -- Enable [ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/).
enabled: false
45 changes: 45 additions & 0 deletions istio-oauth2-proxy-oidc/httpbin-deploy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpbin
namespace: demo
spec:
replicas: 1
selector:
matchLabels:
app: httpbin
version: v1
template:
metadata:
creationTimestamp: null
labels:
app: httpbin
version: v1
spec:
containers:
- image: docker.io/kennethreitz/httpbin
imagePullPolicy: IfNotPresent
name: httpbin
ports:
- containerPort: 80
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
annotations:
labels:
app: httpbin
service: httpbin
name: httpbin
namespace: demo
spec:
ports:
- name: http
port: 8000
protocol: TCP
targetPort: 80
selector:
app: httpbin
sessionAffinity: None
type: ClusterIP
Loading

0 comments on commit c19d505

Please sign in to comment.