compliance/examples/rules/authentication_headers_rule.yaml
2025-05-16 15:18:02 +08:00

99 lines
3.6 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

id: authentication-headers-required
name: API认证头部要求规则
description: 验证API请求是否包含必要的认证头部如Authorization、X-API-Key等
category: Security
version: 1.0.0
severity: error
is_enabled: true
tags:
- security
- authentication
- headers
- authorization
target_type: APIRequest
lifecycle: RequestPreparation
scope: RequestHeaders
required_headers:
- name: Authorization
pattern: "^(Bearer|Basic|Digest) [A-Za-z0-9\\-\\._~\\+\\/]+=*$"
description: 认证令牌,格式应为"Bearer token"、"Basic base64"或"Digest value"
- name: X-API-Key
pattern: "^[A-Za-z0-9]{32,64}$"
description: API密钥应为32-64位的字母数字字符
- name: X-Request-ID
pattern: "^[A-Za-z0-9\\-]{8,36}$"
description: 请求ID用于跟踪请求应为8-36位的字母数字和连字符
check_mode: any # 可以是"all"或"any",表示是需要满足所有头部还是任一头部
code: |
def validate(context):
"""验证API请求是否包含必要的认证头部"""
request = context.get('api_request')
if not request:
return {'is_valid': False, 'message': '缺少API请求对象'}
headers = request.headers or {}
required_headers = context.get('required_headers', [])
check_mode = context.get('check_mode', 'any')
# 获取缺失的头部和无效的头部
missing_headers = []
invalid_headers = []
valid_headers = []
import re
for header in required_headers:
header_name = header.get('name')
header_pattern = header.get('pattern')
if header_name not in headers:
missing_headers.append({
'name': header_name,
'description': header.get('description', '')
})
continue
header_value = headers[header_name]
# 如果指定了模式,验证头部值是否符合模式
if header_pattern and not re.match(header_pattern, header_value):
invalid_headers.append({
'name': header_name,
'value': header_value,
'pattern': header_pattern,
'description': header.get('description', '')
})
else:
valid_headers.append(header_name)
# 根据检查模式判断是否验证通过
if check_mode == 'all':
# 需要所有头部都存在且有效
is_valid = not missing_headers and not invalid_headers
else: # 'any'
# 至少有一个有效的头部即可
is_valid = len(valid_headers) > 0
if is_valid:
message = '请求包含有效的认证头部'
if check_mode == 'any':
message += f": {', '.join(valid_headers)}"
else:
if check_mode == 'all':
if missing_headers:
message = f"请求缺少必要的认证头部: {', '.join([h['name'] for h in missing_headers])}"
else:
message = f"请求包含无效的认证头部: {', '.join([h['name'] for h in invalid_headers])}"
else: # 'any'
message = f"请求不包含任何有效的认证头部,至少需要其中之一: {', '.join([h['name'] for h in required_headers])}"
return {
'is_valid': is_valid,
'message': message,
'details': {
'check_mode': check_mode,
'valid_headers': valid_headers,
'missing_headers': missing_headers,
'invalid_headers': invalid_headers
}
}