---
# System prepended metadata

title: 監控應用透過 Istio 搭配使用 OAuth2-Proxy 身份驗證登入
tags: [工具]

---

# 監控應用透過 Istio 搭配使用 OAuth2-Proxy 身份驗證登入

## 目標

預設 prometheus 和 alertmanager UI 不需要帳密就可以直接進到他們的 UI，透過 istio 和 OAuth2-Proxy 搭配，可以讓我們使用帳密的方式登入到 UI。



## 在 ubuntu 安裝套件
```
$ sudo apt install apache2-utils
```


## 產生加密字串

* 產生一串帳號與加密後的密碼。
```
$ htpasswd -nbs admin password123
admin:{SHA}y/2sYAj5yrQIN4TL0YdPdmGNKpc=
```
* 產生一串隨機的加密金鑰，目的是讓別人看不出 Cookie 裡面存了什麼。
```
$ openssl rand -base64 16 | tr -d '\n'
1om2CJDWzfOQXELLv5mQkA==
```

## 建立 Kubernetes Secret

```
$ nano secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: oauth2-proxy-creds
  namespace: istio-system
type: Opaque
stringData:
  # 剛才 htpasswd 產生的整行內容
  htpasswd: "admin:{SHA}y/2sYAj5yrQIN4TL0YdPdmGNKpc="
  # 隨機 16, 24 或 32 字元的 base64 字串 (用於 Cookie 加密)
  cookie-secret: "1om2CJDWzfOQXELLv5mQkA=="
```

```
$ kubectl apply -f secret.yaml
```

```
$ kubectl -n istio-system get secret oauth2-proxy-creds
NAME                 TYPE     DATA   AGE
oauth2-proxy-creds   Opaque   2      14s
```


## 部署 OAuth2-Proxy
* 它的核心任務是：幫那些「本身沒有登入功能」的應用程式（例如您的 Prometheus、Alertmanager 或 Dashboard），在不改動任何程式碼的情況下，加上一層專業的登入保護。
* OAuth2-Proxy 主要用來為後端服務增加身份驗證層。它支援多種 OAuth 2.0 提供者（如 Google、OIDC、Keycloak 等），可以保護未提供身份驗證的應用程式。 oauth2-proxy 在請求進入後端服務之前，會先進行 OAuth 2.0 登入認證，確保請求者俱有存取權限。它承擔了登入的合法性校驗、重定向、登入成功後的 cookie、response 設定等功能。

```
$ nano oauth2-proxy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: oauth2-proxy
  namespace: istio-system
spec:
  replicas: 1
  selector:
    matchLabels:
      app: oauth2-proxy
  template:
    metadata:
      labels:
        app: oauth2-proxy
    spec:
      containers:
      - name: oauth2-proxy
        image: quay.io/oauth2-proxy/oauth2-proxy:v7.4.0
        ports:
        - containerPort: 4180
        args:
        - --http-address=0.0.0.0:4180
        - --provider=github
        - --client-id=static-client-id
        - --client-secret=static-client-id
        - --htpasswd-file=/etc/proxy/htpasswd
        - --cookie-secure=false
        - --cookie-secret=$(COOKIE_SECRET)
        - --email-domain=*
        - --upstream=static://200
        - --cookie-expire=30m
        env:
        - name: COOKIE_SECRET
          valueFrom:
            secretKeyRef:
              name: oauth2-proxy-creds
              key: cookie-secret
        volumeMounts:
        - name: htpasswd-volume
          mountPath: /etc/proxy
      volumes:
      - name: htpasswd-volume
        secret:
          secretName: oauth2-proxy-creds
          items:
          - key: htpasswd
            path: htpasswd
---
apiVersion: v1
kind: Service
metadata:
  name: oauth2-proxy
  namespace: istio-system
spec:
  ports:
  - port: 4180
    targetPort: 4180
    protocol: TCP
    name: http
  selector:
    app: oauth2-proxy
```


```
$ kubectl apply -f oauth2-proxy.yaml
```
```
$ kubectl -n istio-system get pod
NAME                            READY   STATUS    RESTARTS   AGE
oauth2-proxy-6b444f46d7-w2s86   1/1     Running   0          8s
```
## 安裝 istio
```
$ curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.29.0 sh -

$ sudo cp istio-1.29.0/bin/istioctl /usr/local/bin
```
```
$ nano istio-install.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
  name: istio-control-plane
  namespace: istio-system
spec:
  profile: default
  meshConfig:
    extensionProviders:
    - name: "my-auth-proxy" # 與 AuthorizationPolicy 對應的名字
      envoyExtAuthzHttp:
        service: "oauth2-proxy.istio-system.svc.cluster.local"
        port: "4180"
        includeHeadersInCheck:
          - "authorization"
          - "cookie"
        headersToUpstreamOnAllow:
          - "authorization"
          - "path"
          - "x-auth-request-user"
          - "x-auth-request-email"
        headersToDownstreamOnDeny:
          - "content-type"
          - "set-cookie"
  components:
    pilot:
      enabled: true
    ingressGateways:
      - name: istio-ingressgateway
        enabled: true
        k8s:
          service:
            type: LoadBalancer
            loadBalancerIP: 10.10.7.85   # 設定自己環境可用的 ip
```

```
$ istioctl install -f ./istio-install.yaml
```
## 安裝 prometheus

```
$ helm repo add prometheus-community https://prometheus-community.github.io/helm-charts

$ helm repo update

$ helm install monitoring prometheus-community/kube-prometheus-stack --namespace monitoring-system --create-namespace
```
```
$ kubectl -n monitoring-system get po
NAME                                                     READY   STATUS    RESTARTS   AGE
alertmanager-monitoring-kube-prometheus-alertmanager-0   2/2     Running   0          52s
monitoring-grafana-584c45f5f6-lq96g                      3/3     Running   0          62s
monitoring-kube-prometheus-operator-7967b58468-bbdc6     1/1     Running   0          62s
monitoring-kube-state-metrics-68cbbfb567-kdpwg           1/1     Running   0          62s
monitoring-prometheus-node-exporter-2blh2                1/1     Running   0          65s
monitoring-prometheus-node-exporter-9d88w                1/1     Running   0          65s
monitoring-prometheus-node-exporter-dd22v                1/1     Running   0          65s
monitoring-prometheus-node-exporter-hx9d2                1/1     Running   0          65s
prometheus-monitoring-kube-prometheus-prometheus-0       2/2     Running   0          52s
```
## 建立 Gateway ＆ VirtualService

```
$ nano app-vs.yaml
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: app-gateway
  namespace: istio-system
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*.k8sexample.com"
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: prometheus-vs
  namespace: istio-system
spec:
  hosts:
  - "prometheus.k8sexample.com"
  gateways:
  - app-gateway
  http:
  - match:
    - uri:
        prefix: /oauth2
    route:
    - destination:
        host: oauth2-proxy.istio-system.svc.cluster.local
        port:
          number: 4180
  - match:
    - uri:
        prefix: /
    route:
    - destination:
        host: monitoring-kube-prometheus-prometheus.monitoring-system.svc.cluster.local
        port:
          number: 9090
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: alertmanager-vs
  namespace: istio-system
spec:
  hosts:
  - "alertmanager.k8sexample.com"
  gateways:
  - app-gateway
  http:
  - match:
    - uri:
        prefix: /oauth2
    route:
    - destination:
        host: oauth2-proxy.istio-system.svc.cluster.local
        port:
          number: 4180
  - match:
    - uri:
        prefix: /
    route:
    - destination:
        host: monitoring-kube-prometheus-alertmanager.monitoring-system.svc.cluster.local
        port:
          number: 9093
```

```
$ kubectl apply -f app-vs.yaml
```


```
$ kubectl -n istio-system get gateway.network
NAME          AGE
app-gateway   8s

$ kubectl -n istio-system get vs
NAME              GATEWAYS          HOSTS                             AGE
alertmanager-vs   ["app-gateway"]   ["alertmanager.k8sexample.com"]   6m42s
prometheus-vs     ["app-gateway"]   ["prometheus.k8sexample.com"]     6m42s
```


## 建立 AuthorizationPolicy
```
$ nano auth.yaml
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: monitor-auth-policy
  namespace: istio-system
spec:
  selector:
    matchLabels:
      istio: ingressgateway # 保護您的內部網關流量
  action: CUSTOM
  provider:
    name: "my-auth-proxy" # 務必與上面 IstioOperator 定義的名字相同
  rules:
  - to:
    - operation:
        hosts:
        - "prometheus.k8sexample.com"
        - "alertmanager.k8sexample.com"
        notPaths:
        - "/oauth2/*"
```

```
$ kubectl apply -f auth.yaml

$ kubectl -n istio-system get AuthorizationPolicy
NAME                  ACTION   AGE
monitor-auth-policy   CUSTOM   10s
```

## 登入 UI

* 進入 UI 就需要輸入帳號密碼，輸入 `admin/password123`

![image](https://hackmd.io/_uploads/SkFyxkXFZg.png)

* 成功登入

![image](https://hackmd.io/_uploads/H1AdS1XtWl.png)


## 參考

https://oauth2-proxy.github.io/oauth2-proxy/

