Как получить AccountId как переменную в файле serverless.yml?

Я хочу создать ARN в моем файле динамически, но мне нужно получить текущий текущий аккаунт. Как я могу получить к нему доступ в виде переменной?

Например:

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

Ответ 1

Там есть удобный серверный плагин https://www.npmjs.com/package/serverless-pseudo-parameters, который добавляет возможность ссылаться на параметры aws, такие как регион и идентификатор учетной записи, которые я только что начал используя для большого успеха.

Ответ 2

Сам по себе сервер не может ссылаться на эти переменные, поскольку они определены в 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"

Ответ 3

AWS CloudFormation предлагает некоторые переменные, такие как AWS::AccountId и AWS::Region, но вы не можете использовать их в serverless.yml, например ${AWS::AccountId}. Они не поддерживаются.

@jens answer является правильным. Вы должны использовать синтаксис 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" ]]'

совпадает с жестким кодированием области и идентификатора учетной записи:

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

Ответ 4

В отличие от ответа @Zanon, вы не должны использовать * в качестве AWS::accountId. хотя в этом случае это будет работать, это уязвимость безопасности, поскольку это будет означать ЛЮБУЮ учетную запись (доступную ролью IAM).

Ответ 5

Поскольку уже ответил, серверная версия в настоящее время не предлагает способ получить идентификатор учетной записи. Вы должны использовать синтаксис CloudFormation для этого.

Однако, если вы определяете политику доступа IAM, вам не нужен идентификатор учетной записи AWS. Просто разместите *, где вы поместите номер учетной записи. Идентификатор учетной записи необходим в следующих случаях:

  • Когда вы создаете 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} для ссылки на регион, который я установил в моем провайдере (us-east-1).