如何使用 Python 解码 `X-ARR-ClientCert` header?
How to decode `X-ARR-ClientCert` header using Python?
如何将 Azure 应用服务传递给我的 Azure 函数代码的 X-ARR-ClientCert
header 解码?
示例:
- HTTP-triggered、Python Azure 函数
- Azure 应用服务配置为接受客户端证书
- 请求者使用 GET 请求发送客户端证书(根据 Postman instructions here)
- Azure 应用服务通过
X-ARR-ClientCert
header 将客户端证书传递给函数代码
问题:
- 我找不到关于此 header 编码方式的文档
- 我找不到如何使用 Python
解码此 header 的示例
我得到的最接近的是这段代码:
import logging
import base64
import azure.functions as func
def main(req: func.HttpRequest) -> func.HttpResponse:
logging.info('####### Python HTTP trigger certificate validation function processing a request. #######')
# Retrieve client cert from headers
req_cert_str = req.headers.get("X-ARR-ClientCert")
req_cert_bytes = base64.b64decode(req_cert_str)
decoded_string = req_cert_bytes.decode('cp1252')
return func.HttpResponse(
decoded_string
)
- 这导致
Status 500 Internal server error
和:
Exception while executing function: Functions.certiFunc <--- Result: Failure Exception: UnicodeDecodeError: 'charmap' codec can't decode byte 0x8d in position 403: character maps to <undefined> Stack: File "/azure-functions-host/workers/python/3.8/LINUX/X64/azure_functions_worker/dispatcher.py", line 343, in _handle__invocation_request call_result = await self._loop.run_in_executor( File "/usr/local/lib/python3.8/concurrent/futures/thread.py", line 57, in run result = self.fn(*self.args, **self.kwargs) File "/azure-functions-host/workers/python/3.8/LINUX/X64/azure_functions_worker/dispatcher.py", line 480, in __run_sync_func return func(**params) File "/home/site/wwwroot/certiFunc/__init__.py", line 14, in main decoded_string = req_cert_bytes.decode('cp1252') File "/usr/local/lib/python3.8/encodings/cp1252.py", line 15, in decode return codecs.charmap_decode(input,errors,decoding_table)
- 当代入
decoded_string = req_cert_bytes.decode('utf-8')
时,我得到:
Exception while executing function: Functions.certiFunc <--- Result: Failure Exception: UnicodeDecodeError: 'utf-8' codec can't decode byte 0x82 in position 1: invalid start byte Stack: File "/azure-functions-host/workers/python/3.8/LINUX/X64/azure_functions_worker/dispatcher.py", line 343, in _handle__invocation_request call_result = await self._loop.run_in_executor( File "/usr/local/lib/python3.8/concurrent/futures/thread.py", line 57, in run result = self.fn(*self.args, **self.kwargs) File "/azure-functions-host/workers/python/3.8/LINUX/X64/azure_functions_worker/dispatcher.py", line 480, in __run_sync_func return func(**params) File "/home/site/wwwroot/certiFunc/__init__.py", line 14, in main decoded_string = req_cert_bytes.decode('utf-8')
- 当运行以下(直接解码header)...
req_cert_str = req.headers.get("X-ARR-ClientCert")
decoded_string = base64.b64decode(req_cert_str)
...我得到 Status 200 Success
但响应是二进制 (?) 字符和纯文本的混搭:
使用 Python 解码此 header 的正确方法是什么?
进一步阅读 Github 提出的问题 here
由于您是从 Postman 添加客户端证书,因此它是 DER(二进制)格式。您可以使用 Python cryptography.
从字节本身解码 x509 证书
from cryptography import x509
# header is base64 encoded string, so extract the bytes first
req_cert_str = req.headers.get("X-ARR-ClientCert")
req_cert_bytes = base64.b64decode(req_cert_str)
cert = x509.load_der_x509_certificate(req_cert_bytes)
# do stuffs with cert
logging.info(f'Received client cert with serial number: {cert.serial_number}')
注意:如果证书是 PEM 格式,则需要使用 x509.load_pem_x509_certificate(req_cert_bytes)
如何将 Azure 应用服务传递给我的 Azure 函数代码的 X-ARR-ClientCert
header 解码?
示例:
- HTTP-triggered、Python Azure 函数
- Azure 应用服务配置为接受客户端证书
- 请求者使用 GET 请求发送客户端证书(根据 Postman instructions here)
- Azure 应用服务通过
X-ARR-ClientCert
header 将客户端证书传递给函数代码
问题:
- 我找不到关于此 header 编码方式的文档
- 我找不到如何使用 Python 解码此 header 的示例
我得到的最接近的是这段代码:
import logging
import base64
import azure.functions as func
def main(req: func.HttpRequest) -> func.HttpResponse:
logging.info('####### Python HTTP trigger certificate validation function processing a request. #######')
# Retrieve client cert from headers
req_cert_str = req.headers.get("X-ARR-ClientCert")
req_cert_bytes = base64.b64decode(req_cert_str)
decoded_string = req_cert_bytes.decode('cp1252')
return func.HttpResponse(
decoded_string
)
- 这导致
Status 500 Internal server error
和:
Exception while executing function: Functions.certiFunc <--- Result: Failure Exception: UnicodeDecodeError: 'charmap' codec can't decode byte 0x8d in position 403: character maps to <undefined> Stack: File "/azure-functions-host/workers/python/3.8/LINUX/X64/azure_functions_worker/dispatcher.py", line 343, in _handle__invocation_request call_result = await self._loop.run_in_executor( File "/usr/local/lib/python3.8/concurrent/futures/thread.py", line 57, in run result = self.fn(*self.args, **self.kwargs) File "/azure-functions-host/workers/python/3.8/LINUX/X64/azure_functions_worker/dispatcher.py", line 480, in __run_sync_func return func(**params) File "/home/site/wwwroot/certiFunc/__init__.py", line 14, in main decoded_string = req_cert_bytes.decode('cp1252') File "/usr/local/lib/python3.8/encodings/cp1252.py", line 15, in decode return codecs.charmap_decode(input,errors,decoding_table)
- 当代入
decoded_string = req_cert_bytes.decode('utf-8')
时,我得到:
Exception while executing function: Functions.certiFunc <--- Result: Failure Exception: UnicodeDecodeError: 'utf-8' codec can't decode byte 0x82 in position 1: invalid start byte Stack: File "/azure-functions-host/workers/python/3.8/LINUX/X64/azure_functions_worker/dispatcher.py", line 343, in _handle__invocation_request call_result = await self._loop.run_in_executor( File "/usr/local/lib/python3.8/concurrent/futures/thread.py", line 57, in run result = self.fn(*self.args, **self.kwargs) File "/azure-functions-host/workers/python/3.8/LINUX/X64/azure_functions_worker/dispatcher.py", line 480, in __run_sync_func return func(**params) File "/home/site/wwwroot/certiFunc/__init__.py", line 14, in main decoded_string = req_cert_bytes.decode('utf-8')
- 当运行以下(直接解码header)...
req_cert_str = req.headers.get("X-ARR-ClientCert")
decoded_string = base64.b64decode(req_cert_str)
...我得到 Status 200 Success
但响应是二进制 (?) 字符和纯文本的混搭:
使用 Python 解码此 header 的正确方法是什么?
进一步阅读 Github 提出的问题 here
由于您是从 Postman 添加客户端证书,因此它是 DER(二进制)格式。您可以使用 Python cryptography.
从字节本身解码 x509 证书from cryptography import x509
# header is base64 encoded string, so extract the bytes first
req_cert_str = req.headers.get("X-ARR-ClientCert")
req_cert_bytes = base64.b64decode(req_cert_str)
cert = x509.load_der_x509_certificate(req_cert_bytes)
# do stuffs with cert
logging.info(f'Received client cert with serial number: {cert.serial_number}')
注意:如果证书是 PEM 格式,则需要使用 x509.load_pem_x509_certificate(req_cert_bytes)