API网关Kong学习笔记(四): 功能梳理和插件使用-认证插件使用

Tags: kong 

目录

说明

Kong的plugins中列出了Kong的社区版支持的一些插件,这里尝试使用一下其中的认证插件:

Basic Auth
HMAC Auth
JWT Auth
Key Auth
LDAP Auth
OAuth 2.0 Auth

完整插件名单和使用方法见:Kong Plugins Website

API网关Kong的功能梳理和插件使用(一):基本使用过程已经介绍了基本使用方法,这里不再赘述。

Kong-Ingress-Controller的版本是0.2.0,Kong的版本是0.14.1,是用下面的方式部署的:

./kubectl.sh create -f https://raw.githubusercontent.com/introclass/kubernetes-yamls/master/all-in-one/kong-all-in-one.yaml

相关笔记

2019-05-06 16:28:56:kong 1.1.x有了一个重大变换,实现了db-less模式,可以不使用数据库了,见笔记二十六:查看全部笔记如果是刚开始学习kong,直接从1.x开始,0.x已经不再维护,0.15是0.x的最后一个版本。

前19篇笔记是刚开始接触kong时记录的,使用的版本是0.14.1,当时对kong一知半解,笔记比较杂乱。第二十篇开始是再次折腾时的笔记,使用的版本是1.0.3,笔记相对条理一些。

从0.x到1.x需要关注的变化有:

  1. 插件全部使用pdk
  2. 0.x中不鼓励使用的特性都被移除了;
  3. 全部使用kong.db,以前独立的dao彻底清除,代码简洁清晰了。

部署一个echo应用

为了方便后面的测试,这里部署一个echo应用

./kubectl.sh create -f https://raw.githubusercontent.com/introclass/kubernetes-yamls/master/all-in-one/echo-all-in-one.yaml

创建了一个名为demo-echo的namespace,服务以NodePort的方式暴露出来:

./kubectl.sh -n demo-echo get svc
NAME      TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)                     AGE
echo      NodePort   172.16.57.150   <none>        80:31512/TCP,22:31608/TCP   1d

echo服务返回接收到的数据:

$ curl 192.168.33.12:31512
Hostname: echo-676ff9c67f-jlr8v

Pod Information:
    -no pod information available-

Server values:
    server_version=nginx: 1.13.3 - lua: 10008

Request Information:
    client_address=192.168.33.12
    method=GET
    real path=/
    query=
    request_version=1.1
    request_uri=http://192.168.33.12:8080/

Request Headers:
    accept=*/*
    host=192.168.33.12:31512
    user-agent=curl/7.54.0

Request Body:
    -no body in request-

确保通过Kong的数据平面也可以访问:

curl 192.168.33.11:31512 -H "host:echo.com"
Hostname: echo-676ff9c67f-jlr8v

Pod Information:
    -no pod information available-

Server values:
    server_version=nginx: 1.13.3 - lua: 10008

Request Information:
    client_address=192.168.33.11
    method=GET
    real path=/
    query=
    request_version=1.1
    request_uri=http://echo.com:8080/

Request Headers:
    accept=*/*
    host=echo.com
    user-agent=curl/7.54.0

Request Body:
    -no body in request-

Basic Auth

Kong Plugin: Basic Authentication可以为Route或者Service添加简单的用户名密码认证,插件类型为basic-auth

创建用户user1,设置user1用户的basic-auth:

apiVersion: configuration.konghq.com/v1
kind: KongConsumer
metadata:
  name: user1
  namespace: demo-echo
username: echo-user1

---

apiVersion: configuration.konghq.com/v1
kind: KongCredential
metadata:
  name: user1-basic-auth
  namespace: demo-echo
consumerRef: user1
type: basic-auth
config:
  username: user1
  password: 123456

创建之后可以在Kong-Dashboard中看到新建的Consumer,以及设置的basic-auth信息。

Dashboard中看到的是密码的哈希,不是密码原文:

14049af5b1854d7e7e21cd4bef60d8e1d9f9ff0d

创建KongPlugin:

apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
  name: user1-basic-auth
  namespace: kong
disabled: false  # optional
plugin: basic-auth

编辑ingress-echo:

 ./kubectl.sh -n demo-echo edit ingress ingress-echo

在ingress-echo中添加annotations:

metadata:
  annotations:
    plugins.konghq.com: user1-basic-auth

验证1,直接访问提示未授权(如果是用浏览器访问,弹出输入账号密码的对话框):

$ curl  192.168.33.11:30939/ -H "host:echo.com"
{"message":"Unauthorized"}

验证2,用Basic Auth访问,需要将用户名和密码用base64编码:

$ KEY=`echo "user1:123456" |base64`
$ curl 192.168.33.11:30939/ -H "host:echo.com"  -H "Authorization: Basic $KEY"
Hostname: echo-676ff9c67f-jlr8v

Pod Information:
    -no pod information available-

Server values:
    server_version=nginx: 1.13.3 - lua: 10008

Request Information:
    client_address=172.16.128.17
    method=GET
    real path=/
    query=
    request_version=1.1
    request_uri=http://172.16.128.16:8080/

Request Headers:
    accept=*/*
    connection=keep-alive
    host=172.16.128.16:8080
    user-agent=curl/7.54.0
    x-consumer-custom-id=echo-user1
    x-consumer-id=e7cd11ac-d1b1-11e8-9da4-525400c042d5
    x-consumer-username=echo-user1
    x-credential-username=user1
    x-forwarded-for=192.168.33.11
    x-forwarded-host=echo.com
    x-forwarded-port=8000
    x-forwarded-proto=http
    x-real-ip=192.168.33.11

Request Body:
    -no body in request-

Key Auth

Kong Plugin: Key Auth用来为Route和Service设置key,只有带有正确的key才能访问服务,插件类型为key-auth

在前面的基础上,为Consumser设置key-auth信息,创建相应的KongPlugin:

apiVersion: configuration.konghq.com/v1
kind: KongCredential
metadata:
  name: user1-key-auth
  namespace: demo-echo
consumerRef: user1
type: key-auth
config:
  key: "123456"

---

apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
  name: user1-key-auth
  namespace: demo-echo
disabled: false  # optional
plugin: key-auth
config:
  hide_credentials: true

将ingress-echo annotation中的plugins修改为新建的KongPlugin:

metadata:
  annotations:
    plugins.konghq.com: user1-key-auth

验证,带有apikey时访问成功:

$curl  192.168.33.11:30939/ -H "host:echo.com" -H "apikey: 123456"
Hostname: echo-676ff9c67f-jlr8v

Pod Information:
    -no pod information available-

Server values:
    server_version=nginx: 1.13.3 - lua: 10008

Request Information:
    client_address=172.16.128.17
    method=GET
    real path=/
    query=
    request_version=1.1
    request_uri=http://172.16.128.16:8080/

Request Headers:
    accept=*/*
    connection=keep-alive
    host=172.16.128.16:8080
    user-agent=curl/7.54.0
    x-consumer-custom-id=echo-user1
    x-consumer-id=e7cd11ac-d1b1-11e8-9da4-525400c042d5
    x-consumer-username=echo-user1
    x-forwarded-for=192.168.33.11
    x-forwarded-host=echo.com
    x-forwarded-port=8000
    x-forwarded-proto=http
    x-real-ip=192.168.33.11

Request Body:
    -no body in request-

JWT Auth

Kong Plugin: JWT Auth插件为Service或者Route设置Json Web Token认证,插件类型为jwt

RFC7519:JSON Web Token (JWT)规定了JWT的格式和用法。

在前面的基础上,配置Consumer的jwt信息,并创建KongPlugin:

将Rout到绑定到插件修改为刚创建的KongPlugin:

metadata:
  annotations:
    plugins.konghq.com: user1-jwt-auth

到网页jwt.io上,签署一个Json Web Token:

HEADER:
{
  "alg": "HS256",      # Consumer的jwt中设置的算法
  "typ": "JWT"
}

PAYLOAD:
{
  "iss": "a36c3049b36249a3c9f8891cb127243c"   # Consumer的jwt中设置的key
}

得到Json Web Token:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhMzZjMzA0OWIzNjI0OWEzYzlmODg5MWNiMTI3MjQzYyJ9.oqJY4wM3X2DFs8U93w2aeA6MRf4oRwKOv_8wXMtykCU

验证,直接访问:

$ curl  192.168.33.11:30939/ -H "host:echo.com"
{"message":"Unauthorized"}

验证,使用JWT访问:

$ curl 192.168.33.11:31512/ -H "host:echo.com" -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhMzZjMzA0OWIzNjI0OWEzYzlmODg5MWNiMTI3MjQzYyJ9.oqJY4wM3X2DFs8U93w2aeA6MRf4oRwKOv_8wXMtykCU"

Hostname: echo-676ff9c67f-jlr8v

Pod Information:
    -no pod information available-

Server values:
    server_version=nginx: 1.13.3 - lua: 10008

Request Information:
    client_address=192.168.33.11
    method=GET
    real path=/
    query=
    request_version=1.1
    request_uri=http://echo.com:8080/

Request Headers:
    accept=*/*
    authorization=Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhMzZjMzA0OWIzNjI0OWEzYzlmODg5MWNiMTI3MjQzYyJ9.oqJY4wM3X2DFs8U93w2aeA6MRf4oRwKOv_8wXMtykCU
    host=echo.com
    user-agent=curl/7.54.0

Request Body:
    -no body in request-

OAuth 2.0 Auth

Kong Plugin: OAuth 2.0的用来对接OAuth 2.0授权系统,插件类型为oauth2

OAuth 2.0认证过程中,一共有三个角色:

用户
第三方服务
应用

目标是:用户允许第三方服务直接从应用中查询自己的数据。

启用OAuth2.0插件以后,Kong本身成为OAuth 2.0中的认证服务器。

第三方服务将用户重定向到应用授权页面。用户授权之后,应用调用Kong的接口获得第三方服务的授权码(Code)、重定向URI。应用将用户重定向到第三方服务的URI,并且在重定向URI中带上授权码。第三方服务从URI汇总获得授权码,用授权码从Kong中获得Access Token。第三方服务用Access Token直接调用应用的接口,查询用户的数据。

要使用Kong的OAuth 2.0,需要做以下几件事情:

1. 应用开发一个授权页面,第三方可以访问
2. 应用将为自己在Kong中的Service或者Route,配置OAuth 2.0,设置scope等
3. 第三方在kong中注册一个Consumer
4. 第三方为自己的Consumer配置OAuth 2.0,设置client_id、client_secret、redirect_uri
5. 第三方开发申请授权的页面

授权过程如下:

1. 第三方将用户重定向到应用的授权页面,并带上自己的client_id、request scope等
2. 用户在应用的授权页面确认授权,应用将授权信息发送给Kong(允许某个client_id访问XXX)
3. 应用收到Kong返回的授权码和第三方在Kong中配置的redirect_uri
4. 应用将用户重定向到第三方设置的uri,并在重定向uri中带上了授权码
5. 第三方从uri中获得授权码,用它从Kong中获取Access Token
6. 第三方使用Access Token访问应用、查询数据

这个过程与RFC 6749: The OAuth 2.0 Authorization FrameworkOAuth 认证流程详解中的介绍不同地方在于,第三方的redirect_uri是注册在Kong中的,不是访问应用的授权页面时带过去的。

(不是很确定,需要继续核实)Kong能够做到的是允许获取到Access Token的第三方访问Route或Service。第三方服务能够获取的数据,在应用内进行限制。譬如说,用户A授权第三方从应用中获取自己的信息,第三方就可以访问应用的相应接口。但Kong并不知道第三方正在查询的是哪个用户的信息,如果第三方试图查询用户B的信息,这时候需要应用拒绝请求。

上面是标准的授权码方式,对更简单的password的方式,kong也支持。

要验证OAuth 2.0,有开发个简单的应用,这里暂时不试验,先过比较容易试验的插件。2018-10-19 18:40:49

参考

  1. Kong的plugins
  2. Kong Plugins Website
  3. API网关Kong的功能梳理和插件使用(一):基本使用过程
  4. google echo service
  5. Kong Plugin: Basic Authentication
  6. Kong Plugin: Key Auth
  7. Kong Plugin: JWT Auth
  8. RFC7519:JSON Web Token (JWT)
  9. JSON Web Tokens
  10. Kong Plugin: OAuth 2.0
  11. RFC 6749: The OAuth 2.0 Authorization Framework
  12. OAuth 认证流程详解

kong

  1. API网关Kong学习笔记(二十六): Kong 1.1引入db-less模式,无数据库部署
  2. API网关Kong学习笔记(二十五): 重温 kong ingress controller
  3. API网关Kong学习笔记(二十四): 在kubernetes中启用kong的插件
  4. API网关Kong学习笔记(二十三): Kong 1.0.3的plugin/插件机制的实现
  5. API网关Kong学习笔记(二十二): Kong 1.0.3源代码快速走读
  6. API网关Kong学习笔记(二十一): Kong的开发环境设置(IntelliJ Idea)
  7. API网关Kong学习笔记(二十): Kong 1.0.3的安装部署和与Kubernetes的对接
  8. API网关Kong学习笔记(十九): Kong的性能测试(与Nginx对比)
  9. API网关Kong学习笔记(十八): Kong Ingress Controller的CRD详细说明
  10. API网关Kong学习笔记(十七): Kong Ingress Controller的使用
  11. API网关Kong学习笔记(十六): Kong转发请求的工作过程
  12. API网关Kong学习笔记(十五): KongIngress的定义细节
  13. API网关Kong学习笔记(十四): Kong的Admin API概览和使用
  14. API网关Kong学习笔记(十三): 向数据库中插入记录的过程分析
  15. API网关Kong学习笔记(十二): 插件的目录中schema分析
  16. API网关Kong学习笔记(十一): 自己动手写一个插件
  17. API网关Kong学习笔记(十): Kong在生产环境中的部署与性能测试方法
  18. API网关Kong学习笔记(九): Kong对WebSocket的支持
  19. API网关Kong学习笔记(八): Kong Ingress Controller的实现
  20. API网关Kong学习笔记(七): Kong数据平面Plugin的调用与实现
  21. API网关Kong学习笔记(六): Kong数据平面的事件、初始化与插件加载
  22. API网关Kong学习笔记(五): 功能梳理和插件使用-安全插件使用
  23. API网关Kong学习笔记(四): 功能梳理和插件使用-认证插件使用
  24. API网关Kong学习笔记(三): 功能梳理和插件使用-基本使用过程
  25. API网关Kong学习笔记(二): Kong与Kubernetes集成的方法
  26. API网关Kong学习笔记(一): Nginx、OpenResty和Kong入门,基础概念和安装部署
  27. API网关Kong学习笔记(零): 使用过程中遇到的问题以及解决方法

推荐阅读

Copyright @2011-2019 All rights reserved. 转载请添加原文连接,合作请加微信lijiaocn或者发送邮件: [email protected],备注网站合作

友情链接:  系统软件  程序语言  运营经验  水库文集  网络课程  微信网文  发现知识星球