基于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就不能访问了