WEBKT

Serverless应用数据库凭证安全管理:自动轮换与细粒度控制实战

129 0 0 0

在Serverless架构中,数据库凭证的管理是一个重要的安全课题。传统的凭证管理方式在Serverless环境下面临诸多挑战,例如函数的短暂生命周期、分布式部署以及对精细化权限控制的需求。本文将探讨如何利用云原生服务(如AWS Secrets Manager和Azure Key Vault)在不同的Serverless应用环境(开发、测试、生产)下有效管理数据库凭证,并实现凭证的自动轮换和细粒度的访问控制,从而避免凭证泄露风险。同时,提供实际的配置案例供参考。

1. Serverless环境下的凭证管理挑战

  • 函数生命周期短: Serverless函数通常是无状态的,每次调用都可能在一个新的执行环境中进行。这意味着不能简单地将凭证存储在本地文件或环境变量中,因为这会导致凭证在每次函数调用时都需要重新加载,影响性能,并且增加了泄露风险。
  • 分布式部署: Serverless应用通常由多个函数组成,这些函数可能部署在不同的区域或可用区。需要一个集中式的凭证管理方案,以便在所有函数中共享和管理凭证。
  • 精细化权限控制: 不同的函数可能需要访问不同的数据库或具有不同的权限。需要一个能够实现细粒度访问控制的凭证管理方案,以确保每个函数只能访问其所需的资源。
  • 凭证轮换: 为了提高安全性,需要定期轮换数据库凭证。手动轮换凭证容易出错且耗时,需要一个自动化的凭证轮换方案。

2. 云原生凭证管理服务:AWS Secrets Manager和Azure Key Vault

AWS Secrets Manager和Azure Key Vault是云厂商提供的托管式凭证管理服务,可以安全地存储、轮换和管理数据库凭证、API密钥和其他敏感信息。它们提供了以下关键功能:

  • 加密存储: 使用强大的加密算法对凭证进行加密存储,确保凭证的安全性。
  • 访问控制: 提供细粒度的访问控制策略,可以控制哪些用户、角色或服务可以访问特定的凭证。
  • 自动轮换: 可以自动轮换数据库凭证,无需手动干预,从而降低凭证泄露的风险。
  • 审计日志: 记录所有对凭证的访问和修改操作,方便审计和追踪安全事件。

3. Serverless应用凭证管理最佳实践

以下是在Serverless应用中使用AWS Secrets Manager或Azure Key Vault管理数据库凭证的最佳实践:

  • 集中式凭证存储: 将所有数据库凭证存储在AWS Secrets Manager或Azure Key Vault中,避免将凭证硬编码在代码或配置文件中。
  • 使用IAM角色进行授权: 为每个Serverless函数分配一个IAM角色,并授予该角色访问AWS Secrets Manager或Azure Key Vault中特定凭证的权限。
  • 最小权限原则: 仅授予Serverless函数访问其所需的凭证的权限,避免授予过多的权限。
  • 自动凭证轮换: 启用AWS Secrets Manager或Azure Key Vault的自动凭证轮换功能,定期轮换数据库凭证。
  • 缓存凭证: 为了提高性能,可以在Serverless函数中缓存从AWS Secrets Manager或Azure Key Vault获取的凭证。但需要注意缓存的有效期,并定期刷新缓存。
  • 监控和审计: 监控对AWS Secrets Manager或Azure Key Vault的访问和修改操作,及时发现异常行为。

4. 配置案例:AWS Secrets Manager + Lambda + RDS

以下是一个使用AWS Secrets Manager管理Lambda函数访问RDS数据库凭证的配置案例:

4.1 创建RDS数据库

  • 在AWS RDS中创建一个MySQL数据库实例。

4.2 创建Secrets Manager secret

  • 在AWS Secrets Manager中创建一个新的secret,用于存储数据库的用户名和密码。
  • 选择“凭证类型”为“RDS数据库凭证”。
  • 输入数据库的用户名、密码、主机名和端口号。
  • 配置自动轮换策略,例如每30天轮换一次密码。

4.3 创建Lambda函数

  • 创建一个新的Lambda函数,用于查询RDS数据库。
  • 在Lambda函数的配置中,创建一个新的IAM角色,并授予该角色以下权限:
    • secretsmanager:GetSecretValue:允许Lambda函数从AWS Secrets Manager中获取secret的值。
    • rds:DescribeDBInstances:允许Lambda函数描述RDS数据库实例。

4.4 配置Lambda函数代码

import boto3
import json
import pymysql
import os

secrets_manager = boto3.client('secretsmanager')

def lambda_handler(event, context):
    secret_name = os.environ['SECRET_NAME'] # 从环境变量中获取secret名称
    
    try:
        # 获取secret的值
        response = secrets_manager.get_secret_value(SecretId=secret_name)
        secret_string = response['SecretString']
        secret = json.loads(secret_string)

        # 从secret中获取数据库连接信息
        db_host = secret['host']
        db_port = secret['port']
        db_user = secret['username']
        db_password = secret['password']
        db_name = 'your_database_name'

        # 连接数据库
        conn = pymysql.connect(host=db_host, port=db_port, user=db_user, password=db_password, db=db_name)
        cursor = conn.cursor()

        # 执行查询
        cursor.execute('SELECT * FROM your_table')
        results = cursor.fetchall()

        # 返回结果
        return {
            'statusCode': 200,
            'body': json.dumps(results)
        }

    except Exception as e:
        print(e)
        return {
            'statusCode': 500,
            'body': json.dumps('Error: {}'.format(str(e)))
        }

4.5 配置环境变量

  • 在Lambda函数的配置中,添加一个环境变量SECRET_NAME,其值为AWS Secrets Manager中secret的名称。

4.6 测试Lambda函数

  • 测试Lambda函数,确保其可以成功连接到RDS数据库并执行查询。

5. 配置案例:Azure Key Vault + Azure Functions + Azure SQL Database

以下是一个使用Azure Key Vault管理Azure Functions访问Azure SQL Database凭证的配置案例:

5.1 创建Azure SQL Database

  • 在Azure中创建一个SQL Database实例。

5.2 创建Key Vault secret

  • 在Azure Key Vault中创建一个新的secret,用于存储数据库的连接字符串。

5.3 创建Azure Function

  • 创建一个新的Azure Function,用于查询SQL Database。
  • 在Azure Function的配置中,启用“系统分配的托管标识”。

5.4 授予Azure Function访问Key Vault的权限

  • 在Azure Key Vault的访问策略中,添加一个新的访问策略,授予Azure Function的托管标识“获取”secret的权限。

5.5 配置Azure Function代码

import azure.functions as func
import azure.identity
import azure.keyvault.secrets
import pyodbc
import os
import json

app = func.FunctionApp(http_auth_level=func.AuthLevel.ANONYMOUS)

@app.route(route="http_trigger")
def http_trigger(req: func.HttpRequest) -> func.HttpResponse:
    key_vault_url = os.environ["KEY_VAULT_URL"]
    secret_name = os.environ["SECRET_NAME"]

    try:
        # 使用托管标识认证
        credential = azure.identity.DefaultAzureCredential()
        client = azure.keyvault.secrets.SecretClient(vault_url=key_vault_url, credential=credential)

        # 获取secret的值
        retrieved_secret = client.get_secret(secret_name)
        connection_string = retrieved_secret.value

        # 连接数据库
        cnxn = pyodbc.connect(connection_string)
        cursor = cnxn.cursor()

        # 执行查询
        cursor.execute("SELECT * FROM your_table")
        results = [dict(zip([column[0] for column in cursor.description], row)) for row in cursor.fetchall()]

        # 返回结果
        return func.HttpResponse(
            json.dumps(results),
            mimetype="application/json",
            status_code=200
        )

    except Exception as e:
        return func.HttpResponse(
             f"Error: {str(e)}",
             status_code=500
        )

5.6 配置应用程序设置

  • 在Azure Function的应用程序设置中,添加以下配置:
    • KEY_VAULT_URL:Azure Key Vault的URL。
    • SECRET_NAME:Azure Key Vault中secret的名称。

5.7 测试Azure Function

  • 测试Azure Function,确保其可以成功连接到SQL Database并执行查询。

6. 总结

通过使用AWS Secrets Manager或Azure Key Vault等云原生凭证管理服务,可以有效地解决Serverless应用中数据库凭证的安全管理问题。通过集中式凭证存储、细粒度的访问控制和自动凭证轮换,可以大大降低凭证泄露的风险,并提高Serverless应用的安全性。希望本文提供的最佳实践和配置案例能够帮助您更好地管理Serverless应用的数据库凭证。

云原生架构师 Serverless凭证管理安全

评论点评