NextGen Healthcare, Inc.
是基于云的创新医疗保健技术解决方案的领先提供商,其使命是改善执业者及其患者的生活。我们的 NextGen 人口健康解决方案通过汇总和转换多源数据,直接为护理团队提供切实可行的见解。
NextGen Population Heal
th 是一款云原生产品,在其生命
周期中 一直与 亚马逊云科技 共同发展。随着 亚马逊云科技 发布新的安全相关服务和对现有服务的增强功能,我们一直在努力将其整合到我们的平台中。这种做法使我们的安全态势得到持续、渐进的改善,使我们的客户、他们的护理团队乃至他们所服务的患者受益。
安全是 亚马逊云科技 架构完善的框架的关键支柱,也是
亚马逊云科技
与客户
共同责任
的一部分。亚马逊云科技 在保护数据库时提供了多种选项,但客户有责任为您的特定工作负载确定和实施理想的配置。
在这篇文章中,我们概述了保护
兼容 Amazon Aurora PostgreSQL 的版本
集群的步骤,这些集群包含敏感的、符合 HIPAA 标准的工作负载,这些工作负载需要高度安全。您也可以使用此模式来保护
兼容 Amazon Aurora MySQL
的版本集群。
HIPAA 安全规则
要求受保实体保持合理和适当的管理、技术和物理保护措施,以保护电子保护健康信息 (ePhi)。我们确保 ePhi 机密性的方法之一是通过内部安全控制,要求对静态和传输中的所有数据进行加密。警告:详尽的安全步骤列表视您的工作负载和业务要求而定。
我们还将提供有关如何通过整合预防、侦探和响应控制来监控和维护安全领域最佳实践的方法。
先决条件
这篇文章假设具备以下工作知识:
-
亚马逊云科技 CloudFormation
- 使用 Python 编程以及
Boto3 库与 亚马逊云科技
进行交互
- 极光 PostgreSQL 和 Aurora
- CI/CD 概念
Aurora PostgreSQL 版本 15.3、14.8、13.11、12.15、11.20 中 已经发布
了对支持 ZDP 的 TLS 1.3 的支持。
另外,如果将 OpenJDK 与 TLS 1.3 一起使用,请参阅此 修复程序。
预防性控制
静态加密
静态加密旨在通过使用加密来保护物理和/或虚拟存储设备上的数据。这有助于减少未经授权的访问或盗窃,从而保护 ePhi。Aurora 支持静态加密并使用行业标准 AES-256 加密。要启用数据库集群的加密,请在 CloudFormation 模板 中将 storage
Crypted 参数声明为 真
。以下显示了用于配置此参数的示例 CloudFormation 模板:
Cluster:
Type: AWS::RDS::DBCluster
Properties:
BackupRetentionPeriod: 35
CopyTagsToSnapshot: true
DBClusterParameterGroupName: SampleDBClusterParameterGroupName
DBSubnetGroupName: SampleSubnetGroupName
DeletionProtection: true
EnableCloudwatchLogsExports:
- postgresql
Engine: aurora-postgresql
Port: 5432
EngineMode: provisioned
EngineVersion: 15.3
EnableIAMDatabaseAuthentication: true
KmsKeyId: SampleKmsKeyId
StorageEncrypted: true
VpcSecurityGroupIds:
- sg-00000000000000000
确保安全组仅向需要打开的应用程序和客户端开放。不要将其向世界或信任圈之外的 IP 地址和网络开放。
对数据库集群进行加密后,所有数据库实例、日志、备份和快照也会被加密。为确保只能使用加密方式创建数据库,您可以添加拒绝未经加密创建的 IAM 策略:
DatabaseRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: cloudformation.amazonaws.com
Version: 2012-10-17
Path: /codepipeline/
RoleName: cloudformation-database-role
Policies:
- PolicyName: DatabasePolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Sid: DenyUnencryptedRDS
Effect: Deny
Action: rds:CreateDBInstance
Resource: *
Condition:
Bool:
rds:StorageEncrypted: false
传输中加密旨在通过使用加密保护在设备和网络之间传输的数据。 在这方面,您可以使用
多种控件
来实现网络安全。Aurora PostgreSQL 和 Aurora MySQL 允许通过参数组精细配置安全设置。在下一节中,我们将仔细研究这些控件。我们将说明如何使用它们来确保数据在设备和网络之间传输时保持安全。
强制 TLS
使用 TLS(传输层安全)可确保对系统之间传输的数据进行加密。 要强制客户端连接仅通过 TLS 进行连接,请在 dbClusterParameterGroup 资源类型的 Cloud Formation 模板中将 rds.force_ssl
参数设置为 1。
SSL(安全套接字层)是 TLS 的前身,这两个术语经常互换使用,这就是使用 rds.force_ssl 参数名称
的原因。
这可以使用以下 CloudFormation 代码进行配置:
RDSDBClusterParameterGroup:
Type: AWS::RDS::DBClusterParameterGroup
Properties:
Description: !Sub Aurora PG Cluster Parameter Group for Cloudformation Stack - ${DBName}
Family: !FindInMap [DBFamilyMap, !Ref DBEngineVersion, "family"]
Parameters:
rds.force_ssl: 1
ssl_min_protocol_version: "TLSv1.3"
ssl_ciphers: "TLS_AES_256_GCM_SHA384"
在启用此设置之前,您应该使用
CloudWatch Log Insigh
ts 检查 Aurora 集群日志, 并确定是否建立了任何纯文本连接。如果有,则需要更新应用程序以仅建立加密连接,并合并测试来验证这一点。我们将在本文后面讨论一个示例测试。
以下屏幕截图是针对 /aws/ rds/cluster/database-1/postgresql 日志组的 CloudWatch Log Insights 查询示例,该 日志组用于确定我们的数据库
接受的连接类型。
以下屏幕截图显示了建立未加密连接的查询的输出:
以下屏幕截图显示了建立加密连接的查询的输出:
TLS 版本 1.3
强制加密连接后,我们可以强化各种 TLS 设置。
适用于 PostgreSQL 和 Aurora PostgreSQL 的亚马逊关系数据库服务(亚马逊 RDS)
支持 TLS 版本 1.1、1.2 和 1.3。但是,由于漏洞和其他技术原因,TLS 1.1 已过时。
因为我们想要最强大的保护,所以我们希望使用亚马逊 RDS 支持的最高版本,即 Aurora Po
stgreSQL 的 TLS 1.3 和 Aurora MySQL
的 TLS 1.3。
为此,请在 dbClusterParameterGroup 资源类型的 CloudFormation 模板 中
将另一个名为 ssl_min_protocol_version
的集群参数设置为 tlsv1.3。
限制密码套件
通过使用集群参数组中的 ssl_ciphers 参数,我们可以仅允许使用所需的密码
套件进行连接。我们再次使用 CloudWatch Logs Insights 来确定我们的客户过去使用了哪些密码套件。由于我们删除了低于 1.3 版本的 TLS 连接,因此我们也可以删除绑定到旧 TLS 版本的关联传统密码套件。
支持各种数据库版本的密码套件的完整列表可以在适用于 P
ostgreSQL
和 MySQL 的 Amazon Aurora 用户指南中找到。
以下屏幕截图是用于确定密码套件信息的 CloudWatch Log Insights 查询示例。
fields @timestamp, @message
| sort @timestamp desc
| limit 20
| filter @message like 'cipher='
以下显示了查询的输出。
然后,我们可以使用这些信息来确定我们的应用程序正在使用哪些密码套件,从而为可以安全删除的密码套件提供指导。记录的密码可以编译成允许的密码列表,进一步提高系统的安全性。
ciphersuite.info 是 查找有关密码套件安全性信息的有用资源。
它包含密码套件的评级、对最安全的套件的推荐以及每个套件的技术细节。
证书颁发机构
证书颁发机构 (CA) 在互联网上的通信实体之间建立信任链,并在颁发数字证书方面起着至关重要的作用。最近,Amazon RDS 增加了对 可在预置或修改数据库实例时配置
的新证书颁发机构的
支持。这使我们能够通过选择最安全的私钥和签名算法来进一步加强我们的安全态势。 在 AWS:: RD S:: dbinStan
ce CloudFormation 资源中,将 caCer tificateIdentificate 属性的值设置为 rds-ca-2019、rds-ca-rsa 20
48-g1、rds-ca-rsa4096-g1 或 rds-ca-ecc384-g1。
每个 CA 的描述都可以在
亚马逊 Aurora 用户指南
中找到 。与 RSA 证书相比,ECC 证书是一种较新的方法,它提供了同等级别的加密强度,同时具有密钥长度较短的优点,可以提供速度和安全性。
侦探控制
侦探控制可提供有关工作负载的见解,并提醒我们注意需要人工参与的问题。
Amazon CloudWatch
指标、日志和警报提供了配置这些警报所需的工具,
而 亚马逊简单通知服务
(Amazon SNS) 会在触发警报时提供通知。以下示例侦探控制由以下 亚马逊云科技 服务组成:
- 用于发送警报通知的 SNS 主题
- 用于捕获数据库连接遥测数据的 CloudWatch 日志组
- CloudWatch 指标过滤器,用于定义要根据日志组进行搜索的模式
- 基于指标筛选器的 CloudWatch 警报,用于向 SNS 主题发出警报
通过这种模式,我们可以为之前涵盖的任何或所有预防性控制措施创建警报。要创建针对未加密连接的警报,我们首先构建一个 SNS 主题来接收警报通知:
AlertTopic:
Type: AWS::SNS::Topic
Properties:
Subscription:
- Endpoint: user@example.com
Protocol: email
接下来,我们需要一个日志组来捕获日志,以及一个指标过滤器来捕获日志组中的相关日志消息。在这种情况下,我们不需要创建日志组。我们可以利用创建数据库集群时已经为我们创建的日志组,并在指标筛选器中对其进行引用。要创建指标过滤器,请使用以下 CloudFormation 代码:
PlaintextMetricFilter:
Type: AWS::Logs::MetricFilter
Properties:
FilterPattern: "connection authorized" -"SSL enabled"
LogGroupName: /aws/rds/cluster/example-cluster/postgresql
MetricTransformations:
- MetricName: plaintext_connection
MetricNamespace: rds/postgres
MetricValue: "1"
请注意,我们将 LoggroupName
值与 Amazon RDS 在创建集群时创建的那个日志组一起引用。
接下来,我们将创建警报资源,该资源引用我们创建的指标以及 SNS 主题:
PlaintextConnectionAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmDescription: Plaintext (unencrypted) connection detected
AlarmActions:
- !Ref AlertTopic
MetricName: plaintext_connection
Namespace: rds/postgres
Period: 60 # seconds
EvaluationPeriods: 1
Statistic: Sum
TreatMissingData: notBreaching
Threshold: 1
ComparisonOperator: GreaterThanOrEqualToThreshold
简而言之,此警报旨在每当检测到一个或多个未加密的连接 时 提醒 AlertTopic
的订阅者。
要正确调整警报,需要配置多个属性。 AlarmActi
ons 属性引用了我们之前创建的 SNS 主题,该主题在警报转换为 “警报” 状态时运行。
时间段
设置 为 60
(秒), 评估周期
设置 为 1。
在 1 分钟内,我们生成一个数据点,为了确定警报状态,我们会评估最近的一个时段。 统计数据
属性设置为 Sum
,这为我们提供了警报指标的总和。 由于我们的指标仅在出现未加密的连接时才会生成数据点,因此我们将 treat MissingData 参数设置为 not
Breaching。
最后, 阈值
设置 为 1
,将 C omparisonOperator
设置为 greaterThanorequaltoThreshold ,将其与 统计数据
进行比较,如果它大于或等于该值
,则警报过渡到警报状态。
此配置可在建立未加密连接时提供检测、警报和通知。您可以通过添加更多资源并修改指标筛选模式以匹配新模式,在其他警报中重复这种模式。
亚马逊 GuardDuty RDS Protection 是另一种侦探控件,可以将威胁检测扩展到亚马逊 Aurora。截至撰写本文时,GuardDuty 功能处于预览版中。NextGen Healthcare已与GuardDuty产品团队合作,对服务进行了调整和完善。Amazon GuardDuty RDS 保护使用机器学习来分析和分析登录活动以了解潜在的访问威胁,从而
识别潜在 的可疑
登录活动。 只需几个步骤即可在主机中启用此服务,这些步骤可在
Amazon GuardD
uty用户指南中找到。
响应式控件
为限制弱密码套件而采取的预防性控制措施也可以受益于确定是否发布新的、更安全的密码套件的控制措施。可以对新的密码套件进行评估,以调整我们支持的密码套件列表。 获得及时反馈的一种方法是在构建时添加检查,将默认 ssl_ciphers 参数中的密码套件列表与密码套件列表进行比较。
以下 bash 脚本作为 CI/CD 管道的一部分运行。该脚本调用 d escribeEnginedefaultClusterPar
ameters API 并将结果与之前调用的输出进行比较。如果结果发生了变化,则管道将失败,这使您有机会更新支持的密码配置。
#!/bin/bash
# Check for updated Postgres TLS Ciphers supported, fail build if found
EXPECTED_POSTGRES_TLS_CIPHER_LIST="DHE-RSA-AES128-SHA, DHE-RSA-AES128-SHA256, DHE-RSA-AES128-GCM-SHA256, DHE-RSA-AES256-SHA, DHE-RSA-AES256-SHA256, DHE-RSA-AES256-GCM-SHA384, ECDHE-RSA-AES128-SHA, ECDHE-RSA-AES128-SHA256, ECDHE-RSA-AES128-GCM-SHA256, ECDHE-RSA-AES256-SHA, ECDHE-RSA-AES256-SHA384, ECDHE-RSA-AES256-GCM-SHA384, TLS_RSA_WITH_AES_256_GCM_SHA384, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384"
SUPPORTED_TLS_CIPHERS=`aws rds describe-engine-default-cluster-parameters --db-parameter-group-family aurora-postgresql15 --query "EngineDefaults.Parameters[? ParameterName == 'ssl_ciphers'].AllowedValues" --output text`
if [[ $SUPPORTED_TLS_CIPHERS != $EXPECTED_POSTGRES_TLS_CIPHER_LIST ]]; then
echo "Supported Postgres TLS Ciphers list changed. Update allowlist accordingly in Postgres parameter group - ssl_ciphers."
echo $SUPPORTED_TLS_CIPHERS
exit 1
fi
另一种控制措施是进行测试,以验证无法建立纯文本连接。这证实了在传输过程中强制加密的预防性控制措施正常运行。在禁用加密的情况下尝试连接,但预计会失败。如果连接成功,则测试失败,进而使 CI/CD 管道失败,并防止更改影响下游(生产)环境。
以下 Python 脚本与 PyTest 测试框架结合使用:
import json
import boto3
import psycopg2
aws_session = boto3.Session()
secretsmanager = aws_session.client("secretsmanager")
database_secret: str = "postgres/example-database"
def test_connection_encryption_enforced():
secret: dict[str, str] = json.loads(secretsmanager.get_secret_value(SecretId=database_secret _id))
# Attempt unencrypted connection, if no exception is raised, the test fails.
with pytest.raises(psycopg2.OperationalError) as excinfo:
psycopg2.connect(
dbname=database,
user=username,
password=password,
port=port,
host=host,
sslmode="disable",
)
assert "Is the server running on that host and accepting TCP/IP connections?" in str(
excinfo.value
), "Unencrypted connection was allowed, check rds.force_ssl parameter value is 1"
清理
要清理在您的账户中创建的资源,您应该删除创建的所有 CloudFormation 堆栈。
你可以使用
亚马逊云科技 CloudFormation
控制台或
亚马逊云科技 API
来执行清理。
结论
这篇文章中概述的预防、侦探和响应式控制提供了全面的安全态势,组织可以从中受益,从而确保工作负载满足其业务政策和监管要求。安全是一项持续的工作;组织必须对新出现的威胁保持警惕,并制定相应的流程来主动防范这些威胁。
有关更多信息和进一步阅读,请参阅
亚马逊 Aurora 安全文档
。
作者简介
布兰登·怀特 是 NextGen Healthcare 的 DevOps 高级工程师。他在医疗保健信息技术行业拥有超过 17 年的经验,对无服务器事件驱动架构和自动化感兴趣。在业余时间,他喜欢骑自行车和做柴烧披萨。
摩根·基利克 是NextGen Healthcare的参谋工程师,专注于提高开发人员和系统的运营效率。当不自动化所有事情时,他喜欢跑步。
斯蒂芬·麦克唐纳 是 NextGen Healthcare 的开发运营人员工程师。他住在纽约州罗切斯特。Stephen 对提高应用程序安全性和构建事件驱动型应用程序感到兴奋。他在医疗保健、制造业和商业服务行业拥有 15 年的基础设施工程经验。在业余时间,他喜欢户外烹饪、旅行和现场音乐。
Anand 自 2016 年起担任 亚马逊云科技 的首席解决方案架构师。Anand 已帮助全球医疗保健、金融服务和电信客户使用 亚马逊云科技 和混合云技术架构和实施企业软件解决方案。他拥有路易斯安那州立大学巴吞鲁日分校的计算机科学硕士学位和洛杉矶南加州大学马歇尔商学院的工商管理硕士学位。他在安全、解决方案架构和 DevOps 工程领域获得了 亚马逊云科技 认证。
Bryan 自 2022 年起担任 亚马逊云科技 的首席解决方案架构师。布莱恩是一位首席解决方案架构师,负责Nextgen的成功。他拥有丰富的背景,曾领导美国十大银行的数据中心、迁移、IT 运营、网络安全和创新。他拥有亚利桑那州立大学的管理信息系统硕士学位,并获得了 CISSP 认证和 亚马逊云科技 解决方案架构认证。