

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 用于 Amazon SNS 访问控制的示例案例
<a name="sns-access-policy-use-cases"></a>

本节描述了针对访问控制的几个典型使用案例示例。

## 授予对主题的 AWS 账户 访问权限
<a name="sns-grant-aws-account-access-to-topic"></a>

假设您在 Amazon SNS 中有一个主题，并且您想允许一个或多个 AWS 账户 主题对该主题执行特定操作，例如发布消息。使用 Amazon SNS API 操作 `AddPermission` 即可做到这一点。

该`AddPermission`操作允许您指定主题、列表 AWS 账户 IDs、操作列表和标签。然后，Amazon SNS 会自动生成新的策略声明，并将其添加到该主题的访问控制策略中。您无需自己编写策略声明，Amazon SNS 将为您处理。如果您以后需要移除该策略，则可以通过调用 `RemovePermission` 并提供您在添加权限时使用的标签来实现。

例如，如果您调用 `AddPermission` arn: aws: sns: us-east-2:444455556666:，指定 MyTopic ID 1111-2222-3333 AWS 账户 、操作`Publish`和标签，Amazon `grant-1234-publish` SNS 将生成以下策略声明并将其插入到该主题的访问控制策略中：

```
{
  "Statement": [{
    "Sid": "grant-1234-publish",
    "Effect": "Allow",
    "Principal": {
      "AWS": "111122223333"
    },
    "Action": ["sns:Publish"],
    "Resource": "arn:aws:sns:us-east-2:444455556666:MyTopic"
  }]
}
```

添加此声明后， AWS 账户 1111-2222-3333 将有权向该主题发布消息。

**其他信息：**
+ **自定义策略管理：**虽然 `AddPermission` 可以方便地授予权限，但对于更复杂的场景，例如添加条件或向特定 IAM 角色或服务授予权限，手动管理主题的访问控制策略通常很有用。为此，您可以使用 `SetTopicAttributes` API 直接更新策略属性。
+ **安全最佳实践：**在授予权限时要谨慎行事，确保只有受信任的实体 AWS 账户 或实体才能访问您的 Amazon SNS 主题。定期审查和审核您的主题所附的策略，以维护安全性。
+ **策略限制：**请记住，Amazon SNS 策略的规模和复杂性有限制。如果您需要添加许多权限或复杂条件，请确保您的策略保持在这些限制范围内。

## 限制 HTTPS 订阅
<a name="sns-limit-subscriptions-to-https"></a>

要将您的 Amazon SNS 主题的通知传送协议限制为 HTTPS，您必须创建自定义策略。Amazon SNS 中的 `AddPermission` 操作不允许您在授予主题访问权限时指定协议限制。因此，您需要手动编写强制执行此限制的策略，然后使用 `SetTopicAttributes` 操作将该策略应用于您的主题。

您可以通过以下方式创建限制订阅 HTTPS 的策略：

1. **撰写策略。**该策略必须指定您要授予访问权限的 AWS 账户 ID，并强制执行仅允许 HTTPS 订阅的条件。以下是一个策略示例，该策略授予 AWS 账户 ID 1111-2222-3333 订阅该主题的权限，但前提是使用的协议是 HTTPS。

   ```
   {
     "Statement": [{
       "Sid": "Statement1",
       "Effect": "Allow",
       "Principal": {
         "AWS": "111122223333"
       },
       "Action": ["sns:Subscribe"],
       "Resource": "arn:aws:sns:us-east-2:444455556666:MyTopic",
       "Condition": {
         "StringEquals": {
           "sns:Protocol": "https"
         }
       }
     }]
   }
   ```

1. **应用策略**。使用 Amazon SNS API 中的 `SetTopicAttributes` 操作将此策略应用于您的主题。将主题的 `Policy` 属性设置为您创建的 JSON 策略。

   ```
   snsClient.setTopicAttributes(SetTopicAttributesRequest.builder()
           .topicArn("arn:aws:sns:us-east-2:444455556666:MyTopic")
           .attributeName("Policy")
           .attributeValue(jsonPolicyString)  // The JSON policy as a string
           .build());
   ```

**其他信息：**
+ **自定义访问控制。**这种方法允许您实施更精细的访问控制，例如限制订阅协议，而光靠 `AddPermission` 操作是无法实现的。自定义策略为需要特定条件（例如协议强制执行或 IP 地址限制）的场景提供了灵活性。
+ **安全最佳实践。**将订阅限制为 HTTPS 可确保传输中的数据经过加密，从而增强通知的安全性。定期查看您的主题策略，确保它们符合您的安全和合规性要求。
+ **策略测试。**在生产环境中应用策略之前，请在开发环境中对其进行测试，以确保其行为符合预期。这有助于防止意外访问问题或意外限制。

## 发布消息到 Amazon SQS 队列
<a name="sns-publish-messages-to-sqs-queue"></a>

要将来自您的 Amazon SNS 主题的消息发布到 Amazon SQS 队列，您需要在 Amazon SQS 队列上配置正确的权限。虽然 Amazon SNS 和 Amazon SQS 都 AWS使用访问控制策略语言，但您必须在 Amazon SQS 队列上明确设置策略，以允许从亚马逊 SNS 主题发送消息。

您可以使用 `SetQueueAttributes` 操作将自定义策略应用于 Amazon SQS 队列，从而实现此目的。与 Amazon SNS 不同，Amazon SQS 不支持创建带有条件的策略声明的 `AddPermission` 操作。因此，您必须手动编写策略。

以下是 Amazon SQS 策略的示例，该策略授予对 Amazon SNS 向队列发送消息的权限。请注意，此策略与 Amazon SQS 队列有关，与 Amazon SNS 主题无关。这些指定操作都是 Amazon SQS 操作，并且资源是队列的 Amazon 资源名称（ARN）。您可以使用 `GetQueueAttributes` 操作检索队列的 ARN。

```
{
  "Statement": [{
    "Sid": "Allow-SNS-SendMessage",
    "Effect": "Allow",
    "Principal": {
      "Service": "sns.amazonaws.com"
    },
    "Action": ["sqs:SendMessage"],
    "Resource": "arn:aws:sqs:us-east-2:444455556666:MyQueue",
    "Condition": {
      "ArnEquals": {
        "aws:SourceArn": "arn:aws:sns:us-east-2:444455556666:MyTopic"
      }
    }
  }]
}
```

这种策略，根据所发送信息的来源，利用 `aws:SourceArn` 条件限制对 SQS 队列的访问。这样可以确保只允许将来自指定 SNS 主题（在本例中为 arn: aws: sns: us-east-2:444455556666:）的消息传送到队列。MyTopic

**其他信息：**
+ 队列 ARN。确保您使用 `GetQueueAttributes` 操作检索 Amazon SQS 队列的正确 ARN。此 ARN 对于设置正确的权限至关重要。
+ **安全最佳实践。**设置策略时，请始终遵循最低权限原则。仅向 Amazon SNS 主题授予与 Amazon SQS 队列进行交互的必要权限，并定期查看您的政策，确保其有效且安全 up-to-date
+ **Amazon SNS 中的默认策略。**Amazon SNS 不会自动授予允许其他 AWS 服务 或账户访问新创建主题的默认策略。默认情况下，Amazon SNS 主题是在没有权限的情况下创建的，这意味着它们是私有的，只有创建它们的账户才能访问。要为其他 AWS 服务、账户或委托人启用访问权限，您必须明确定义访问策略并将其附加到该主题。这符合最低权限原则，确保默认情况下不会授予任何意外访问权限。
+ **测试和验证。**设置策略后，通过将消息发布到 Amazon SNS 主题并验证消息是否已成功传送到 Amazon SQS 队列来测试集成。这有助于确认策略配置是否正确。

## 允许 Amazon S3 事件通知发布到主题
<a name="sns-allow-s3-bucket-to-publish-to-topic"></a>

要允许另一个 Amazon S3 存储桶 AWS 账户 向您的 Amazon SNS 主题发布事件通知，您需要相应地配置该主题的访问策略。这包括编写自定义策略，向特定 AWS 账户 的 Amazon S3 服务授予权限，然后将此策略应用于您的 Amazon SNS 主题。

您可以通过以下方式进行设置：

1. **撰写策略。**该策略应授予 Amazon S3 服务（s3.amazonaws.com）发布到 Amazon SNS 主题所需的权限。您将使用`SourceAccount`条件来确保只有拥有 Amazon S3 存储桶的指定 AWS 账户人员才能向您的主题发布通知。

   下面是一个策略示例：

   ```
   {
     "Statement": [{
       "Effect": "Allow",
        "Principal": { 
         "Service": "s3.amazonaws.com" 
       },
       "Action": "sns:Publish",
       "Resource": "arn:aws:sns:us-east-2:111122223333:MyTopic",
       "Condition": {
         "StringEquals": {
           "AWS:SourceAccount": "444455556666"
         }       
       }
     }]
   }
   ```
   + **话题所有者** — 111122223333 是 AWS 账户 拥有亚马逊 SNS 话题的 ID。
   + **亚马逊 S3 存储桶所有者** — 444455556666 是 AWS 账户 拥有发送通知的亚马逊 S3 存储桶的 ID。

1. **应用策略**。使用 `SetTopicAttributes` 操作在您的 Amazon SNS 主题上设置此策略。这将更新主题的访问控制，使其包含您的自定义策略中指定的权限。

   ```
   snsClient.setTopicAttributes(SetTopicAttributesRequest.builder()
           .topicArn("arn:aws:sns:us-east-2:111122223333:MyTopic")
           .attributeName("Policy")
           .attributeValue(jsonPolicyString)  // The JSON policy as a string
           .build());
   ```

**其他信息：**
+ **使用 `SourceAccount` 条件。**该`SourceAccount`条件可确保只有源自指定 AWS 账户 （在本例中为 444455556666）的事件才能触发 Amazon SNS 主题。这是一项安全措施，可防止未经授权的账户向您的主题发送通知。
+ **其他服务支持 `SourceAccount`。**以下服务支持 `SourceAccount` 条件。当您想要根据原始账户限制访问您的 Amazon SNS 主题时，使用此条件至关重要。
  + Amazon API Gateway
  + Amazon CloudWatch
  + Amazon DevOps Guru
  + Amazon EventBridge
  + 亚马逊 GameLift 服务器
  + Amazon Pinpoint SMS 和 Voice API
  + Amazon RDS
  + Amazon Redshift
  + Amazon Glacier
  + Amazon SES
  + Amazon Simple Storage Service
  + AWS CodeCommit
  + Directory Service
  + AWS Lambda
  + AWS Systems Manager Incident Manager
+ **测试和验证。**应用策略后，通过在 Amazon S3 存储桶中触发事件并确认该事件已成功发布到您的 Amazon SNS 主题来测试设置。这将有助于确保您的策略配置正确。
+ **安全最佳实践。**定期审查和审核您的 Amazon SNS 主题策略，确保它们符合您的安全要求。仅限可信账户和服务访问对于维护安全运营至关重要。

## 允许 Amazon SES 向其他账户拥有的主题发布
<a name="sns-allow-specified-service-to-publish-to-topic"></a>

您可以 AWS 服务 允许其他人发布他人拥有的主题 AWS 账户。假设您登录了 111122223333 账户，打开了 Amazon SES 并创建了一封电子邮件。要将有关此电子邮件的通知发布到 444455556666 账户拥有的 Amazon SNS 主题，您需要创建一个如下所示的策略。为此，您需要提供有关委托人（其他服务）和每个资源的所有权的信息。`Resource` 语句提供主题 ARN，其中包括主题所有者的账户 ID 444455556666。`"aws:SourceOwner": "111122223333"` 语句指定您的账户拥有该电子邮件。

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Id": "__default_policy_ID",
  "Statement": [
    {
      "Sid": "__default_statement_ID",
      "Effect": "Allow",
      "Principal": {
        "Service": "ses.amazonaws.com"
      },
      "Action": "sns:Publish",
      "Resource": "arn:aws:sns:us-east-2:444455556666:MyTopic",
      "Condition": {
        "StringEquals": {
          "aws:SourceOwner": "111122223333"
        }
      }
    }
  ]
}
```

------

向 Amazon SNS 发布事件时，以下服务支持 `aws:SourceOwner`：
+ Amazon API Gateway
+ Amazon CloudWatch
+ Amazon DevOps Guru
+ 亚马逊 GameLift 服务器
+ Amazon Pinpoint SMS 和 Voice API
+ Amazon RDS
+ Amazon Redshift
+ Amazon SES
+ AWS CodeCommit
+ Directory Service
+ AWS Lambda
+ AWS Systems Manager Incident Manager

## `aws:SourceAccount` 与 `aws:SourceOwner`
<a name="source-account-versus-source-owner"></a>

**重要**  
`aws:SourceOwner` 已弃用，新服务只能通过 `aws:SourceArn` 和 `aws:SourceAccount` 与 Amazon SNS 集成。对于目前支持 `aws:SourceOwner` 的现有服务，Amazon SNS 仍保持向后兼容性。

`aws:SourceAccount` 和 `aws:SourceOwner` 条件键由一些 AWS 服务 在它们发布到 Amazon SNS 主题时设置。如果支持，则该值将是服务代表其发布数据的 12 位 AWS 账户 ID。一些服务支持其中一项，一些服务支持另一项。
+ [允许 Amazon S3 事件通知发布到主题](#sns-allow-s3-bucket-to-publish-to-topic)请参阅，了解 Amazon S3 通知的使用方式`aws:SourceAccount`以及支持该条件的 AWS 服务列表。
+ [允许 Amazon SES 向其他账户拥有的主题发布](#sns-allow-specified-service-to-publish-to-topic)有关 Amazon SES 的使用方式`aws:SourceOwner`以及支持该条件的 AWS 服务列表，请参阅。

## 允许组织中的账户 AWS Organizations 向其他账户中的主题发布内容
<a name="sns-allow-organization-to-publish-to-topic-in-another-account"></a>

该 AWS Organizations 服务可帮助您集中管理账单，控制访问权限和安全性，并在整个系统中共享资源 AWS 账户。

您可以在 [Organizations 控制台](https://console.aws.amazon.com/organizations/)中找到您的组织 ID。有关更多信息，请参阅[从管理账户查看组织的详细信息](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_org_details.html#orgs_view_org)。

在此示例中，任何组织成员都`myOrgId`可以在账户 AWS 账户 中向 Amazon SNS 主题发布内容`MyTopic`。`444455556666`该策略使用 `aws:PrincipalOrgID` 全局条件键检查组织 ID 值。

```
{
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": "sns:Publish",
            "Resource": "arn:aws:sns:us-east-2:444455556666:MyTopic",
            "Condition": {
                "StringEquals": {
                    "aws:PrincipalOrgID": "myOrgId"
                }
            }
        }
    ]
}
```

## 允许将任何 CloudWatch 警报发布到其他账户中的主题
<a name="sns-allow-cloudwatch-alarm-to-publish-to-topic-in-another-account"></a>

使用以下步骤调用带有不同 CloudWatch 警报的 Amazon SNS 主题。 AWS 账户此示例使用两个账户：
+ **账户 A** 用于创建 CloudWatch 警报。
+ **账户 B** 用于创建 SNS 主题。

**在账户 B 中创建 SNS 主题**

1. 登录 [Amazon SNS 控制台](https://console.aws.amazon.com/sns/home)。

1. 在导航窗格中，选择**主题**，然后选择**创建主题**。

1. 为主题类型选择**标准**，然后为该主题创建名称。

1. 选择**创建主题**，然后复制该主题的 **ARN**。

1. 在导航窗格中，选择**订阅**，然后选择**创建订阅**。

1. 在**主题 ARN** 部分添加主题的 ARN，选择**电子邮件**作为协议，然后**输入电子邮件地址**。

1. 选择**创建订阅**，然后检查您的电子邮件来**确认订阅**。

**在账户 A 中创建 CloudWatch 警报**

1. 打开 CloudWatch 控制台，网址为[https://console.aws.amazon.com/cloudwatch/](https://console.aws.amazon.com/cloudwatch/)。

1. 在导航窗格中，选择**警报**，然后选择**创建警报**。

1. 如果您尚未创建警报，请立即创建一个。否则，请选择您的**指标**，然后提供阈值和比较参数的详细信息。

1. 在**配置操作**的**通知**下，选择**使用主题 ARN 通知其他账户**，然后输入账户 B 中的**主题 ARN**。

1. 为警报创建名称，然后选择**创建警报**。

**更新账户 B 中 SNS 主题的访问策略**

1. 登录 [Amazon SNS 控制台](https://console.aws.amazon.com/sns/home)。

1. 在左侧导航窗格中，选择**主题**，然后选择该主题。

1. 选择**编辑**，然后将以下内容添加到策略中：

**注意**  
请将以下策略中的示例值替换为您的实际值。

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Id": "__default_policy_ID",
    "Statement": [
        {
            "Sid": "__default_statement_ID",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": [
                "SNS:GetTopicAttributes",
                "SNS:SetTopicAttributes",
                "SNS:AddPermission",
                "SNS:RemovePermission",
                "SNS:DeleteTopic",
                "SNS:Subscribe",
                "SNS:ListSubscriptionsByTopic",
                "SNS:Publish"
            ],
            "Resource": "arn:aws:cloudwatch:us-west-1:111122223333:alarm:",
            "Condition": {
                "ArnLike": {
                    "aws:SourceArn": "arn:aws:cloudwatch:us-west-1:111122223333:alarm:"
                }
            }
        }
    ]
}
```

------

**测试警报**

要测试警报，您可以根据指标数据点更改警报阈值，也可以手动更改警报状态。当您更改警报阈值或警报状态时，您会收到一封电子邮件通知。

**使用本地 Amazon SNS 主题并转发消息的解决方法**

使用以下步骤为警报启用跨账户 Amazon SNS 通知 CloudWatch：

1. 使用与**CloudWatch警报**相同的账户 (111122223333) 创建[**亚马逊 SNS 主题**](sns-create-topic.md)。

1. 为该亚马逊 SNS 主题订阅 [**Lambda 函数**](lambda-console.md)或[亚马逊 EventBridge规则](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-s3-object-created-tutorial.html)。

1. 然后，Lambda 函数或 EventBridge 规则可以将消息发布到目标账户 (444455556666) 中的 Amazon SNS 主题。

## 仅限从特定 VPC 终端节点发布到 Amazon SNS 主题
<a name="sns-restrict-publication-only-from-specified-vpc-endpoint"></a>

在这种情况下，账户 444455556666 中的主题只允许从具有 ID `vpce-1ab2c34d` 的 VPC 终端节点发布。

```
{
  "Statement": [{
    "Effect": "Deny",
    "Principal": "*",
    "Action": "sns:Publish",
    "Resource": "arn:aws:sns:us-east-2:444455556666:MyTopic",
    "Condition": {
      "StringNotEquals": {
        "aws:sourceVpce": "vpce-1ab2c34d"
      }
    }
  }]
}
```