一次kong概念验证之旅
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录前言0. 本地k8s 环境搭建(minikube)1. kong及 kong ingress controller 配置并验证1.1 安装kong:dbless (无数据库模式,较灵活)1.2 部署echo测试服务2. kong plugin 介绍3. Kong plugin 开发4. Oauth2+jwt+Kong 认证鉴权
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
提示:这里可以添加本文要记录的大概内容:
项目需要使用kong网关,一路跌跌撞撞完成的过程记录
提示:以下是本篇文章正文内容,下面案例可供参考
知识储备:
K8s
Docker
kong及kong 插件开发(openresty+lua)
OAuth2.0机制
JWT结构
授权认证服务:KeyCloack
Spring Security OAuth2
0. 本地k8s 环境搭建(minikube)
(1)安装docker
(2) 安装minikube
(3) 安装image k8s
安装步骤参考:https://blog.csdn.net/weixin_44716147/article/details/123409201
了解下K8s相关知识及概念
Pod:是kubernetes调度的最小部署单位
pod是一个容器的集合,一个pod可以包含一个或多个容器
同个Pod中的容器使用相同的网络命名空间和IP地址, 端口号
同个pod下的容器相互之间通过localhost来发现和通信
每个组内的容器共享一个存储卷(volume)
pod是一个服务的多个进程的聚合单位
pod作为一个独立的部署单位,支持横向扩展和复制
Pod是短暂的
Controllers: 控制器是更高级层次对象,用于部署和管理Pod,每个控制器负责不同的任务
Deployment:无状态应用部署
StatefulSet:有状态应用部署
DaemonSet:确保所有Node运行同一个Pod
Job:一次性任务
Cronjob:定时任务
Service: 防止Pod失联,定义一组Pod的访问策略
Namespace:命名空间,将对象逻辑上隔离,系统命名空间有一下四种
default:默认的命名空间,不声明空间的pod都在这里。
kube-node-lease:为高可用提供心跳监视的命名空间
kube-public:公共数据,所有用户都可以读取它。
kube-system:系统服务对象所使用的命名空间
CoreDNS:用于Kubernetes集群内部Service的解析,可以让Pod把Service名称解析成IP地址,然后
通过Service的IP地址进行连接到对应的应用上。
Dashboard:基于web的用户接口,用于可视化k8s集群
Node:
- master节点(管理节点)
提供集群的控制
对集群进行全局决策
检测和响应集群事件
主要由:kube-apiserver、kuberproxy、schedular、controller manage和etcd
- node节点(计算节点)
运行容器的实际节点
维护运行pod,并提供具体应用的运行环境
node节点由:kubelet、kube-proxy和容器引擎(如docker)组成
计算节点被设计成水平扩展,该组件在多个节点上运行
1. kong及 kong ingress controller 配置并验证
1.1 安装kong:dbless (无数据库模式,较灵活)
安装:
基于最新kong的dbless yaml 部署
kubectl create -f https://raw.githubusercontent.com/Kong/kubernetes-ingress-controller/2.0.x/deploy/single/all-in-one-dbless.yaml
验证:
查看kong pod 详细信息:
kubectl describe pod <kong 容器名称>
1.2 部署echo测试服务
在集群上运行指定镜像:
kubectl run echo --image=googlecontainer/echoserver:1.10
将资源暴露为新的Kubernetes Service。
kubectl expose deploy echo --port=8080 --target-port=8080
1.3 配置ingress(可以直接再k8s dashboard 配置)
命令执行:kubectl create -f echo-ingress.yaml
apiVersion: networking.k8s.io/v1
metadata:
name: echo-ingress
namespace: kong
spec:
ingressClassName: kong
rules:
- http:
paths:
- path: /hello
pathType: Prefix
backend:
service:
name: hello-minikube
port:
number: 8080
- 通过port-forward 将本机端口转发到kong service 的端口
kubectl port-forward -n kong svc/kong-proxy 7080:80
验证: curl -i http://127.0.0.1:7080/echo
2. kong plugin 介绍
kong的插件分为开源版和社区版,社区版还有更多的定制功能,但是社区版是要收费的
KONG开源版本一共开放28个插件,如下:
acl、aws-lambda、basic-auth、bot-detection、correlation-id、cors、datadog、file-log、galileo、hmac-auth、http-log、ip-restriction、jwt、key-auth、ldap-auth、loggly、oauth2、rate-limiting、request-size-limiting、request-termination、request-transformer、response-ratelimiting、response-transformer、runscope、statsd、syslog、tcp-log、udp-log
以上插件,主要分五大类:
Authentication认证;
Security安全;
Traffic Control流量控制;
Analytics & Monitoring分析&监控;
Logging日志;
其他还有请求报文处理类。
熔断request-termination插件
该插件用来定义指定请求或服务不进行上层服务,而直接返回指定的内容.用来为指定的请求或指定的服务进行熔断.
可以参考:https://docs.konghq.com/hub/kong-inc/request-termination/
限流rate-limiting插件
说明:
根据年、月、日、时、分、秒设置限流规则,多个限制同时生效。
比如:每天不能超过10次调用,每分不能超过3次。
当一分钟内,访问超过3次,第四次就会报错。
当一天内,访问次数超过10次,第十一次就会报错。
可以参考:https://docs.konghq.com/hub/kong-inc/rate-limiting/
IP黑白名单ip-restriction限制插件
IP限制插件,是一个非常简单的插件,可以设置黑名单IP,白名单IP这个很简单。
规则:
IP黑白名单,支持单个,多个,范围分段IP(满足CIDR notation规则)。多个IP之间用逗号,分隔。
CIDR notation规范如下:
10.10.10.0/24 表示10.10.10.*的都不能访问。
基本认证Basic Authentication插件
这个是个基础的认证方式,服务端设置用户和密码,客户端发送请求时在头部设置用户和密码,服务端接收到以后对请求进行校验,如果通过,则处理请求,否则返回401Unauthorized。
key认证key-Auth插件
该插件很简单,利用提前预设好的关键字名称,
设置的keynote = apices,然后为consumer设置一个key-auth 密钥,假如key-auth=test@keyauth。
在请求api的时候,将apikey=test@keyauth,作为一个参数附加到请求url后,或者放置到headers中。
HMAC认证hmac_auth插件
Clock Skew
使用Kong的hmac后,请求必须带有Date和x-date请求头,这个是防止重放攻击(Replay Attacks),默认的情况下,客户端传过来的时间和服务端的时间相差300s,Kong就认为这个请求是有问题的。这个值可以修改的,通过修改config.clock_skew的参数
Headers的完整性
使用Kong的hmac来确保请求头的完整性。具体要确保那个头,这个也是可以配置的,下面会演示。官方推荐,最差应该是 request-line, host, and date这三个头,最好是全部的头。
Body的完整性
使用Kong的hmac可以确保请求内容的完整性
可以参考: https://docs.konghq.com/hub/kong-inc/hmac-auth/
Openid-connect (oidc)插件:
可以参考:https://docs.konghq.com/hub/kong-inc/openid-connect/
允许以标准化方式与第 3 方身份提供商 (IdP) 集成。此插件可用于将 Kong 实现为(代理)OAuth 2.0资源服务器(RS)和/或客户端与上游服务之间的 OpenID Connect 依赖方(RP)。
该插件支持多种类型的凭据和授权:
签名的 JWT访问令牌 ( JWS )
不透明的访问令牌
刷新令牌
授权码
用户名和密码
客户端凭据
会话 cookie
3. Kong plugin 开发
下载官方插件开发模板:
git clone https://github.com/Kong/kong-plugin.git
目录结构如下:
kong插件主要有三个文件:
handler.lua 是包含插件逻辑处理相关代码。 schema.lua 包含插件的配置文件。 rockspec 文件是通过luarock安装时用的配置文件。
逻辑处理的代码根据openresty的不同处理阶段分成了不同的函数,根据插件的功能只需要在不同的函数中添加自己的业务逻辑
插件开发学习:https://docs.konghq.com/gateway-oss/2.5.x/plugin-development/
Kong 插件安装
cd /usr/local/share/lua/5.1/kong/plugin
将自定义插件目录(例如:myplugin) 放到文件夹下即可。
重启kong:
如果再k8s , 找到kong deployment,点击restart即可
k8s配置KongPlugin案例:
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
plugin: rate-limiting
metadata:
name: XXX-rate-limiting
annotations:
# Important otherwise kong can't be enabled
kubernetes.io/ingress.class: kong
config:
second: 1000
hour: 2000000
policy: redis
hide_client_headers: true
redis_host: "ratelimit.kong.svc.cluster.local"
4. Oauth2+jwt+Kong 认证鉴权
Oauth2 参考:https://blog.csdn.net/Laputa_SKY/article/details/80428220
Resource Owner - 资源所有者,一般指用户。
Resource Server - 资源服务器。
Client - 代表Resource Owner去访问受保护的资源。
Authorization Server - 对Resource Owner进行身份认证,并颁发访问受保护资源的access token。
User Agent - 用户代理,一般指浏览器,负责用户登录和注销后的页面跳转。
Resource - 受保护的资源,比如API,页面
OAuth2 框架定义以下几种flow (授权流程):
Authorization Code Flow - 授权码授权流程;最常见的授权流程。
是功能最完整、流程最严密的授权模式。它的特点就是通过客户端的后台服务器,与"服务提供商"的认证服务器进行互动
Implicit Flow - 隐式授权流程
简化模式(implicit grant type)不通过第三方应用程序的服务器,直接在浏览器中向认证服务器申请令牌,跳过了"授权码"这个步骤,因此得名。所有步骤在浏览器中完成,令牌对访问者是可见的,且客户端不需要认证。
Resource Owner Credential Flow - 资源所有者凭据授权流程;不安全,强烈不建议使用。
密码模式(Resource Owner Password Credentials Grant)中,用户向客户端提供自己的用户名和密码。客户端使用这些信息,向"服务商提供商"索要授权。
在这种模式中,用户必须把自己的密码给客户端,但是客户端不得储存密码。这通常用在用户对客户端高度信任的情况下,比如客户端是操作系统的一部分,或者由一个著名公司出品。而认证服务器只有在其他授权模式无法执行的情况下,才能考虑使用这种模式。
Client Credential Flow - 客户端凭据授权流程(服务端之间调用)
Client 自己就是 Resource Owner ,Client 取用的是自己擁有的 Protected Resources
Client is requesting access to protected resources based on an authorization previously arranged with the authorization server.
這個流程只能用在 Confidential Client 。
关于几个重点参数:
response_type:code 表示要求返回授权码,token 表示直接返回令牌
client_id:客户端身份标识
client_secret:客户端密钥
redirect_uri:重定向地址
scope:表示授权的范围,read只读权限,all读写权限
grant_type:表示授权的方式,AUTHORIZATION_CODE(授权码)、password(密码)、client_credentials(凭证式)、refresh_token 更新令牌
state:应用程序传递的一个随机数,用来防止CSRF攻击
JWT知识:
示例:
eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJqRkdrVnhBbEVXcGN4ekJPZ25RUWxZb2VQYkZfOXM1aG5SeVlRdExHeTNVIn0.eyJleHAiOjE2MTA3MjA5NDAsImlhdCI6MTYxMDcyMDY0MCwianRpIjoiM2Q3M2IyNjItZDU3NC00OWEyLThlMGEtYWQ0ZmM0ZDAxMTA1IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL2F1dGgvcmVhbG1zL29yZy1kZW1vIiwiYXVkIjoiYWNjb3VudCIsInN1YiI6IjQ4ZGJiMGJkLTBiODYtNDFjNC1hNWUwLTlmNmY2YTAwMGQyMiIsInR5cCI6IkJlYXJlciIsImF6cCI6ImFwcC0xIiwic2Vzc2lvbl9zdGF0ZSI6ImRlNzZmNmYwLTRjMjktNDkwMy04YTQxLTUxYmVlMjllMmNiZiIsImFjciI6IjEiLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiVXNlciIsIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6InByb2ZpbGUgZW1haWwiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsInByZWZlcnJlZF91c2VybmFtZSI6IndpbGxpYW0ifQ.JAZhvi8QHY0MHyiwuhXZ9amxXXvutLhYN3jUclmPUrJizikYNpS61Qub8iVruSGOxI6pfvc5BcwTJUwZ0UsmBl_BalKEox1MkOujHKhtMQ78631H3eZyANCUbbe-u0y4Vp3fmWTk6ErgcIQSY2DkmsE97tzVVCrVC_uGdcpewUpUu1VDzA1TPd5KSvU-2d8T_KOeTUsLoG4964ryheJiYQOkXVxJCe1CN5eQlIIZlSIujq7O71tPDaNif9RunrpU0c2rAtqKoU0bS1iKXIOqRtxfFum7Ju1l7I2Sa4uiZH-T76yLRO5Mxk124FNu49y6H-Zu10u0memWAPvtJSi-ZQ
这是一串Base64URL的编码。
对其解码后,内容包括header, payload 和 signature:
Header:
{
"typ": "JWT",
"alg": "RS256",
"kid": "jFGkVxAlEWpcxzBOgnQQlYoePbF_9s5hnRyYQtLGy3U"}
Payload:
{
"exp": 1610720940, # 令牌过期时间戳
"iat": 1610720640, # 令牌颁发时间戳
"jti": "3d73b262-d574-49a2-8e0a-ad4fc4d01105", # 令牌唯一标识符
"iss": "http://localhost:8080/auth/realms/org-demo", # 令牌颁发者
"aud": "account", # 令牌的受众,接收者
"sub": "48dbb0bd-0b86-41c4-a5e0-9f6f6a000d22", # 令牌的主体
"typ": "Bearer", # 令牌的类型
"azp": "app-1",
"session_state": "de76f6f0-4c29-4903-8a41-51bee29e2cbf",
"acr": "1",
"realm_access": {
"roles": [
"User",
"offline_access",
"uma_authorization"
]
},
"resource_access": {
"account": {
"roles": [
"manage-account",
"manage-account-links",
"view-profile"
]
}
},
"scope": "profile email",
"email_verified": false,
"preferred_username": "william"
}
Signture
secret
https://www.jsonwebtoken.io/
可以看到JWT本身已经包含验证Token所需的全部元数据,因此Resource Server无需调用Authorization Server的接口就可以验证Access Token的有效性。
认证授权服务器(KeyCloak)
官网文档:https://www.keycloak.org/documentation
Keycloak是一个开源的 oauth 用户认证和授权解决方案。使用 keycloak 开发者就不用自己实现用户管理功能了。
安装:
k8s:
kubectl create -f https://raw.githubusercontent.com/keycloak/keycloak-quickstarts/latest/kubernetes-examples/keycloak.yaml
kubectl port-forward --address 0.0.0.0 svc/keycloak 9080:8080 映射外网ip及端口
配置参考:https://blog.csdn.net/qq_33430322/article/details/105861261
5. POC 实现过程
根据目前状态,我们对外部第三方提供OAuth2认证方式,最佳方案是授权码认证方式,故结合kong和keycloack(认证服务器)或者spring security oauth2 +jwt 完成如下流程
更多推荐
所有评论(0)