Python Flask中启用AWS Secrets Manager+AWS Parameter Store配置中心
问题
最近需要改造一个Python的Flask项目。需要在这个项目中添加AWS Secrets Manager作为配置中心,主要是数据库相关配置。
前提
得预先在Amazon RDS里面新建好数据库用户和数据库,以AWS Aurora为例子,建库和建用户语句类似如下:
create database hf_gc default character set utf8mb4 collate utf8mb4_unicode_ci;
create user 'hf_gc'@'%' identified by '3pbP0EMfZcOusvaawfaOv4U';
grant all privileges on hf_gc.* to 'hf_gc'@'%';
flush privileges;
Secrets Manager
新建轮转密钥
开始新建Aurora密钥,如下图:
设置密钥名称为/dev/flask-rds
,如下图:
启用自动轮转密码,并设置相关策略,如下图:
最后审计一下,没问题就直接创建,如下图:
Parameter Store
设置数据库主机参数,如下图:
设置Flask Web应用程序使用的轮转密钥参数,如下图:
Flask
FLASK_PROFILE自定义环境变量
设置自定义环境变量:FLASK_PROFILE
。内容如下:
export FLASK_PROFILE="dev"
这里需要以FLASK_
开头的,进行环境变量命名的。
PyCharm设置如下图:
在Flask中读取环境变量,类似如下方式:
app.config.from_prefixed_env()
app.config["FLASK_PROFILE"] # Is "dev"
安装boto3 SDK
pip install boto3
pip install botocore
secrets_manager.py
aws secrets manager客户端工具类,这里主要就是使用boto3来访问AWS 的secrets manager服务,然后取secrets manager服务中配置/dev/flask-rds
参数。还使用lru_cache缓存管理注解,在使用的时候,需要进行缓存处理。内容如下:
import json
import sys
sys.path.append('./')
from typing import Dict, Anyimport boto3
from botocore.exceptions import ClientError
from functools import lru_cache
from flask import current_appclass SecretsManagerClient:def __init__(self, region_name: str = 'cn-north-1'):"""初始化客户端:param region_name: AWS区域,默认为中国区北京"""self.session = boto3.session.Session()self.client = self.session.client(service_name='secretsmanager',region_name=region_name)@lru_cache(maxsize=32) # 缓存最多32个不同的secretdef get_secret(self, secret_name: str) -> Dict[str, Any]:"""获取Secret的值(带缓存):param secret_name: Secret的完整路径或名称:return: 解析后的Secret字典:raises: ClientError 当获取失败时抛出"""try:current_app.logger.debug(f"Fetching secret: {secret_name}")response = self.client.get_secret_value(SecretId=secret_name)if 'SecretString' in response:secret = response['SecretString']return json.loads(secret)else:raise ValueError("Binary secrets are not supported")except ClientError as e:current_app.logger.error(f"Failed to get secret {secret_name}: {str(e)}")raiseexcept json.JSONDecodeError as e:current_app.logger.error(f"Failed to parse secret JSON: {str(e)}")raise ValueError("Invalid secret JSON format")def clear_cache(self, secret_name: str = None):"""清除缓存:param secret_name: 指定清除某个secret的缓存,None表示清除全部"""if secret_name:self.get_secret.cache_clear(secret_name)else:self.get_secret.cache_clear()current_app.logger.debug(f"Cleared cache for secret: {secret_name or 'all'}")# 创建全局客户端实例(单例模式)
client = SecretsManagerClient()
使用方式,类似如下代码:
from configs.secrets_manager import client
client.clear_cache("/dev/flask-rds") # 清除缓存
secret = client.get_secret("/dev/flask-rds")
user = secret['username'] # 读取用户名
passwd = secret['password']
parameter_store.py
parameter store工具类内容如下:
import json
import sys
sys.path.append('./')
from typing import Dict, Anyimport boto3
from botocore.exceptions import ClientError
from functools import lru_cache
from flask import current_appclass SecretsManagerClient:def __init__(self, region_name: str = 'cn-north-1'):"""初始化客户端:param region_name: AWS区域,默认为中国区北京"""self.session = boto3.session.Session()self.client = self.session.client(service_name='secretsmanager',region_name=region_name)@lru_cache(maxsize=32) # 缓存最多32个不同的secretdef get_secret(self, secret_name: str) -> Dict[str, Any]:"""获取Secret的值(带缓存):param secret_name: Secret的完整路径或名称:return: 解析后的Secret字典:raises: ClientError 当获取失败时抛出"""try:current_app.logger.debug(f"Fetching secret: {secret_name}")response = self.client.get_secret_value(SecretId=secret_name)if 'SecretString' in response:secret = response['SecretString']return json.loads(secret)else:raise ValueError("Binary secrets are not supported")except ClientError as e:current_app.logger.error(f"Failed to get secret {secret_name}: {str(e)}")raiseexcept json.JSONDecodeError as e:current_app.logger.error(f"Failed to parse secret JSON: {str(e)}")raise ValueError("Invalid secret JSON format")def clear_cache(self, secret_name: str = None):"""清除缓存:param secret_name: 指定清除某个secret的缓存,None表示清除全部"""if secret_name:self.get_secret.cache_clear(secret_name)else:self.get_secret.cache_clear()current_app.logger.debug(f"Cleared cache for secret: {secret_name or 'all'}")# 创建全局客户端实例(单例模式)
client = SecretsManagerClient()
使用方式,类似如下代码:
from parameter_store import ssmClient
ssmClient.clear_cache("/local_flask/db/secret_name") # 清除缓存
secret_name = ssmClient.get_parameter("/local_flask/db/secret_name")
数据库场景测试
在Flask Web应用程序中,获取数据库连接类,类似内容如下:
# -*- coding: utf-8 -*-import sys
sys.path.append('./')
import pymysql
from secrets_manager import client
from parameter_store import ssmClientfrom tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type
from flask import current_app# 数据库连接
@retry(stop=stop_after_attempt(3),wait=wait_exponential(multiplier=1, min=4, max=10),retry=(retry_if_exception_type(pymysql.OperationalError) |retry_if_exception_type(pymysql.InternalError)))
def get_conn_sqldb():conn = Nonesecret_name_title = "/{}_flask/db/secret_name".format(current_app.config['PROFILE'])secret_name = ssmClient.get_parameter(secret_name_title)db_host_title = "/{}_flask/db/host".format(current_app.config['PROFILE'])try:secret = client.get_secret(secret_name)host = ssmClient.get_parameter(db_host_title)port = secret['port'] # 端口号user = secret['username'] # 用户名passwd = secret['password']db = 'xxx_database' # 库名current_app.logger.debug(f"Connecting to {host}:{port}")conn = pymysql.connect(host=host, port=port, user=user,passwd=passwd, db=db, charset='utf8mb4', client_flag=pymysql.constants.CLIENT.MULTI_STATEMENTS)return connexcept pymysql.OperationalError as e:if conn:conn.close()if e.args[0] == 1045: # Access deniedcurrent_app.logger.warning("Authentication failed, refreshing secret...")client.clear_cache(secret_name) # 清除缓存ssmClient.clear_cache(secret_name_title) # 清除缓存ssmClient.clear_cache(db_host_title) # 清除缓存raiseraiseexcept Exception as e:if conn:conn.close()current_app.logger.error(f"Unexpected error: {str(e)}")raise
这里使用了tenacity库的@retry
注解,进行数据库连接失败时重试策略;还使用了current_app.config['PROFILE']
方式来获取Flask环境变量配置;还针对AWS RDS响应1045
编码做了清除缓存处理。这里主要是先从parameters store中获取secret名称后,再拿个这个值,去secrets manager换RDS轮换密钥数据库密码,数据库端口,数据库用户名。
总结
现在这个点(2025年),Flask在Python里面的地位。貌似没有Spring生态在java中Web地位那么强势和全面。AWS这两个服务可以统一都通过boto3 SDK访问,比以前强多了,以前parameters store和secrets manager这个两个服务,客户端得安装两个SDK才能读取数据,有点费劲,这一点比以前强多了。这里直接使用Python自带的@lru_cache
注解感觉挺香。重试库Tenacity也挺香的。
参考
- Configuring from Environment Variables
- AWS Systems Manager Parameter Store
- get_parameter
- How to Use SSM Parameter Store with boto3
- Logging
- How to Get Started with Logging in Flask
- Tenacity
- 使用 Python AWS SDK 获取 Secrets Manager 密钥值
- 在不重启容器的情况下轮换数据库凭证
相关文章:

Python Flask中启用AWS Secrets Manager+AWS Parameter Store配置中心
问题 最近需要改造一个Python的Flask项目。需要在这个项目中添加AWS Secrets Manager作为配置中心,主要是数据库相关配置。 前提 得预先在Amazon RDS里面新建好数据库用户和数据库,以AWS Aurora为例子,建库和建用户语句类似如下࿱…...

机器学习与深度学习10-支持向量机02
目录 前文回顾6.如何构建SVM7.SVM与多分类问题8.SVM与逻辑回归9.SVM的可扩展性10.SVM的适用性和局限性 前文回顾 上一篇文章链接:地址 6.如何构建SVM 选择合适的核函数和超参数来构建支持向量机(SVM)模型通常需要一定的经验和实验。以下是…...
《深入解析UART协议及其硬件实现》-- 第二篇:UART硬件架构设计与FPGA实现
第二篇:UART硬件架构设计与FPGA实现 1. 模块化架构设计 1.1 系统级框图与时钟域划分 核心模块划分 : 发送模块(TX) :负责数据帧组装与串行输出。 接收模块(RX) :负责串行数据采样与…...
java swing 晃动鼠标改变背景颜色
import java.awt.Color; import java.awt.Component; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionListener;import javax.swing.*; public class testA extends JFrame {testA(){super("晃动鼠标改变背景颜色");setBounds(600, 200, 600, …...

HikariCP 可观测性最佳实践
HikariCP 介绍 HikariCP 是一个高性能、轻量级的 JDBC 连接池,由 Brett Wooldridge 开发。它以“光”命名,象征快速高效。它支持多种数据库,配置简单,通过字节码优化和智能管理,实现低延迟和高并发处理。它还具备自动…...

简简单单探讨下starter
前言 今天其实首先想跟大家探讨下:微服务架构,分业务线了,接入第三方服务、包啥的是否自己定义一个stater更好? 一、starter是什么? 在 Spring Boot 中,Starter 是一种特殊的依赖模块,用于快速…...

PyTest框架学习
0. 优先查看学习教程 超棒的学习教程 1. yield 语句 yield ptc_udp_clientyield:在 Pytest fixture 中,yield 用于分隔设置和清理代码。yield 之前的代码在测试用例执行前运行,yield 之后的代码在测试用例执行后运行。ptc_udp_client&…...

SIP、SAP、SDP、mDNS、SSH、PTP
🌈 一、SIP 会话初始协议 会话初始协议 SIP 是一个在 IP 网络上进行多媒体通信的应用层控制协议,它被用来创建、修改和终结 1 / n 个参加者参加的会话进程。SIP 不能单独完成呼叫功能,需要和 RTP、SDP 和 DNS 配合来完成。 1. SIP 协议的功…...

【AI学习笔记】Coze工作流写入飞书多维表格(即:多维表格飞书官方插件使用教程)
背景前摇: 今天遇到一个需求,需要把Coze平台大模型和用户的对话记录保存进飞书表格,这个思路其实不难,因为官方提供了写入飞书表格和多维表格的插件,但是因为平台教程和案例的资料匮乏,依据现有的官方文档…...
System.Threading.Timer 和 System.Timers.Timer
在 .NET 中,System.Threading.Timer 和 System.Timers.Timer 都是用于定时任务的类,但它们的实现方式、使用场景和特性有所不同。以下是它们的 核心区别 和 使用示例: 1. System.Threading.Timer 特点 轻量级,基于线程池…...

在 Windows 系统下配置 VSCode + CMake + Ninja 进行 C++ 或 Qt 开发
在 Windows 系统下配置 VSCode CMake Ninja 进行 C 或 Qt 开发,是一个轻量级但功能强大的开发环境。下面我将分步骤详细说明如何搭建这个开发环境,支持纯 C 和 Qt 项目。 🧰 所需工具安装 1. 安装 Visual Studio Code(VSCode&…...
`tokenizer.decode` 出现乱码或异常输出,怎么处理
tokenizer.decode 出现乱码或异常输出,怎么处理 在使用 Hugging Face Transformers 库进行大语言模型(LLM)开发时,tokenizer.decode 出现乱码或异常输出,通常和模型输出的 token 序列、分词器对齐逻辑、特殊 token 处理有关。以下从模型侧、分词器侧、后处理环节给出解决…...
几何绘图与三角函数计算应用
几何绘图与三角函数计算应用 设计思路 左侧为绘图控制面板,右侧为绘图区域支持绘制点、线、矩形、圆、多边形等基本几何图形实现三角函数计算器(正弦、余弦、正切等)包含角度/弧度切换和常用数学常数历史记录功能保存用户绘图 完整实现代码…...

leetcode 二叉搜索树中第k小的元素 java
中序遍历 定义一个栈,用于存取二叉树中的元素 Deque<TreeNode> stack new ArrayDeque<TreeNode>();进入while循环while(! stack.isEmpty()|| root ! null){}将root的左节点入栈,直到rootnull while(rootnull){stack.push(root);root ro…...

5.1 初探大数据流式处理
在本节中,我们深入探讨了大数据流式处理的基础知识和关键技术。首先,我们区分了批式处理和流式处理两种大数据处理方式,了解了它们各自的适用场景和特点。流式处理以其低延迟和高实时性适用于需要快速响应的场景,而批式处理则适用…...
基于 Android 和 JBox2D 的简单小游戏
以下是一个基于 Android 和 JBox2D 的简单小游戏开发示例,实现一个小球在屏幕上弹跳的效果: 1. 添加 JBox2D 依赖 在项目的 build.gradle 文件中添加 JBox2D 的依赖: dependencies {implementation org.jbox2d:jbox2d-library:2.3.1 } 2.…...

传输层协议 UDP 介绍 -- UDP 协议格式,UDP 的特点,UDP 的缓冲区
目录 1. 再识的端口号 1.1 端口号范围划分 1.2 知名端口号(Well-Know Port Number) 2. UDP 协议 2.1 UDP 协议格式 2.2 UDP 的特点 2.3 UDP 的缓冲区 2.4 一些基于 UDP 的应用层协议 传输层(Transport Layer)是计算机网络…...
Python try-except-else 语句详解
try-except-else 是 Python 中用于异常处理的重要结构,它允许你优雅地处理可能出现的错误,并在没有错误发生时执行特定代码。下面我将详细解释这个结构及其用法。 基本语法 try:# 可能引发异常的代码块 except [ExceptionType]:# 异常处理代码块 else:…...

ApacheSuperset CVE-2023-27524
前言:CVE-2023-27524 是一种远程代码执行漏洞,攻击者通过该漏洞可在受影响系统上执行任意代码,从而获得未授权访问权 CVE-2023-27524 GitHubhttps://github.com/horizon3ai/CVE-2023-27524 任务一 代理 | 拉取镜像 vi /etc/proxychains4.conf //最下面修…...
Windows Server部署Vue3+Spring Boot项目
在Windows Server 上部署Vue3 Spring Boot前后端分离项目的详细步骤如下: 一、环境准备 安装JDK 17 下载JDK MSI安装包(如Oracle JDK 或 OpenJDK) 双击安装,配置环境变量: JAVA_HOME:JDK安装路径…...
malloc 是如何分配内存的?——C 语言内存分配详解
文章目录 malloc是如何分配内存的?——C语言内存分配详解一、引言二、内存分配的基本概念1. 虚拟内存与物理内存2. 进程内存布局 三、malloc函数详解1. 函数原型与功能2. 关键特性 四、malloc的底层实现机制1. 内存分配器的角色2. 分配策略3. 内存碎片问题 五、glib…...
Opencl
**OpenCL(Open Computing Language)**是一种用于异构平台(包括CPU、GPU、FPGA、DSP等)上的并行计算框架和编程标准。它由Khronos Group制定,旨在提供一种跨平台、统一的编程接口,使开发者可以利用不同硬件设…...

如何在 HTML 中添加按钮
原文:如何在 HTML 中添加按钮 | w3cschool笔记 (请勿将文章标记为付费!!!!) 在网页开发中,按钮是用户界面中不可或缺的元素之一。无论是用于提交表单、触发动作还是导航࿰…...
【优秀三方库研读】quill 开源库中的命名空间为什么要用宏封装
将命名空间封装成宏的作用与优势 QUILL_BEGIN_NAMESPACE 和 QUILL_END_NAMESPACE 这种宏封装是 C++ 库开发中的常见技巧,主要解决以下问题并提供显著优势: 1. 解决核心问题:命名空间嵌套与版本控制 问题场景: 库需要支持多版本共存(如 quill::v1, quill::v2),但希望默认…...
AlphaFold3运行错误及解决方法(1)
1. chemical_component_sets.pickle 运行alphafold3遇到下面的问题: FileNotFoundError: [Errno 2] No such file or directory: /xxx/xxx/anaconda3/envs/alphafold3/lib/python3.11/site-packages/alphafold3/constants/converters/chemical_component_sets.pickle搜索你的系…...

Linux--进程的程序替换
问题导入: 前面我们知道了,fork之后,子进程会继承父进程的代码和“数据”(写实拷贝)。 那么如果我们需要子进程完全去完成一个自己的程序怎么办呢? 进程的程序替换来完成这个功能! 1.替换原理…...

调教 DeepSeek - 输出精致的 HTML MARKDOWN
【序言】 不知道是不是我闲的蛋疼,对百度AI 和 DeepSeek 的回答都不太满意。 DeepSeek 回答句子的引用链接,始终无法准确定位。有时链接只是一个域名,有时它给的链接是搜索串如: baidu.com/?q"搜索内容"。 百度AI 回答句子的引用…...

【笔记】Windows系统部署suna基于 MSYS2的Poetry 虚拟环境backedn后端包编译失败处理
基于 MSYS2(MINGW64)中 Python 的 Poetry 虚拟环境包编译失败处理笔记 一、背景 在基于 MSYS2(MINGW64)中 Python 创建的 Poetry 虚拟环境里,安装 Suna 开源项目相关包时编译失败,阻碍项目正常部署。 后端…...
GQA(Grouped Query Attention):分组注意力机制的原理与实践《一》
GQA(Grouped Query Attention)是近年来在大语言模型中广泛应用的一种注意力机制优化方法,最初由 Google 在 2023 年提出。它是对 Multi-Query Attention (MQA) 的扩展,旨在平衡模型性能与计算效率。 🌟 GQA 是什么&…...

【深度学习优化算法】02:凸性
【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈PyTorch深度学习 ⌋ ⌋ ⌋ 深度学习 (DL, Deep Learning) 特指基于深层神经网络模型和方法的机器学习。它是在统计机器学习、人工神经网络等算法模型基础上,结合当代大数据和大算力的发展而发展出来的。深度学习最重…...