首页 > 解决方案 > 无服务应用程序部署失败 - 启用细粒度访问控制或将限制性访问策略应用于您的域

问题描述

我有一个无服务器应用程序,我想在其中部署一个弹性搜索集群。我已经这样配置它:

PostsSearch:
      Type: AWS::Elasticsearch::Domain
      Properties:
        ElasticsearchVersion: '6.3'
        DomainName: images-search-${self:provider.stage}
        ElasticsearchClusterConfig:
          DedicatedMasterEnabled: false
          InstanceCount: 1
          ZoneAwarenessEnabled: false
          InstanceType: t2.small.elasticsearch
        EBSOptions:
          EBSEnabled: true
          Iops: 0
          VolumeSize: 10
          VolumeType: 'gp2'
        AccessPolicies:
          Version: '2012-10-17'
          Statement:
            - Effect: Allow
              Principal:
                AWS: '*'
              Action: 'es:ESHttp*'
              Resource: '*'

但是,我收到一个错误:

发生错误:PostsSearch - 启用细粒度访问控制或对您的域应用限制性访问策略(服务:AWSElasticsearch;状态代码:400;错误代码:ValidationException;请求 ID:be0eca95-23ae-4ac9-be81-67cab37ccd70;代理: 空值)。

我应该如何解决这个问题?

标签: amazon-web-serviceselasticsearchserverless-framework

解决方案


基于评论中的额外讨论。

使 ES 域完全公开是不可能的。CloudFormation 不允许这样做。因此,有三个选项可供选择。下面我将在一个示例无服务器应用程序中介绍其中的三个。这只是基本的 hello-world 应用程序,它不以任何身份使用 ES 域,但我使用它来验证每个选择是否有效,并且可以使用无服务器框架进行部署而不会出错。

应用基于 IP 的条件

这将使您的域开放,只能访问单个 IP 地址或 IP CIDR 范围。下面的示例将访问限制为一个单一的 IP 地址。

service: estest

provider:
  name: aws
  runtime: python3.8

  stage: ${opt:stage, 'dev'}
  region: ${opt:region, 'us-east-1'}  

functions:
  hello:
    handler: handler.hello

resources:
  Resources:
    PostsSearch:
      Type: AWS::Elasticsearch::Domain
      Properties:
        ElasticsearchVersion: '6.3'
        DomainName: images-search-${self:provider.stage}
        ElasticsearchClusterConfig:
          DedicatedMasterEnabled: false
          InstanceCount: 1
          ZoneAwarenessEnabled: false
          InstanceType: t2.small.elasticsearch
        EBSOptions:
          EBSEnabled: true
          Iops: 0
          VolumeSize: 10
          VolumeType: 'gp2'
        AccessPolicies:
          Version: '2012-10-17'
          Statement:
            - Effect: Allow
              Principal:
                AWS: '*'
              Action: 'es:ESHttp*'
              Resource: !Sub "arn:aws:es:${self:provider.region}:${AWS::AccountId}:domain/images-search-${self:provider.stage}/*"
              Condition:
                IpAddress:
                   aws:SourceIp: ["12.13.14.15"] 

限制本金

您可以将对您的 ES 域的访问限制为选定的 IAM 用户或角色。这样,只有给定的 IAM 用户/角色才能访问 ES 域。在下面我使用 lambda 现有的 IAM 角色作为原则。该功能及其角色必须已经存在。

service: estest

provider:
  name: aws
  runtime: python3.8

  stage: ${opt:stage, 'dev'}
  region: ${opt:region, 'us-east-1'}  

functions:
  hello:
    handler: handler.hello

resources:
  Resources:
    PostsSearch:
      Type: AWS::Elasticsearch::Domain
      Properties:
        ElasticsearchVersion: '6.3'
        DomainName: images-search-${self:provider.stage}
        ElasticsearchClusterConfig:
          DedicatedMasterEnabled: false
          InstanceCount: 1
          ZoneAwarenessEnabled: false
          InstanceType: t2.small.elasticsearch
        EBSOptions:
          EBSEnabled: true
          Iops: 0
          VolumeSize: 10
          VolumeType: 'gp2'
        AccessPolicies:
          Version: '2012-10-17'
          Statement:
            - Effect: Allow
              Action: 'es:ESHttp*'            
              Principal:
                AWS: !Sub "arn:aws:iam::${AWS::AccountId}:role/service-role/lambda-function-es-role-b44mvudf"
              Resource: !Sub "arn:aws:es:${self:provider.region}:${AWS::AccountId}:domain/images-search-${self:provider.stage}/*"


使用细粒度的访问控制

此处的示例使用需要用户名和密码的细粒度控件创建可公开访问的 ES 域。在 free-tier 中不起作用。我还硬编码了用户名和密码,这显然需要修改并作为来自SSM Parameter store实际应用程序的参数提供。

service: estest

provider:
  name: aws
  runtime: python3.8

  stage: ${opt:stage, 'dev'}
  region: ${opt:region, 'us-east-1'}  

functions:
  hello:
    handler: handler.hello

resources:
  Resources:
    PostsSearch:    
      Type: AWS::Elasticsearch::Domain
      Properties: 
        DomainName: images-search-${self:provider.stage}        
        AccessPolicies: !Sub |
          {
            "Version": "2012-10-17",
            "Statement": [
              {
                "Effect": "Allow",
                "Principal": {
                  "AWS": "*"
                },
                "Action": "es:*",
                "Resource": "*"
              }
            ]
          }
        AdvancedSecurityOptions:
            Enabled: true
            InternalUserDatabaseEnabled: true
            MasterUserOptions: 
              MasterUserName: admin
              MasterUserPassword: fD343sfdf!3rf
        EncryptionAtRestOptions: 
          Enabled: true
        NodeToNodeEncryptionOptions:
          Enabled: true
        DomainEndpointOptions:
          EnforceHTTPS: true
        EBSOptions: 
          EBSEnabled: true
          VolumeSize: 20
          VolumeType: gp2
        ElasticsearchClusterConfig: 
          DedicatedMasterEnabled: false
          InstanceCount: 1
          InstanceType: c4.large.elasticsearch
          ZoneAwarenessEnabled: false
        ElasticsearchVersion: 7.7

推荐阅读