1. 安全概述
1.1 安全架构
Kong提供了多层次的安全防护机制: - 认证层: 验证用户身份 - 授权层: 控制访问权限 - 传输层: SSL/TLS加密 - 应用层: 输入验证和防护
1.2 安全插件分类
- 认证插件: Basic Auth, JWT, OAuth 2.0, LDAP等
- 授权插件: ACL, RBAC等
- 安全防护: Rate Limiting, IP Restriction, Bot Detection等
- 数据保护: Request/Response Transformer等
2. 基础认证
2.1 Basic Authentication
2.1.1 启用Basic Auth插件
# 为服务启用Basic Auth
curl -X POST http://localhost:8001/services/{service}/plugins \
--data "name=basic-auth" \
--data "config.hide_credentials=true"
# 为路由启用Basic Auth
curl -X POST http://localhost:8001/routes/{route}/plugins \
--data "name=basic-auth" \
--data "config.hide_credentials=true"
# 全局启用Basic Auth
curl -X POST http://localhost:8001/plugins \
--data "name=basic-auth"
2.1.2 创建消费者和凭证
# 创建消费者
curl -X POST http://localhost:8001/consumers \
--data "username=john" \
--data "custom_id=user123"
# 为消费者添加Basic Auth凭证
curl -X POST http://localhost:8001/consumers/john/basic-auth \
--data "username=john" \
--data "password=secret123"
# 添加多个凭证
curl -X POST http://localhost:8001/consumers/john/basic-auth \
--data "username=john_api" \
--data "password=api_secret"
2.1.3 测试Basic Auth
# 无认证请求(应该返回401)
curl http://localhost:8000/api/test
# 正确的认证请求
curl -u john:secret123 http://localhost:8000/api/test
# 使用Base64编码
echo -n "john:secret123" | base64
curl -H "Authorization: Basic am9objpzZWNyZXQxMjM=" http://localhost:8000/api/test
2.2 Key Authentication
2.2.1 启用Key Auth插件
# 启用Key Auth插件
curl -X POST http://localhost:8001/services/{service}/plugins \
--data "name=key-auth" \
--data "config.key_names[]=apikey" \
--data "config.key_names[]=x-api-key"
2.2.2 创建API Key
# 为消费者创建API Key
curl -X POST http://localhost:8001/consumers/john/key-auth \
--data "key=my-secret-api-key"
# 自动生成API Key
curl -X POST http://localhost:8001/consumers/john/key-auth
2.2.3 使用API Key
# 通过查询参数
curl http://localhost:8000/api/test?apikey=my-secret-api-key
# 通过请求头
curl -H "apikey: my-secret-api-key" http://localhost:8000/api/test
curl -H "x-api-key: my-secret-api-key" http://localhost:8000/api/test
2.3 HMAC Authentication
2.3.1 启用HMAC Auth插件
# 启用HMAC Auth插件
curl -X POST http://localhost:8001/services/{service}/plugins \
--data "name=hmac-auth" \
--data "config.clock_skew=300"
2.3.2 创建HMAC凭证
# 为消费者创建HMAC凭证
curl -X POST http://localhost:8001/consumers/john/hmac-auth \
--data "username=john" \
--data "secret=my-hmac-secret"
2.3.3 生成HMAC签名
# Python示例
import hmac
import hashlib
import base64
from datetime import datetime
def generate_hmac_signature(secret, method, uri, body, date):
# 构建签名字符串
string_to_sign = f"date: {date}\n(request-target): {method.lower()} {uri}"
if body:
string_to_sign += f"\ndigest: SHA-256={base64.b64encode(hashlib.sha256(body.encode()).digest()).decode()}"
# 生成HMAC签名
signature = hmac.new(
secret.encode(),
string_to_sign.encode(),
hashlib.sha256
).digest()
return base64.b64encode(signature).decode()
# 使用示例
secret = "my-hmac-secret"
method = "GET"
uri = "/api/test"
body = ""
date = datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')
signature = generate_hmac_signature(secret, method, uri, body, date)
print(f"Authorization: hmac username=\"john\", algorithm=\"hmac-sha256\", headers=\"date request-target\", signature=\"{signature}\"")
3. JWT认证
3.1 JWT插件配置
3.1.1 启用JWT插件
# 基本JWT配置
curl -X POST http://localhost:8001/services/{service}/plugins \
--data "name=jwt" \
--data "config.secret_is_base64=false"
# 高级JWT配置
curl -X POST http://localhost:8001/services/{service}/plugins \
--data "name=jwt" \
--data "config.uri_param_names[]=jwt" \
--data "config.header_names[]=authorization" \
--data "config.claims_to_verify[]=exp" \
--data "config.claims_to_verify[]=iat"
3.1.2 创建JWT凭证
# 为消费者创建JWT凭证
curl -X POST http://localhost:8001/consumers/john/jwt \
--data "key=my-jwt-key" \
--data "secret=my-jwt-secret"
# 使用RSA算法
curl -X POST http://localhost:8001/consumers/john/jwt \
--data "key=my-rsa-key" \
--data "algorithm=RS256" \
--data "rsa_public_key=@public_key.pem"
3.2 JWT Token生成
3.2.1 使用HS256算法
# Python JWT生成示例
import jwt
import time
# JWT配置
key = "my-jwt-key"
secret = "my-jwt-secret"
# JWT载荷
payload = {
"iss": key, # 发行者,必须与Kong中的key匹配
"exp": int(time.time()) + 3600, # 过期时间(1小时后)
"iat": int(time.time()), # 签发时间
"sub": "john", # 主题(用户ID)
"custom_claim": "custom_value" # 自定义声明
}
# 生成JWT
token = jwt.encode(payload, secret, algorithm="HS256")
print(f"JWT Token: {token}")
3.2.2 使用RS256算法
# 使用RSA私钥生成JWT
with open('private_key.pem', 'r') as f:
private_key = f.read()
payload = {
"iss": "my-rsa-key",
"exp": int(time.time()) + 3600,
"iat": int(time.time()),
"sub": "john"
}
token = jwt.encode(payload, private_key, algorithm="RS256")
print(f"RSA JWT Token: {token}")
3.3 JWT使用
# 通过Authorization头
curl -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..." \
http://localhost:8000/api/test
# 通过查询参数
curl "http://localhost:8000/api/test?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
# 通过自定义头
curl -H "X-JWT-Token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..." \
http://localhost:8000/api/test
4. OAuth 2.0认证
4.1 OAuth 2.0插件配置
4.1.1 启用OAuth 2.0插件
# 基本OAuth 2.0配置
curl -X POST http://localhost:8001/services/{service}/plugins \
--data "name=oauth2" \
--data "config.scopes[]=read" \
--data "config.scopes[]=write" \
--data "config.mandatory_scope=true" \
--data "config.enable_authorization_code=true"
# 高级OAuth 2.0配置
curl -X POST http://localhost:8001/services/{service}/plugins \
--data "name=oauth2" \
--data "config.scopes[]=read" \
--data "config.scopes[]=write" \
--data "config.scopes[]=admin" \
--data "config.token_expiration=3600" \
--data "config.enable_client_credentials=true" \
--data "config.enable_implicit_grant=true"
4.1.2 创建OAuth应用
# 为消费者创建OAuth应用
curl -X POST http://localhost:8001/consumers/john/oauth2 \
--data "name=My App" \
--data "client_id=my-client-id" \
--data "client_secret=my-client-secret" \
--data "redirect_uris[]=http://localhost:3000/callback"
4.2 OAuth 2.0授权流程
4.2.1 授权码模式
# 1. 获取授权码
# 用户访问授权URL
http://localhost:8000/oauth2/authorize?response_type=code&client_id=my-client-id&scope=read&redirect_uri=http://localhost:3000/callback
# 2. 用户授权后,重定向到回调URL
# http://localhost:3000/callback?code=AUTHORIZATION_CODE
# 3. 使用授权码获取访问令牌
curl -X POST http://localhost:8000/oauth2/token \
--data "grant_type=authorization_code" \
--data "client_id=my-client-id" \
--data "client_secret=my-client-secret" \
--data "code=AUTHORIZATION_CODE" \
--data "redirect_uri=http://localhost:3000/callback"
4.2.2 客户端凭证模式
# 直接获取访问令牌
curl -X POST http://localhost:8000/oauth2/token \
--data "grant_type=client_credentials" \
--data "client_id=my-client-id" \
--data "client_secret=my-client-secret" \
--data "scope=read write"
4.2.3 隐式授权模式
# 直接在授权URL中获取访问令牌
http://localhost:8000/oauth2/authorize?response_type=token&client_id=my-client-id&scope=read&redirect_uri=http://localhost:3000/callback
# 重定向URL包含访问令牌
# http://localhost:3000/callback#access_token=ACCESS_TOKEN&token_type=bearer&expires_in=3600
4.3 使用OAuth 2.0令牌
# 使用访问令牌访问API
curl -H "Authorization: Bearer ACCESS_TOKEN" \
http://localhost:8000/api/test
# 刷新令牌
curl -X POST http://localhost:8000/oauth2/token \
--data "grant_type=refresh_token" \
--data "client_id=my-client-id" \
--data "client_secret=my-client-secret" \
--data "refresh_token=REFRESH_TOKEN"
5. LDAP认证
5.1 LDAP插件配置
# 启用LDAP认证插件
curl -X POST http://localhost:8001/services/{service}/plugins \
--data "name=ldap-auth" \
--data "config.ldap_host=ldap.example.com" \
--data "config.ldap_port=389" \
--data "config.start_tls=false" \
--data "config.base_dn=ou=users,dc=example,dc=com" \
--data "config.attribute=uid" \
--data "config.cache_ttl=60"
# LDAPS配置
curl -X POST http://localhost:8001/services/{service}/plugins \
--data "name=ldap-auth" \
--data "config.ldap_host=ldaps.example.com" \
--data "config.ldap_port=636" \
--data "config.start_tls=true" \
--data "config.verify_ldap_host=true" \
--data "config.base_dn=ou=users,dc=example,dc=com" \
--data "config.attribute=uid"
5.2 LDAP认证测试
# 使用LDAP用户名和密码
curl -u ldap_user:ldap_password http://localhost:8000/api/test
# 使用Basic Auth头
curl -H "Authorization: Basic $(echo -n 'ldap_user:ldap_password' | base64)" \
http://localhost:8000/api/test
6. 访问控制列表(ACL)
6.1 ACL插件配置
# 启用ACL插件
curl -X POST http://localhost:8001/services/{service}/plugins \
--data "name=acl" \
--data "config.allow[]=admin" \
--data "config.allow[]=developer"
# 黑名单模式
curl -X POST http://localhost:8001/services/{service}/plugins \
--data "name=acl" \
--data "config.deny[]=guest" \
--data "config.deny[]=anonymous"
6.2 为消费者分配组
# 为消费者添加组
curl -X POST http://localhost:8001/consumers/john/acls \
--data "group=admin"
curl -X POST http://localhost:8001/consumers/john/acls \
--data "group=developer"
# 查看消费者的组
curl http://localhost:8001/consumers/john/acls
6.3 动态ACL管理
# 添加新组到允许列表
curl -X PATCH http://localhost:8001/plugins/{acl-plugin-id} \
--data "config.allow[]=manager"
# 从消费者移除组
curl -X DELETE http://localhost:8001/consumers/john/acls/{acl-id}
7. 基于角色的访问控制(RBAC)
7.1 RBAC概念
7.1.1 RBAC组件
- 用户(User): 系统的使用者
- 角色(Role): 权限的集合
- 权限(Permission): 对资源的操作权限
- 资源(Resource): 被保护的API端点
7.1.2 RBAC插件配置
# 启用RBAC插件(企业版功能)
curl -X POST http://localhost:8001/services/{service}/plugins \
--data "name=rbac" \
--data "config.roles[]=admin" \
--data "config.roles[]=user" \
--data "config.permissions.admin[]=read" \
--data "config.permissions.admin[]=write" \
--data "config.permissions.admin[]=delete" \
--data "config.permissions.user[]=read"
7.2 自定义RBAC实现
7.2.1 使用JWT Claims
# JWT中包含角色信息
payload = {
"iss": "my-jwt-key",
"exp": int(time.time()) + 3600,
"sub": "john",
"roles": ["admin", "user"],
"permissions": ["read", "write"]
}
token = jwt.encode(payload, secret, algorithm="HS256")
7.2.2 使用Request Transformer
# 基于JWT claims添加头部
curl -X POST http://localhost:8001/services/{service}/plugins \
--data "name=request-transformer" \
--data "config.add.headers=X-User-Role:$(jwt.roles)" \
--data "config.add.headers=X-User-Permissions:$(jwt.permissions)"
8. 安全防护插件
8.1 速率限制
8.1.1 基本速率限制
# 全局速率限制
curl -X POST http://localhost:8001/plugins \
--data "name=rate-limiting" \
--data "config.minute=100" \
--data "config.hour=1000" \
--data "config.policy=local"
# 基于消费者的速率限制
curl -X POST http://localhost:8001/plugins \
--data "name=rate-limiting" \
--data "config.minute=1000" \
--data "config.hour=10000" \
--data "config.policy=redis" \
--data "config.redis_host=redis.example.com"
8.1.2 高级速率限制
# 响应速率限制
curl -X POST http://localhost:8001/services/{service}/plugins \
--data "name=response-ratelimiting" \
--data "config.limits.video=10" \
--data "config.limits.image=20" \
--data "config.limits.json=100"
# 基于请求大小的限制
curl -X POST http://localhost:8001/services/{service}/plugins \
--data "name=request-size-limiting" \
--data "config.allowed_payload_size=1024"
8.2 IP限制
8.2.1 IP白名单
# IP白名单
curl -X POST http://localhost:8001/services/{service}/plugins \
--data "name=ip-restriction" \
--data "config.allow[]=192.168.1.0/24" \
--data "config.allow[]=10.0.0.0/8"
8.2.2 IP黑名单
# IP黑名单
curl -X POST http://localhost:8001/services/{service}/plugins \
--data "name=ip-restriction" \
--data "config.deny[]=192.168.1.100" \
--data "config.deny[]=10.0.0.50"
8.2.3 地理位置限制
# 基于国家的限制(需要GeoIP数据库)
curl -X POST http://localhost:8001/services/{service}/plugins \
--data "name=ip-restriction" \
--data "config.allow_countries[]=US" \
--data "config.allow_countries[]=CN" \
--data "config.deny_countries[]=XX"
8.3 Bot检测
# 启用Bot检测插件
curl -X POST http://localhost:8001/services/{service}/plugins \
--data "name=bot-detection" \
--data "config.allow[]=googlebot" \
--data "config.allow[]=bingbot" \
--data "config.deny[]=badbot"
8.4 CORS配置
# 配置CORS
curl -X POST http://localhost:8001/services/{service}/plugins \
--data "name=cors" \
--data "config.origins[]=https://example.com" \
--data "config.origins[]=https://app.example.com" \
--data "config.methods[]=GET" \
--data "config.methods[]=POST" \
--data "config.methods[]=PUT" \
--data "config.methods[]=DELETE" \
--data "config.headers[]=Accept" \
--data "config.headers[]=Content-Type" \
--data "config.headers[]=Authorization" \
--data "config.exposed_headers[]=X-Custom-Header" \
--data "config.credentials=true" \
--data "config.max_age=3600"
9. 数据保护
9.1 请求/响应转换
9.1.1 隐藏敏感信息
# 移除敏感请求头
curl -X POST http://localhost:8001/services/{service}/plugins \
--data "name=request-transformer" \
--data "config.remove.headers[]=X-Internal-Token" \
--data "config.remove.headers[]=X-Debug-Info"
# 移除敏感响应头
curl -X POST http://localhost:8001/services/{service}/plugins \
--data "name=response-transformer" \
--data "config.remove.headers[]=Server" \
--data "config.remove.headers[]=X-Powered-By"
9.1.2 数据脱敏
# 使用Lua脚本进行数据脱敏
curl -X POST http://localhost:8001/services/{service}/plugins \
--data "name=pre-function" \
--data 'config.functions[]=
local body = kong.request.get_raw_body()
if body then
-- 脱敏处理
body = string.gsub(body, "\"password\":\"[^\"]*\"", "\"password\":\"***\"")
kong.service.request.set_raw_body(body)
end'
9.2 数据加密
9.2.1 字段级加密
-- 自定义加密插件示例
local crypto = require "crypto"
local json = require "cjson"
function encrypt_sensitive_fields(data, key)
local parsed = json.decode(data)
-- 加密敏感字段
if parsed.credit_card then
parsed.credit_card = crypto.encrypt("aes-256-cbc", parsed.credit_card, key)
end
if parsed.ssn then
parsed.ssn = crypto.encrypt("aes-256-cbc", parsed.ssn, key)
end
return json.encode(parsed)
end
10. 安全监控和审计
10.1 访问日志
10.1.1 文件日志
# 启用文件日志
curl -X POST http://localhost:8001/plugins \
--data "name=file-log" \
--data "config.path=/var/log/kong/access.log" \
--data "config.reopen=true"
10.1.2 HTTP日志
# 发送日志到外部系统
curl -X POST http://localhost:8001/plugins \
--data "name=http-log" \
--data "config.http_endpoint=https://log-collector.example.com/logs" \
--data "config.method=POST" \
--data "config.content_type=application/json"
10.1.3 Syslog
# 发送到Syslog
curl -X POST http://localhost:8001/plugins \
--data "name=syslog" \
--data "config.host=syslog.example.com" \
--data "config.port=514" \
--data "config.facility=16"
10.2 安全事件监控
10.2.1 失败认证监控
# 监控认证失败
curl -X POST http://localhost:8001/plugins \
--data "name=prometheus" \
--data "config.per_consumer=true"
# 查看认证失败指标
curl http://localhost:8001/metrics | grep kong_http_status | grep 401
10.2.2 异常访问模式检测
-- 自定义监控插件
local redis = require "resty.redis"
function detect_anomaly(consumer_id, endpoint)
local red = redis:new()
red:connect("127.0.0.1", 6379)
local key = "access_pattern:" .. consumer_id .. ":" .. endpoint
local count = red:incr(key)
red:expire(key, 60) -- 1分钟窗口
if count > 100 then -- 异常阈值
kong.log.warn("Anomalous access pattern detected for consumer: ", consumer_id)
-- 发送告警
end
end
10.3 合规性审计
10.3.1 GDPR合规
# 记录数据访问日志
curl -X POST http://localhost:8001/plugins \
--data "name=datadog" \
--data "config.host=datadog.example.com" \
--data "config.tags[]=environment:production" \
--data "config.tags[]=compliance:gdpr"
10.3.2 PCI DSS合规
# 确保信用卡数据安全
curl -X POST http://localhost:8001/services/payment/plugins \
--data "name=request-transformer" \
--data "config.remove.body[]=credit_card_number" \
--data "config.add.headers[]=X-PCI-Compliant:true"
11. 安全最佳实践
11.1 认证策略
11.1.1 多因素认证
# 组合多种认证方式
# 1. 首先验证API Key
curl -X POST http://localhost:8001/services/{service}/plugins \
--data "name=key-auth"
# 2. 然后验证JWT
curl -X POST http://localhost:8001/services/{service}/plugins \
--data "name=jwt"
# 3. 最后检查ACL
curl -X POST http://localhost:8001/services/{service}/plugins \
--data "name=acl" \
--data "config.allow[]=verified_users"
11.1.2 令牌轮换
# 定期轮换JWT密钥
import schedule
import time
def rotate_jwt_secret():
new_secret = generate_random_secret()
update_kong_jwt_secret(consumer_id, new_secret)
notify_clients_of_new_secret(new_secret)
# 每周轮换一次
schedule.every().week.do(rotate_jwt_secret)
while True:
schedule.run_pending()
time.sleep(1)
11.2 网络安全
11.2.1 网络隔离
# Docker Compose网络隔离
version: '3.7'
services:
kong:
image: kong:latest
networks:
- frontend
- backend
database:
image: postgres:13
networks:
- backend # 只能从后端访问
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true # 内部网络
11.2.2 防火墙规则
# iptables规则示例
# 只允许特定端口
iptables -A INPUT -p tcp --dport 8000 -j ACCEPT # Proxy
iptables -A INPUT -p tcp --dport 8443 -j ACCEPT # Proxy SSL
iptables -A INPUT -p tcp --dport 8001 -s 10.0.0.0/8 -j ACCEPT # Admin API(仅内网)
iptables -A INPUT -j DROP # 拒绝其他连接
11.3 配置安全
11.3.1 敏感信息管理
# 使用环境变量存储敏感信息
export KONG_PG_PASSWORD="$(cat /run/secrets/db_password)"
export JWT_SECRET="$(cat /run/secrets/jwt_secret)"
# 使用Vault管理密钥
export KONG_VAULT_URI="vault://secret/kong/database#password"
11.3.2 最小权限原则
# 为不同环境创建不同的消费者
# 开发环境
curl -X POST http://localhost:8001/consumers \
--data "username=dev-client" \
--data "tags[]=environment:development"
# 生产环境
curl -X POST http://localhost:8001/consumers \
--data "username=prod-client" \
--data "tags[]=environment:production"
11.4 监控和告警
11.4.1 安全指标监控
# 监控关键安全指标
# 1. 认证失败率
# 2. 异常访问模式
# 3. 速率限制触发
# 4. IP黑名单命中
# 使用Prometheus查询
rate(kong_http_status{code="401"}[5m]) # 401错误率
rate(kong_http_status{code="429"}[5m]) # 速率限制触发率
11.4.2 自动化响应
# 自动封禁异常IP
def auto_ban_suspicious_ip(ip_address, reason):
# 添加到IP黑名单
response = requests.patch(
f"http://localhost:8001/plugins/{ip_restriction_plugin_id}",
data={"config.deny[]": ip_address}
)
# 记录封禁日志
logger.warning(f"Auto-banned IP {ip_address}: {reason}")
# 发送告警
send_alert(f"IP {ip_address} has been automatically banned")
12. 总结
Kong提供了全面的安全认证与授权机制,从基础的API Key认证到复杂的OAuth 2.0流程,再到企业级的RBAC控制。通过合理配置这些安全插件,可以构建一个安全、可靠的API网关系统。
关键要点: 1. 多层防护: 结合多种认证和安全插件 2. 最小权限: 遵循最小权限原则 3. 监控审计: 实施全面的安全监控 4. 定期更新: 保持密钥和证书的定期轮换 5. 合规性: 确保符合相关法规要求
在下一章节中,我们将详细介绍Kong的性能优化与监控。