问题 如何将AccountId作为serverless.yml文件中的变量?


我想动态地在我的文件中构建一个ARN,但我需要获取当前的AccountId。如何将其作为变量访问?

例如:

example: arn:aws:states:${region}:${accountId}:stateMachine:${self:service}-${self:custom.stage}-example

引用当前的正确方法是什么 region 和 accountId

编辑:(解决方案)

由于这种解决方案的丑陋和冗长,我对这个解决方案并不满意 Fn::Join 解决方案,但我最终做的是制作一个 arns.yml 只有这一个地方有所有这些的文件然后通过其他地方的变量引用。

# arns.yml
example:
  Fn::Join:
    - ":"
    - - arn
      - aws
      - states
      - Ref: AWS::Region
      - Ref: AWS::AccountId
      - stateMachine
      - ${self:service}-${self:custom.stage}-example

然后:

# serverless.yml
custom:
  stage: "${opt:stage, self:provider.stage}"


functions:
  foo:
    handler: handler.foo
    environment:
      example_arn: ${file(arns.yml):example}

编辑2 :(更好的解决方案)

这可能听起来很蹩脚,但我最终选择的解决方案是将其硬编码到我的自定义变量中。我实际上有两个帐户,我使用自定义生成步骤复制具有帐户特定设置的两个文件,如下所示:

account.stag.yml
account.prod.yml

每个文件可能如下所示:

# account.stag.yml
account: 123456789
region: ${opt:region, "us-east-1"}
domain: mycompany.qa

当我构建时,我指定一个帐户,并使用gulp来完成我的所有建筑:

gulp build --account stag

然后,我将我的帐户特定设置重命名为

build/account.yml

我可以在我的serverless.yml中引用它,如下所示:

# build/serverless.yml
custom: ${file(account.yml)}
functions:
  foo:
    handler: handler.foo
    environment:
      example_arn: arn:aws:states:${self:custom.region}:${self:custom.account}:${self:service}-${opt:stage}-example

12737
2018-03-05 18:49


起源



答案:


有一个方便的无服务器插件 https://www.npmjs.com/package/serverless-pseudo-parameters 这增加了引用aws参数的能力,例如我刚开始使用的区域和帐户ID,取得了很大的成功。


6
2018-06-15 06:47



我还没有审查这个插件,但这似乎是最诚实的答案,转而成为正确的答案。 - justin.m.chase


答案:


有一个方便的无服务器插件 https://www.npmjs.com/package/serverless-pseudo-parameters 这增加了引用aws参数的能力,例如我刚开始使用的区域和帐户ID,取得了很大的成功。


6
2018-06-15 06:47



我还没有审查这个插件,但这似乎是最诚实的答案,转而成为正确的答案。 - justin.m.chase


无服务器本身无法引用这些变量,因为它们是在CloudFormation中定义的,但不会在无服务器中公开。

如果您需要资源部分中的那些,您可以通过“Ref”-call直接访问它们。

AWS CloudFormation伪变量

如果需要将这些变量用作函数环境变量,则可以使用CloudFormation代码覆盖无服务器生成的函数代码。

因此,要实现此目的,您必须通过以下模式修改serverless.yml。

functions:
  hello:
    handler: handler.hello
resources:
  Resources:
   HelloLambdaFunction:
     Type: AWS::Lambda::Function
     Properties:
       Environment:
         Variables:
           accountId:
             Ref: AWS::AccountId
           region:
             Ref: AWS::Region
           arn:
             Fn::Join:
               - ""
               - - "arn:aws:states:"
                 - Ref: AWS::Region
                 - ":"
                 - Ref: AWS::AccountId
                 - ":stateMachine:"
                 - ${self:service}
                 - "-"
                 - ${self:custom.stage}
                 - "-example"

5
2018-03-05 22:01





AWS CloudFormation提供 一些变数 喜欢 AWS::AccountIdAWS::Region,但你不能在使用它们 serverless.yml 文件就像 ${AWS::AccountId}。那些不受支持。

@jens回答 是对的。您必须使用CloudFormation语法。在下面的示例中,我提供了另一种使用CloudFormation的方法。

service: testing-aws-account-id

provider:
  name: aws
  runtime: nodejs4.3
  region: us-east-1
  iamRoleStatements:
    - Effect: "Allow"
      Action:
        - "iot:Publish"
      Resource: 'Fn::Join: ["", [ "aws:iot:", { "Ref": "AWS::Region" }, ":", { Ref: "AWS::AccountId" }, ":topic/foo" ]]'

functions:
  publishIot:
    handler: handler.publishIot

这条线:

 Resource: 'Fn::Join: ["", [ "aws:iot:", { "Ref": "AWS::Region" }, ":", { Ref: "AWS::AccountId" }, ":topic/foo" ]]'

与区域和帐户ID的硬编码相同:

Resource: "arn:aws:iot:us-east-1:1234567890:topic/foo"    

2
2018-03-05 22:21



是否可以替换该行 Resource: '!Sub arn:aws:iot:${AWS::Region}:${AWS::AccountId}:topic/foo' ? - BamaPookie
@BamaPookie,我不这么认为。它应该只在你添加时工作 这个插件。 - Zanon
我明白了 Partition "" is not valid for resource "arn::Join: ["", [ "arn: - SteveCoffman


已经回答了,无服务器框架目前不提供检索帐户ID的方法。您必须使用CloudFormation语法。

但是,如果您要定义IAM访问策略,则为您 不需要 AWS账户ID。只是放置 * 你在哪里放帐号。在以下情况下,帐户ID是必需的:

  • 在构建ARN以标识特定资源(例如,通过其ARN调用函数)时,不要授予访问权限。
  • 在与其他AWS账户建立信任关系时。

请看以下内容 serverless.yml 文件:

service: testing-aws-account-id

provider:
  name: aws
  runtime: nodejs4.3
  region: us-east-1
  iamRoleStatements:
    - Effect: "Allow"
      Action:
        - "iot:Publish"
      Resource: "arn:aws:iot:${self:provider.region}:*:topic/foo"

functions:
  publishIot:
    handler: handler.publishIot

有用。我在用着 *而不是我的帐号,我正在使用 ${self:provider.region} 引用我设置的区域 提供商 (美国东部-1)。


2
2018-03-05 22:48