基于oauth2-proxy和keycloak为Ingress Gateway实现SSO

部署keycloak,前面的文章有

添加域 名字叫istio

访问keycloak添加客户端

 

配置客户端

 

获取客户端的凭据,后面要用

创建mappers

 

部署oauth2-proxy

[root@k8s-master 05-JWT-and-Keycloak]# kubectl  apply -f 01-deploy-oauth2.yaml 
namespace/oauth2-proxy created
secret/oauth2-proxy created
service/oauth2-proxy created
deployment.apps/oauth2-proxy created

  客户端凭据的秘密 
  OAUTH2_PROXY_CLIENT_SECRET: 9l0fSqO1figCeQqr7TsKtnYqz832dRav

  数题报告openssl随机生成一个
  # Generate by command: openssl rand -base64 32 | tr -- '+/' '-_'
  OAUTH2_PROXY_COOKIE_SECRET: QVJH6PnqYxXvTC33ugOXU4bn8vBlAExl_TuLcUEyf-E=

[root@k8s-master 05-JWT-and-Keycloak]# cat 01-deploy-oauth2.yaml 
apiVersion: v1
kind: Namespace
metadata:
  name: oauth2-proxy
  labels:
    istio-injection: enabled
---
apiVersion: v1
kind: Secret
metadata:
  name: oauth2-proxy
  namespace: oauth2-proxy
stringData:
  # change this to your Keycloak Realm Client Id 
  OAUTH2_PROXY_CLIENT_ID: ingress-gateway
  # change this to your Keycloak Client Secret 
  OAUTH2_PROXY_CLIENT_SECRET: 9l0fSqO1figCeQqr7TsKtnYqz832dRav
  # Generate by command: openssl rand -base64 32 | tr -- '+/' '-_'
  OAUTH2_PROXY_COOKIE_SECRET: QVJH6PnqYxXvTC33ugOXU4bn8vBlAExl_TuLcUEyf-E=
---
apiVersion: v1
kind: Service
metadata:
  name: oauth2-proxy
  namespace: oauth2-proxy
spec:
  selector:
    app: oauth2-proxy
  ports:
  - name: http
    port: 4180
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: oauth2-proxy
  namespace: oauth2-proxy
spec:
  selector:
    matchLabels:
      app: oauth2-proxy
  template:
    metadata:
      labels:
        app: oauth2-proxy
    spec:
      containers:
      - name: oauth2-proxy
        image: quay.io/oauth2-proxy/oauth2-proxy:v7.2.1
        args:
        - --provider=oidc
        - --oidc-issuer-url=http://keycloak.keycloak.svc.cluster.local:8080/auth/realms/istio
        - --profile-url=http://keycloak.keycloak.svc.cluster.local:8080/auth/realms/istio/protocol/openid-connect/userinfo
        - --validate-url=http://keycloak.keycloak.svc.cluster.local:8080/auth/realms/istio/protocol/openid-connect/userinfo      
        - --set-authorization-header=true
        - --http-address=0.0.0.0:4180
        - --pass-host-header=true
        - --reverse-proxy=true
        - --auth-logging=true
        - --cookie-httponly=true
        - --cookie-refresh=4m
        - --cookie-secure=false
        - --email-domain="*"
        - --pass-access-token=true
        - --pass-authorization-header=true
        - --request-logging=true
        - --set-xauthrequest=true
        - --silence-ping-logging=true
        - --skip-provider-button=true
        - --skip-auth-strip-headers=false
        - --ssl-insecure-skip-verify=true
        - --standard-logging=true
        - --upstream="static://200"
        - --whitelist-domain=".magedu.com,.cluster.local"
        env:
        - name: OAUTH2_PROXY_CLIENT_ID
          valueFrom:
            secretKeyRef:
              name: oauth2-proxy
              key: OAUTH2_PROXY_CLIENT_ID
        - name: OAUTH2_PROXY_CLIENT_SECRET
          valueFrom:
            secretKeyRef:
              name: oauth2-proxy
              key: OAUTH2_PROXY_CLIENT_SECRET
        - name: OAUTH2_PROXY_COOKIE_SECRET
          valueFrom:
            secretKeyRef:
              name: oauth2-proxy
              key: OAUTH2_PROXY_COOKIE_SECRET
        resources:
          requests:
            cpu: 10m
            memory: 100Mi
        ports:
        - containerPort: 4180
          protocol: TCP
        readinessProbe:
          periodSeconds: 3
          httpGet:
            path: /ping
            port: 4180

我在这里踩了一个坑,是因为我没创建istio域,默认在master上创建的客户端,所有会报错404错误,新建istio域,重新创建客户端,在创建oauth2-proxy的pod

[2022-09-28T12:29:10.878Z] "GET /auth/realms/istio/.well-known/openid-configuration HTTP/1.1" 404 - via_upstream - "-" 0 32 9 9 "-" "Go-ient/1.1" "f279bec4-59bf-9b76-8897-16c7ece30d99" "keycloak.keycloak.svc.cluster.local:8080" "10.244.104.34:8080" outbound|8080||keycloakak.svc.cluster.local 10.244.166.159:34290 10.211.55.29:8080 10.244.166.159:55398 - default

运行正常

[root@master 05-JWT-and-Keycloak]# kubectl get pods -n oauth2-proxy
NAME                            READY   STATUS    RESTARTS      AGE
oauth2-proxy-779cbcdbbd-ddqpj   2/2     Running   2 (54s ago)   62s
[root@master 05-JWT-and-Keycloak]# kubectl logs oauth2-proxy-779cbcdbbd-ddqpj -n oauth2-proxy
[2022/12/03 02:02:28] [proxy.go:77] mapping path "/" => static response 200
[2022/12/03 02:02:28] [oauthproxy.go:148] OAuthProxy configured for OpenID Connect Client ID: ingress-gateway
[2022/12/03 02:02:28] [oauthproxy.go:154] Cookie settings: name:_oauth2_proxy secure(https):false httponly:true expiry:168h0m0s domains: path:/ samesite: refresh:after 4m0s

将OAuth2-proxy添加为Istio的Provider

[root@k8s-master 05-JWT-and-Keycloak]# istioctl apply -f 02-istio-operator-update.yaml
[root@k8s-master 05-JWT-and-Keycloak]# cat 02-istio-operator-update.yaml 
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  profile: demo
  meshConfig:
    extensionProviders:
    - name: oauth2-proxy
      envoyExtAuthzHttp:
        service: oauth2-proxy.oauth2-proxy.svc.cluster.local
        port: 4180
        timeout: 1.5s
        includeHeadersInCheck: ["authorization", "cookie"]
        headersToUpstreamOnAllow: ["x-forwarded-access-token", "authorization", "path", "x-auth-request-user", "x-auth-request-email", "x-auth-request-access-token"]
        headersToDownstreamOnDeny: ["content-type", "set-cookie"]

在ingress-gateway上添加授权策略

[root@k8s-master 05-JWT-and-Keycloak]# kubectl apply -f 03-ext-auth-ingress-gateway.yaml 
requestauthentication.security.istio.io/istio-ingressgateway created
authorizationpolicy.security.istio.io/ext-authz-oauth2-proxy created
[root@k8s-master 05-JWT-and-Keycloak]# cat 03-ext-auth-ingress-gateway.yaml 
apiVersion: security.istio.io/v1beta1
kind: RequestAuthentication
metadata:
  name: istio-ingressgateway
  namespace: istio-system
spec:
  selector:
    matchLabels:
      app: istio-ingressgateway
  jwtRules:
  - issuer: http://keycloak.keycloak.svc.cluster.local:8080/auth/realms/istio
    jwksUri: http://keycloak.keycloak.svc.cluster.local:8080/auth/realms/istio/protocol/openid-connect/certs
    #audiences: ["ingress-gateway","istio-ingress-gateway"]
    # Forward JWT to Envoy Sidecar
    forwardOriginalToken: true
  - issuer: http://keycloak.magedu.com:8080/auth/realms/istio
    jwksUri: http://keycloak.magedu.com:8080/auth/realms/istio/protocol/openid-connect/certs
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: ext-authz-oauth2-proxy
  namespace: istio-system
spec:
  selector:
    matchLabels:
      app: istio-ingressgateway
  action: CUSTOM
  provider:
    # Extension provider configured when we installed Istio
    name: oauth2-proxy
  rules:
  - to:
    - operation:
        hosts: 
        - "kiali.magedu.com"
        - "prometheus.magedu.com"
        - "bookinfo.magedu.com"
        notPaths: ["/auth/*"]
  #- to:
  #  - operation:
  #      hosts: ["*.magedu.com"]
  #      notPaths: ["/auth/*"]
[root@master 05-JWT-and-Keycloak]# kubectl get ra -n istio-system
NAME                   AGE
istio-ingressgateway   119s
[root@master 05-JWT-and-Keycloak]# kubectl get authorizationpolicies -n istio-system
NAME                     AGE
ext-authz-oauth2-proxy   2m4s

为开放的kiali服务添加路由策略

[root@k8s-master 05-JWT-and-Keycloak]# kubectl apply -f 04-routeconfig-for-services/kiali/
gateway.networking.istio.io/kiali-gateway unchanged
virtualservice.networking.istio.io/kiali-virtualservice configured
[root@k8s-master 05-JWT-and-Keycloak]# cat 04-routeconfig-for-services/kiali/kiali-gateway.yaml 
---
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: kiali-gateway
  namespace: istio-system
spec:
  selector:
    app: istio-ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "kiali.magedu.com"
    tls:
      httpsRedirect: true
  - port:
      number: 443
      name: https
      protocol: HTTPS
    tls:
      mode: SIMPLE
      credentialName: kiali-credential
    hosts:
    - "kiali.magedu.com"
---
[root@k8s-master 05-JWT-and-Keycloak]# cat 04-routeconfig-for-services/kiali/kiali-virtualservice.yaml 
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: kiali-virtualservice
  namespace: istio-system
spec:
  hosts:
  - "kiali.magedu.com"
  gateways:
  - kiali-gateway
  http:
  - match:
    - uri:
        prefix: /auth
    route:
    - destination:
        host: keycloak.keycloak.svc.cluster.local
        port:
          number: 8080
  - match:
    - uri:
        prefix: /oauth2
    route:
    - destination:
        host: oauth2-proxy.oauth2-proxy.svc.cluster.local
        port:
          number: 4180 
  - route:
    - destination:
        host: kiali
        port:
          number: 20001
---

浏览器直接访问kiali.magedu.com会自动跳转到http://keycloak.keycloak.svc.cluster.local:8080

自己提前做好本地解析keycloak.keycloak.svc.cluster.local  编辑/etc/hosts

本地hosts文件

创建一个kiali账号,电子邮件认证必须开启否则会登陆失败。

设置密码,把临时给关掉,如果不关掉需要模拟登陆下新创建的用户。

这次直接输入账号密码就可以访问kiali了

我们访问bookinfo.magedu.com/productpage也会自动跳转到keycloak进行认证。

 

我们创建一个bookinfo用户

设置密码,把临时给关掉,如果不关掉需要模拟登陆下新创建的用户。

添加一个bookinfo角色

添加一个bookinfo组

将bookinfo-role角色分配到bookinfo用户

将bookinfo用户加入到bookinfo-admin组中

在ingress-gateway客户端中添加groups mappers

在客户端直接curl,有个报错提示我账户未完全设置,

[root@master ~]# curl -d "username=bookinfo&password=yang7194&grant_type=password&client_id=ingress-gateway&client_secret=n0rqaYQOtedtYv1xcNIrtc2cT6R78jZh" http://keycloak.keycloak.svc.cluster.local:8080/auth/realms/istio/protocol/openid-connect/token
{"error":"invalid_grant","error_description":"Account is not fully set up"}

直接访问bookinfo.magedu.com,用bookinfo账号登陆,会提示重制密码,把密码重置下再次curl请求登陆

curl -d "username=bookinfo&password=123123&grant_type=password&client_id=ingress-gateway&client_secret=n0rqaYQOtedtYv1xcNIrtc2cT6R78jZh" http://keycloak.keycloak.svc.cluster.local:8080/auth/realms/istio/protocol/openid-connect/token
{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ0UldzR2xRamhEc1ptSVlCLXJhdDFiaTBQcGh0NWt1UldtSEZsaXFnd3UwIn0.eyJleHAiOjE2NjQ0MjA5NzUsImlhdCI6MTY2NDQyMDY3NSwianRpIjoiZTFjNDJhNWQtN2Y5ZC00NDdjLTliMmQtMWE2MzRiNmZkY2M4IiwiaXNzIjoiaHR0cDovL2tleWNsb2FrLmtleWNsb2FrLnN2Yy5jbHVzdGVyLmxvY2FsOjgwODAvYXV0aC9yZWFsbXMvaXN0aW8iLCJhdWQiOlsiaW5ncmVzcy1nYXRld2F5IiwiYWNjb3VudCJdLCJzdWIiOiJiYWMwMDY0MC01MmQ2LTRmNGEtODVhNi04YjQ4NTQ4ZDdlMWUiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJpbmdyZXNzLWdhdGV3YXkiLCJzZXNzaW9uX3N0YXRlIjoiNmEzYzVmOTktMWM1YS00NTBlLTg1NmYtMDYyYTE4NDlhYTg4IiwiYWNyIjoiMSIsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIiwiYm9va2luZm8tcm9sZSIsImRlZmF1bHQtcm9sZXMtaXN0aW8iXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6ImVtYWlsIHByb2ZpbGUiLCJzaWQiOiI2YTNjNWY5OS0xYzVhLTQ1MGUtODU2Zi0wNjJhMTg0OWFhODgiLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwibmFtZSI6ImJvb2tpbmZvIHlhbmciLCJncm91cHMiOlsiL2Jvb2tpbmZvLWFkbWluIl0sInByZWZlcnJlZF91c2VybmFtZSI6ImJvb2tpbmZvIiwiZ2l2ZW5fbmFtZSI6ImJvb2tpbmZvIiwiZmFtaWx5X25hbWUiOiJ5YW5nIiwiZW1haWwiOiJib29raW5mb0AxNjMuY29tIn0.ackxCEZ41InZRDlTUutfS0rV9-NgSykc6FLT81wEZ1jCK8i0IqUAC2WTRuqGUCp8tPsbDXG7Aa4ul-tBxcdI5sypSvOhpJqd5Zh__9VKK_j_njmZBa9glp4kgdAJa7VAet5o2j7xfTi4Cnht8bJ-WbVvB8tEFSasM0dNsRM61ksrL_heJUt0h3Sh9HtVqAIvKUr9zDAxfKCBZ-1I_C5owB0KwzRwI5G2b7P3n-H9eBre3PxYlUBkeuZGVPwrscpOvKi692yiw9qc-z97OJg6WCuXtDr2tgT6KU0kioEmJf75DhHzkAhQJml8Qg28lZoqFHkfquFzAajMILkM4xk9_Q","expires_in":300,"refresh_expires_in":1800,"refresh_token":"eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICIyZGQ3NWU0Yi05YTgwLTRkYzEtOTM1Ni01OWVkNDVmMDdhYjEifQ.eyJleHAiOjE2NjQ0MjI0NzUsImlhdCI6MTY2NDQyMDY3NSwianRpIjoiZTI1NjAwNTYtNmFjOC00Y2MwLTg0ZWUtYTQ3YWM2N2Y3MjRhIiwiaXNzIjoiaHR0cDovL2tleWNsb2FrLmtleWNsb2FrLnN2Yy5jbHVzdGVyLmxvY2FsOjgwODAvYXV0aC9yZWFsbXMvaXN0aW8iLCJhdWQiOiJodHRwOi8va2V5Y2xvYWsua2V5Y2xvYWsuc3ZjLmNsdXN0ZXIubG9jYWw6ODA4MC9hdXRoL3JlYWxtcy9pc3RpbyIsInN1YiI6ImJhYzAwNjQwLTUyZDYtNGY0YS04NWE2LThiNDg1NDhkN2UxZSIsInR5cCI6IlJlZnJlc2giLCJhenAiOiJpbmdyZXNzLWdhdGV3YXkiLCJzZXNzaW9uX3N0YXRlIjoiNmEzYzVmOTktMWM1YS00NTBlLTg1NmYtMDYyYTE4NDlhYTg4Iiwic2NvcGUiOiJlbWFpbCBwcm9maWxlIiwic2lkIjoiNmEzYzVmOTktMWM1YS00NTBlLTg1NmYtMDYyYTE4NDlhYTg4In0.KBYlBQgRXJmMh2GhXc03BVTJ8tmDLciyKChcEDXPr54","token_type":"Bearer","not-before-policy":0,"session_state":"6a3c5f99-1c5a-450e-856f-062a1849aa88","scope":"email profile"}[root@master ~]#

将返回数据进行解码

创建一个roles

再次curl请求复制返回结果

将返回结果复制 解码,可以看到刚才添加的user_roles

 

再次登陆bookinfo.magedu.com/productpage,使用之前的kiali用户也可以访问bookinfo

限制一下只有bookinfo用户能访问bookinfo。

[root@master 05-JWT-and-Keycloak]# kubectl apply -f 05-ingress-gateway-authz.yaml 
authorizationpolicy.security.istio.io/istio-ingressgateway created
[root@master 05-JWT-and-Keycloak]# cat 05-ingress-gateway-authz.yaml 
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: istio-ingressgateway
  namespace: istio-system
spec:
  selector:
    matchLabels:
      app: istio-ingressgateway
  action: ALLOW
  rules:
  - to:
    - operation:
        hosts: ["bookinfo.magedu.com"]
        paths: ["/*"]
    when:
    - key: request.auth.claims[iss]
      values: 
      - "http://keycloak.keycloak.svc.cluster.local:8080/auth/realms/istio"
      - "http://keycloak.magedu.com:8080/auth/realms/istio"
    - key: request.auth.claims[user_roles]
      values: 
      - "bookinfo-role"

我们使用kiali用户访问bookinfo就不能访问了

 

posted @ 2022-09-29 11:34  Maniana  阅读(1789)  评论(0编辑  收藏  举报