--- name: implementing-api-gateway-security-controls description: > 在API网关层实施安全控制,包括认证强制执行、速率限制、请求验证、IP白名单、TLS终止和威胁防护。 配置API网关(Kong、AWS API Gateway、Azure APIM、Apigee)作为集中式安全执行点, 在流量到达后端服务前对所有API流量进行验证、节流和监控。 domain: cybersecurity subdomain: api-security tags: [api-security, api-gateway, kong, aws-api-gateway, rate-limiting, waf] version: 1.0.0 author: mahipal license: Apache-2.0 --- # 实施API网关安全控制 ## 适用场景 - 为微服务API部署集中式认证和授权层 - 对所有API端点实施速率限制、节流和配额管理 - 在网关级别根据OpenAPI规范配置请求/响应验证 - 为API流量设置TLS终止、双向TLS和证书管理 - 将WAF规则与API网关集成,阻断注入、XSS和已知攻击模式 **不适用**作为唯一安全层。API网关提供纵深防御,但后端服务也必须验证授权和输入。 ## 前置条件 - 已选择并部署API网关平台(Kong、AWS API Gateway、Azure APIM或Apigee) - 所有后端API的OpenAPI/Swagger规范 - 网关域名的TLS证书 - 已为OAuth2/OIDC配置身份提供商(IdP)(Okta、Auth0、Azure AD) - 监控和日志基础设施(CloudWatch、Datadog、ELK) - 后端服务端点已注册并可从网关访问 ## 工作流程 ### 步骤1:Kong网关安全配置 ```yaml # kong.yml - 带安全插件的声明式Kong配置 _format_version: "3.0" services: - name: user-service url: http://user-service:8080 routes: - name: user-api paths: - /api/v1/users methods: - GET - POST - PUT - PATCH - DELETE strip_path: false plugins: # 1. 认证:JWT验证 - name: jwt config: uri_param_names: - jwt header_names: - Authorization claims_to_verify: - exp maximum_expiration: 3600 # 令牌最大有效期1小时 # 2. 速率限制 - name: rate-limiting config: minute: 60 hour: 1000 policy: redis redis_host: redis redis_port: 6379 fault_tolerant: true hide_client_headers: false limit_by: credential # 按用户而非按IP # 3. 请求大小限制 - name: request-size-limiting config: allowed_payload_size: 1 # 最大1MB size_unit: megabytes # 4. IP限制(管理端点) - name: ip-restriction service: admin-service config: allow: - 10.0.0.0/8 - 172.16.0.0/12 # 5. 机器人检测 - name: bot-detection config: deny: - "sqlmap" - "nikto" - "nmap" - "masscan" # 6. CORS配置 - name: cors config: origins: - "https://app.example.com" methods: - GET - POST - PUT - PATCH - DELETE headers: - Authorization - Content-Type credentials: true max_age: 3600 # 7. 响应转换器 - 移除敏感头部 - name: response-transformer config: remove: headers: - X-Powered-By - Server add: headers: - "X-Content-Type-Options: nosniff" - "X-Frame-Options: DENY" - "Strict-Transport-Security: max-age=31536000; includeSubDomains" - "Content-Security-Policy: default-src 'none'" ``` ### 步骤2:AWS API Gateway安全配置 ```python import boto3 import json apigw = boto3.client('apigatewayv2') # 创建带双向TLS的API api_response = apigw.create_api( Name='secure-api', ProtocolType='HTTP', DisableExecuteApiEndpoint=True, # 强制使用自定义域名 ) api_id = api_response['ApiId'] # 配置授权器(带Cognito的JWT) authorizer = apigw.create_authorizer( ApiId=api_id, AuthorizerType='JWT', IdentitySource='$request.header.Authorization', Name='cognito-jwt-authorizer', JwtConfiguration={ 'Audience': ['your-app-client-id'], 'Issuer': 'https://cognito-idp.us-east-1.amazonaws.com/us-east-1_xxxxx' } ) # 创建带授权器的路由 apigw.create_route( ApiId=api_id, RouteKey='GET /api/v1/users', AuthorizerId=authorizer['AuthorizerId'], AuthorizationType='JWT', ) # 配置节流 apigw.create_stage( ApiId=api_id, StageName='prod', DefaultRouteSettings={ 'ThrottlingBurstLimit': 100, 'ThrottlingRateLimit': 50.0, # 每秒50个请求 }, AccessLogSettings={ 'DestinationArn': 'arn:aws:logs:us-east-1:123456789:log-group:api-access-logs', 'Format': json.dumps({ 'requestId': '$context.requestId', 'ip': '$context.identity.sourceIp', 'caller': '$context.identity.caller', 'user': '$context.identity.user', 'requestTime': '$context.requestTime', 'httpMethod': '$context.httpMethod', 'resourcePath': '$context.resourcePath', 'status': '$context.status', 'protocol': '$context.protocol', 'responseLength': '$context.responseLength' }) } ) # WAF关联 waf = boto3.client('wafv2') web_acl = waf.create_web_acl( Name='api-security-acl', Scope='REGIONAL', DefaultAction={'Allow': {}}, Rules=[ { 'Name': 'AWS-AWSManagedRulesSQLiRuleSet', 'Priority': 1, 'Statement': { 'ManagedRuleGroupStatement': { 'VendorName': 'AWS', 'Name': 'AWSManagedRulesSQLiRuleSet' } }, 'OverrideAction': {'None': {}}, 'VisibilityConfig': { 'SampledRequestsEnabled': True, 'CloudWatchMetricsEnabled': True, 'MetricName': 'SQLiRuleSet' } }, { 'Name': 'RateLimit', 'Priority': 2, 'Statement': { 'RateBasedStatement': { 'Limit': 2000, 'AggregateKeyType': 'IP' } }, 'Action': {'Block': {}}, 'VisibilityConfig': { 'SampledRequestsEnabled': True, 'CloudWatchMetricsEnabled': True, 'MetricName': 'RateLimitRule' } }, ], VisibilityConfig={ 'SampledRequestsEnabled': True, 'CloudWatchMetricsEnabled': True, 'MetricName': 'ApiSecurityACL' } ) ``` ### 步骤3:使用OpenAPI Schema进行请求验证 ```yaml # Kong OAS验证插件配置 plugins: - name: oas-validation config: api_spec: | openapi: "3.0.3" info: title: Secure API version: "1.0" paths: /api/v1/users: post: requestBody: required: true content: application/json: schema: type: object required: [name, email] properties: name: type: string maxLength: 100 pattern: "^[a-zA-Z ]+$" email: type: string format: email maxLength: 255 additionalProperties: false # 阻止批量赋值 responses: '201': description: User created validate_request_body: true validate_request_header_params: true validate_request_query_params: true validate_request_uri_params: true verbose_response: false # 错误信息中不暴露Schema详情 ``` ### 步骤4:双向TLS配置 ```bash # 为mTLS生成CA和客户端证书 # 1. 创建CA openssl genrsa -out ca.key 4096 openssl req -new -x509 -key ca.key -out ca.crt -days 365 \ -subj "/CN=API Gateway CA/O=Example Corp" # 2. 创建客户端证书 openssl genrsa -out client.key 2048 openssl req -new -key client.key -out client.csr \ -subj "/CN=api-client/O=Example Corp" openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key \ -CAcreateserial -out client.crt -days 365 # Kong mTLS配置 # 将CA证书上传到Kong curl -X POST http://kong-admin:8001/ca_certificates \ -F "cert=@ca.crt" # 启用mTLS插件 curl -X POST http://kong-admin:8001/services/user-service/plugins \ --data "name=mtls-auth" \ --data "config.ca_certificates[]=$(cat ca_cert_id)" \ --data "config.revocation_check_mode=SKIP" \ --data "config.authenticated_group_by=CN" ``` ### 步骤5:日志和监控配置 ```python # 用于API安全事件的CloudWatch监控 import boto3 cloudwatch = boto3.client('cloudwatch') logs = boto3.client('logs') # 为安全事件创建指标过滤器 security_filters = [ { 'name': 'UnauthorizedAccess', 'pattern': '{ $.status = 401 || $.status = 403 }', 'metric': 'UnauthorizedAccessCount' }, { 'name': 'RateLimitHits', 'pattern': '{ $.status = 429 }', 'metric': 'RateLimitHitCount' }, { 'name': 'ServerErrors', 'pattern': '{ $.status >= 500 }', 'metric': 'ServerErrorCount' }, { 'name': 'LargeResponses', 'pattern': '{ $.responseLength > 1000000 }', 'metric': 'LargeResponseCount' }, ] for sf in security_filters: logs.put_metric_filter( logGroupName='api-access-logs', filterName=sf['name'], filterPattern=sf['pattern'], metricTransformations=[{ 'metricName': sf['metric'], 'metricNamespace': 'APISecurityMetrics', 'metricValue': '1', 'defaultValue': 0 }] ) # 为异常401/403峰值创建告警 cloudwatch.put_metric_alarm( AlarmName='API-UnauthorizedAccessSpike', MetricName='UnauthorizedAccessCount', Namespace='APISecurityMetrics', Statistic='Sum', Period=300, # 5分钟 EvaluationPeriods=1, Threshold=100, ComparisonOperator='GreaterThanThreshold', AlarmActions=['arn:aws:sns:us-east-1:123456789:security-alerts'], AlarmDescription='5分钟内超过100次未授权访问尝试' ) ``` ## 核心概念 | 术语 | 定义 | |------|------------| | **API网关(API Gateway)** | 所有API流量的集中入口点,在路由到后端服务前强制执行认证、授权、速率限制和请求验证 | | **速率限制(Rate Limiting)** | 控制客户端在时间窗口内的API请求数量,防止滥用并确保资源公平分配 | | **请求验证(Request Validation)** | 在转发到后端服务前,验证传入的API请求是否符合预期的Schema(数据类型、必填字段、值范围) | | **双向TLS(Mutual TLS,mTLS)** | 客户端和服务器双方均出示证书的双向TLS认证,为API间通信提供强身份验证 | | **WAF集成(WAF Integration)** | 在API网关层应用Web应用防火墙规则,阻断常见攻击模式(SQL注入、XSS、路径遍历) | | **OAuth2/OIDC** | 基于令牌的认证协议,网关在允许访问前针对身份提供商验证JWT令牌 | ## 工具和系统 - **Kong Gateway**:开源API网关,具有丰富的安全、速率限制和认证插件生态系统 - **AWS API Gateway**:托管API网关服务,内置节流、WAF集成和Lambda授权器 - **Azure API Management**:企业级API网关,具有基于策略的安全、开发者门户和Azure AD集成 - **Apigee(Google Cloud)**:API管理平台,具有威胁防护、配额管理和API分析 - **Envoy Proxy**:高性能代理,在服务网格架构中用作API网关,具有广泛的过滤链 ## 常见场景 ### 场景:使用Kong Gateway保护微服务API **背景**:公司正在将单体API迁移到微服务架构,每个微服务都有自己的REST API。安全团队需要在不修改每个服务的情况下实施集中式认证、速率限制和请求验证。 **方法**: 1. 将Kong Gateway部署为单一入口点,将流量路由到8个后端微服务 2. 配置JWT验证插件,验证公司Keycloak身份提供商的令牌 3. 应用速率限制:普通用户每分钟60个请求,高级用户每分钟300个请求,通过JWT Claims识别 4. 启用OAS验证插件,拒绝不符合OpenAPI规范的请求(阻断批量赋值和注入攻击) 5. 为网关后的服务间通信配置mTLS 6. 配置响应转换器删除Server和X-Powered-By头,并添加安全头 7. 集成AWS WAF实现SQL注入和XSS防护规则 8. 将访问日志配置到CloudWatch,并设置安全指标过滤器和告警 **注意事项**: - 仅依赖网关进行授权,而后端服务也需要验证权限 - 未按认证用户配置速率限制(仅按IP允许攻击者通过IP轮换绕过) - 使用详细错误响应,暴露内部服务架构信息 - 部署后未使用安全工具测试网关配置 - 网关和后端服务之间缺少双向TLS,允许直接访问后端 ## 输出格式 ``` ## API网关安全配置报告 **网关**: Kong 3.5(Kubernetes部署) **后端服务**: 8个微服务 **日期**: 2024-12-15 ### 已实施安全控制 | 控制措施 | 插件/功能 | 配置 | |---------|---------------|---------------| | 认证 | JWT插件 | Cognito IdP,最大TTL 1小时 | | 速率限制 | 速率限制插件 | 60 req/min(用户),Redis后端 | | 请求验证 | OAS验证 | 严格模式,不允许额外属性 | | TLS | Kong TLS | 仅TLS 1.3,启用HSTS | | mTLS | mTLS认证插件 | 管理API需要客户端证书 | | WAF | AWS WAF | SQL注入、XSS、基于速率的规则 | | 响应头 | 响应转换器 | 删除Server头,添加安全头 | | 日志 | HTTP日志插件 | CloudWatch,安全指标过滤器 | ### 验证结果 - JWT验证:过期/无效令牌正确拒绝(测试了50个载荷) - 速率限制:在60 req/min强制执行,返回带Retry-After头的429 - 请求验证:格式错误的请求被拒绝并返回400(测试了30个无效载荷) - mTLS:无客户端证书的请求被拒绝并返回401 - WAF:SQL注入载荷被阻断(测试了Top 100 SQL注入模式) ```