Создание защищенной MFA роли с помощью AWS CDK обходит условие MFA - PullRequest
2 голосов
/ 13 января 2020

Я пытаюсь создать защищенную MFA роль, предоставляющую AdministratorAccess, которую может принять другой пользователь. Я могу получить его, чтобы определить пользователя и политику разрешений роли. Однако когда я определяю требование MFA, принципал и разрешенное действие дублируются в политике разрешений, что делает условие требования MFA бесполезным.

Мой код CDK выглядит следующим образом:

from aws_cdk import (
    aws_iam as iam,
    core,
)


class AssumeRoleStack(core.Stack):

    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        user = iam.User(self, 'myuser')
        role = iam.Role(self, 'myrole',
                        assumed_by=iam.ArnPrincipal(user.user_arn),
                        max_session_duration=core.Duration.hours(8))
        role.add_managed_policy(iam.ManagedPolicy.from_aws_managed_policy_name('AdministratorAccess'))
        role.assume_role_policy.add_statements(
            iam.PolicyStatement(principals=[user],
                                actions=['sts:AssumeRole'],
                                conditions={'Bool': {'aws:MultiFactorAuthPresent': True}})
        )
        user.add_to_policy(iam.PolicyStatement(actions=['sts:AssumeRole'], resources=[role.role_arn]))

Результирующая политика разрешений роли выглядит следующим образом:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::012345678910:user/assume-role-myuserZ09A543B-1ULCILBM447SF"
      },
      "Action": "sts:AssumeRole"
    },
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::012345678910:user/assume-role-myuserZ09A543B-1ULCILBM447SF"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "Bool": {
          "aws:MultiFactorAuthPresent": "true"
        }
      }
    }
  ]
}

Это не то, что я хочу, потому что - как упоминалось выше - пользователь сможет взять на себя роль даже без присутствия MFA. Мне нужно следующее:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::012345678910:user/assume-role-myuserZ09A543B-1ULCILBM447SF"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "Bool": {
          "aws:MultiFactorAuthPresent": "true"
        }
      }
    }
  ]
}

Я уже пытался определить роль без аргумента assumed_by и вместо этого добавить принципала в assume_role_policy, но класс iam.Role требует принципала. , Точно так же, iam.PolicyStatement в assume_role_policy.add_statements() не позволяет пропустить ни аргумент principals, ни actions.

Как я могу создать политику разрешений роли без избыточностей и без необходимости делать условия бесполезными из-за них

Ответы [ 2 ]

1 голос
/ 13 января 2020

Похоже, что нет способа обновить существующую политику доверия. Возможно, вы можете поднять проблему на Github .

. В качестве обходного пути вы можете установить AccountRootPrincipal в качестве доверенного участника при определении роли, поэтому пользователь не может принять это без MFA.

iam.Role(
   assumed_by=iam.AccountRootPrincipal()
)
0 голосов
/ 22 января 2020

Я понял это сейчас. Решение представляет собой комбинацию предложенного @Vikyol и подсказок добрых людей на этой проблеме Github :

Вам необходимо создать класс, который наследует от iam.AccountRootPrincipal и переопределяет свойство policy_fragment, поэтому возвращаемая политика доверия содержит блок Conditions:

from aws_cdk import (
    aws_iam as iam,
    core,
)


class MFAAccountRootPrincipal(iam.AccountRootPrincipal):
    def __init__(self):
        super().__init__()

    @property
    def policy_fragment(self) -> iam.PrincipalPolicyFragment:
        return iam.PrincipalPolicyFragment(
            principal_json={'AWS': [self.arn]},
            conditions={'Bool': {'aws:MultiFactorAuthPresent': True}}
        )


class AssumeRoleStack(core.Stack):

    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        user = iam.User(self, 'myuser')
        role = iam.Role(self, 'MFA_Admin_Role',
                        assumed_by=MFAAccountRootPrincipal(),
                        managed_policies=[iam.ManagedPolicy.from_aws_managed_policy_name('AdministratorAccess')],
                        max_session_duration=core.Duration.hours(8))
        user.add_to_policy(iam.PolicyStatement(actions=['sts:AssumeRole'], resources=[role.role_arn]))

Обратите внимание, что это не позволяет доверять учетным записям, отличным от той, в которой определены пользователь и роль. Однако это можно легко решить, передав номер счета или экземпляр core.Environment в качестве аргумента инициализатору AssumeRoleStack. Передав это инициализатору MFAAccountRootPrincipal, вы можете вручную создать ARN пользователя root доверенной учетной записи.

...