-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Istio and OAuth2-Proxy as a layer in front of an app to authenticate…
… through OIDC in K8s
- Loading branch information
Showing
305 changed files
with
47,912 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Oops, something went wrong.