CDK DnsValidatedCertificate: можно ли создать сертификат в связанной учетной записи AWS, если размещенная зона является частью родительской учетной записи?

Я пытаюсь использовать AWS Cloud Development Kit для создания сертификата SSL для некоторых поддоменов моего веб-сайта. Проблема в том, что я использую AWS Organizations, а соответствующие ресурсы принадлежат разным учетным записям AWS. размещенная зона для моего домена является частью нашей основной учетной записи. , но я использую CDK для развертывания стека в связанной учетной записи. Это означает, что DnsValidatedCertificate класс может запросить новый сертификат (они все еще видны в ACM после отката стека), но выдает ошибку при попытке создать запись DNS для автоматической проверки запроса.

Вот ошибка (номер моей учетной записи и имя стека отредактированы):

 5/6 | 22:44:14 | CREATE_FAILED        | AWS::CloudFormation::CustomResource | SubSubDomainsCertificate/CertificateRequestorResource/Default (SubSubDomainsCertificateCertificateRequestorResourceBC626C85) Failed to create resource. User: arn:aws:sts::123456789012:assumed-role/MyStack-SubSubDomainsCertificateCertificat-16QRI74P8POO2/MyStack-SubSubDomainsCertificateCertificat-BXZ55WHIH1XC is not authorized to access this resource
        new CustomResource (C:\repos\my-project\node_modules\@aws-cdk\aws-cloudformation\lib\custom-resource.ts:92:21)
        \_ new DnsValidatedCertificate (C:\repos\my-project\node_modules\@aws-cdk\aws-certificatemanager\lib\dns-validated-certificate.ts:81:29)
        \_ new MyStack (C:\repos\my-project\.elasticbeanstalk\api-stack.js:91:25)

И вот соответствующий фрагмент кода CDK (опять же, с удаленными HZ и доменом):

    // Executed with `cdk deploy --profile profileForLinkedAwsAccount`
    const hostedZone = route53.HostedZone.fromHostedZoneAttributes(
      this,
      'MyDomainHostedZone',
      {
        hostedZoneId: 'Z2ABC1234RYN', // in master AWS account
        zoneName: 'mydomain.com.'
      }
    );
    const certificate = new certificatemanager.DnsValidatedCertificate(
      this,
      'SubSubDomainsCertificate',
      {
        domainName: `*.demo.mydomain.com`,
        hostedZone,
        region: 'us-east-1',
        validationMethod: certificatemanager.ValidationMethod.DNS // ???
      }
    );

Итак, есть ли способ настроить CDK, который позволит автоматически выполнять проверку DNS? Или мне нужно сделать это в качестве второго шага, используя другой профиль?

РЕДАКТИРОВАТЬ: по предложению Майкла я добавил роль с именем LinkedAccountCertValidatorRole в главную учетную запись AWS. Управляемая политика, которую я привязал к роли, и ее доверительные отношения показаны ниже. К сожалению, я все еще получаю ту же ошибку. Кроме того, вкладка Access Advisor указывает на то, что политика никогда не использовалась этой ролью.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "route53:ChangeResourceRecordSets",
            "Resource": "arn:aws:route53:::hostedzone/Z2ABC1234RYN"
        }
    ]
}
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::123456789012:root"
      },
      "Action": "sts:AssumeRole",
      "Condition": {}
    }
  ]
}

person carpiediem    schedule 25.09.2019    source источник


Ответы (3)


Для полноты картины я опубликую здесь простой ответ: используйте Certificate вместо DnsValidatedCertificate. Я могу сделать так, чтобы CDK создал запрос на сертификат, но не пытался автоматически проверять субдомен. Это означает, что я должен:

  1. Найдите запрос в Amazon Certificate Manager связанной учетной записи,
  2. Проверьте (или экспортируйте) запись CNAME, которую она просит добавить, и
  3. Переключитесь на главную учетную запись AWS и добавьте запись в Route53.
// Executed with `cdk deploy --profile profileForLinkedAwsAccount`
const certificate = new certificatemanager.Certificate(this, 'SubSubDomainsCertificate', {
  domainName: `*.${SUBDOMAIN}.mydomain.com`,
  validationMethod: ValidationMethod.DNS
});

Я пока остановился на этом варианте, но было бы неплохо полностью автоматизировать процесс.

person carpiediem    schedule 26.09.2019
comment
Я нашел CDK в отношении диспетчера сертификатов очень расплывчатым. Я предположил, что DnsValidatedCertificate действительно попытается получить сертификат, который я создал вручную, потому что у меня также были проблемы с проверкой DNS при автоматической проверке. Однако, когда я использую DnsValidatedCertificate, он все равно будет создавать новый сертификат вместо того, чтобы использовать тот, который уже доступен. Проверка DNS работает, потому что я уже проверял сертификат раньше, но теперь у меня есть дубликаты ... Сейчас я попробую ваш подход. - person Mattijs; 31.10.2020
comment
Смотрите мой ответ ниже; Я считаю, что теперь, когда API был обновлен, это решает проблему так, как вам хотелось бы, и полностью с автоматизацией. - person Andrew Philips; 14.06.2021

Работа с IAM может быть сложной задачей. Прежде всего, созданная вами роль должна иметь доверительные отношения с пользователем / учетными записями / группами, которые могут принять эту роль. Я не вижу, чтобы вы упомянули об этом в своем ОП. Я не знаю, что такое CDK, поэтому не могу получить четкое представление о том, что вы делаете.

Роль имеет разрешения на действия, которые могут быть выполнены. Также существует часть доверительных отношений, которая определяет, кто или что может взять на себя эту роль.

Доверенные отношения должны иметь сопоставление с главной учетной записью организации, например ....

Создайте роль в основной учетной записи с прикрепленными разрешениями:

My_Role_To_Assume
Assign Permissions in Master:

Trust Relationship(Master Account)
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::0123456789012:root"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

Создайте группу в основной учетной записи и назначьте пользователей в эту группу. Разрешения группы должны иметь документ политики, показывающий, какие роли и номера дополнительных учетных записей разрешено принимать пользователю.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "sts:AssumeRole"
      ],
      "Resource": [
        "arn:aws:iam::987654321098:role/My_Role_To_Assume",
        "arn:aws:iam::567890123456:role/My_Other_Role_Assume"
      ]
    }
  ]
}

Затем в учетной записи вы хотите, чтобы роль имела доступ. Создайте роль с таким же именем (не обязательно, но гораздо легче запомнить, какие роли предназначены для последующих ролей).

My_Role_To_Assume
Assign Permissions for role in sub-account:

Attach Trust Realtionship policy for sub-account role to trust master account:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::0123456789012:root"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

Вы можете настроить наборы разрешений в каждой учетной записи, чтобы обеспечить более детальный контроль / доступ к ресурсам. Обычно в основной учетной записи у вас может не быть никаких разрешений, за исключением пароля IAM, управления ключами и т. Д.

Этот подход работает хорошо, и общая суть заключается в том, что вы создаете доверительные отношения на корневом уровне, но групповая политика в основной учетной записи определяет, какие роли могут быть приняты на себя этим пользователем / группой в рамках дополнительных учетных записей.

Поскольку вы используете интерфейс командной строки, вам нужно будет выполнить вызов aws sts, чтобы взять на себя роль, прежде чем создавать или обновлять ресурсы в дополнительной учетной записи. Есть несколько сценариев, которые справятся с этим за вас.

Пример:

#! /bin/bash
#
# Dependencies:
#   yum install -y jq
#
# Setup:
#   chmod +x ./assume_cloudadmin_role.sh
#
# Execute:
#   source ./assume_cloudadmin_role.sh
#
# Description:
#   Makes assuming an AWS IAM role (+ exporting new temp keys) easier. You're users access key and secret must allow you to assume the role in the sts CLI call.

unset  AWS_SESSION_TOKEN
export AWS_ACCESS_KEY_ID=<place_your_key_here> #Master Account API Key
export AWS_SECRET_ACCESS_KEY=<place_your_secret_here>#Master Account API Secret
export AWS_REGION=us-east-1

temp_role=$(aws sts assume-role \
                    --role-arn "arn:aws:iam::0123456789012:role/My_Role_To_Assume" \
                    --role-session-name "temp_cli_role")

export AWS_ACCESS_KEY_ID=$(echo $temp_role | jq -r .Credentials.AccessKeyId)
export AWS_SECRET_ACCESS_KEY=$(echo $temp_role | jq -r .Credentials.SecretAccessKey)
export AWS_SESSION_TOKEN=$(echo $temp_role | jq -r .Credentials.SessionToken)

env | grep -i AWS_

Этот вызов установит ваш ключ доступа и секретный + токен сеанса для выполнения действий с дополнительной учетной записью.

Надеюсь, у вас это сработает!

person Michael Quale    schedule 25.09.2019
comment
Извините, похоже, вы ответили на мое первоначальное сообщение, затем я переписал большую часть его, как только обнаружил основную причину. Тем не менее, я думаю, вы на правильном пути. Я думаю, мне нужно добавить роль в основную учетную запись, у которой есть разрешение на создание записей DNS, а затем использовать вкладку «Отношения доверия» в IAM ›Роли, чтобы позволить моей группе пользователей CLI в связанной учетной записи взять на себя эту роль. Я попробую. - person carpiediem; 25.09.2019
comment
Понятно, я вижу, вы обновили вопрос. для ваших доверительных отношений вы можете просто добавить то, что я поместил в свой отредактированный ответ, и пока ваша основная учетная запись имеет правильные сопоставления пользователей / ролей, она должна работать. И да, рут правильный. В основной учетной записи у вас также будет роль и назначить пользователей этой роли. - person Michael Quale; 25.09.2019
comment
Хм. Пока не повезло. Является ли root часть ARN потенциальной проблемой? Поскольку это предполагаемая роль, пытающаяся подключиться к основной учетной записи и взять на себя вторую роль? - person carpiediem; 26.09.2019
comment
Нет, корневая часть правильная. Отредактировал свой ответ, чтобы было понятнее. - person Michael Quale; 26.09.2019

На дату этого ответа и с обновлением API CDK разрешает этот тип проверки DNS. Я успешно создал сертификат с поддоменом и несколькими альтернативными доменами в уже существующей размещенной зоне. Однако я не работаю со связанными учетными записями, поэтому я не проверял, работает ли этот аспект.

На DnsValidatedCertificate свойство input validation может принимать результат вызова CertificateValidation.fromDnsMultiZone. Этот вызов статического члена принимает объект, пары ключ / значение которого представляют домены в сертификате и их IHostedZone объекты. Вы можете получить ссылку на размещенную зону, вызвав HostedZone.fromLookup(this, id, { domainName: domain }) CDK Route53.

Собираем все вместе:

import { HostedZone } from '@aws-cdk/aws-route53';
import { Certificate, CertificateValidation } from '@aws-cdk/aws-certificatemanager';

// within the stack...
const hzone = HostedZone.fromLookup(this, 'hz', { domainName: 'www.example.com' });
const cert  = new Certificate(this, 'cert', {
  domainName: site,
  validation: CertificateValidation.fromDnsMultiZone({ 'www.example.com': hzone }),
  region: 'us-east-1',
});

ПРИМЕЧАНИЕ. Возможно, вам придется внести некоторые изменения в приведенный выше фрагмент кода в зависимости от конфигурации DNS. Например, www.example.com может быть записью CNAME или A в размещенной зоне example.com. В этом случае вызов fromLookup должен использовать example.com как domainName вместо поддомена www.

Кроме того, этот процесс создает файл cdk.context.json, который сохраняет контекст поиска DNS для ссылки на вашу размещенную зону. Вот целая ветка обсуждения о необходимости проверить этот файл в системе контроля версий.

person Andrew Philips    schedule 14.06.2021