Permissions Boundaryを複数のAWSアカウントに適用して利用者の操作権限にガードレールを設ける

こんにちは、櫻井です。

 

今回は、IAMの機能のひとつであるPermissions Boundaryについての説明と、Permissions BoundaryをデプロイするためのCloudFormationのテンプレートの作成、CloudFormationを利用した複数アカウントに対してのデプロイを行います。

 

CloudFormationを利用した複数アカウント・複数リージョンにデプロイする方法がわからない方、興味がある方は以前記事にしたので、下記のリンクを参照してください。

CloudFormationのStackSetsを使って複数アカウント・複数リージョンにデプロイする

 

目次

Permissions Boundaryとは

 

Permissions Boundaryとは、IAMの機能のひとつです。

 

Permissions Boundaryは、IAMユーザとIAMロールに対して付与することができます。IAMユーザ(またはロール)に付与されいているIAMポリシーとPermissions Boundaryの「両方」で許可されている場合は許可となり、「どちらか一方」で拒否されている場合は拒否となります。

 

したがって、IAMユーザ(ロール)に対して強い権限が与えられていたとしても、Permissions Boundaryで設定された制限の範囲を超えた権限を実行することができなくなります。

 

このサービスを適切に利用することで、社内AWS管理者は、AWSを利用する開発者全体に対して、AWSの利用をする際に最低限守ってほしい要件をガードレールとして設定することができます。

 

 

 

なぜ必要か

 

Permissions Boundaryが必要な理由として、「社内AWS管理者の運用負荷を軽減することができる」、「ガバナンスを強化することができる」、「開発速度の向上が見込める」などが挙げられます。

 

例えば、EC2を作成する権限は無いが、IAMロールを作成することはできる権限を持つIAMユーザがいるとします。その場合、このIAMユーザはEC2を作成する権限を付与したロールを作成し、そのロールに対してスイッチロールをすることで、EC2を作成することができてしまいます。

これは、あまりガバナンス的に良いとは考えにくいです。

 

では、上記のロールを作成する権限を持つIAMユーザからロールを作成する権限をデタッチした場合はどうなるでしょうか? 社内AWS管理者が、必要に応じ、その都度ロールを作成し、開発者に対してロールを払い出すことになるでしょう。

これでは、管理者の運用の負荷が高まってしまいます。また、ロール作成の都度、管理者と開発者間でやり取りを行う必要があるため、開発速度も低下してしまいます。

 

このような場合にPermissions Boundaryを使い、必要な権限を超えた権限を持たないようにするガードレールを設けることで、開発者は、管理者の想定範囲内で自由に開発を行うことができるようになります。

 

その結果、管理者と開発者間の必要なやり取りを減らすことができるがゆえに、管理者は運用負荷が軽減し、開発者はスピーディーな開発ができるようになり、ガバナンスの強化もすることができます。

 

 

CloudFormationテンプレートを作成する

 

先にテンプレートの全体像を見ていただき、その後、それぞれの制限についての説明を行います。

 

テンプレートの全体像

 

以下が今回作成したPermissions Boundaryのテンプレートの全体像です。

このあと、それぞれの制限についての説明をしていきます。

AWSTemplateFormatVersion: 2010-09-09

Parameters:
  BoundaryName:
    Type: String
    Default: GFPermissionsBoundary

  BoundaryArn:
    Type: String
    Default: arn:aws:iam::*:policy/GFPermissionsBoundary 

  GFSSORoleArn:
    Type: String
    Default: arn:aws:iam::*:role/GFSSORole

Conditions:
  IsEC2RestrictedAccount:
    !Or [
      !Equals ["************", !Ref AWS::AccountId],
      !Equals ["************", !Ref AWS::AccountId],
    ]

Resources:
  #--------------------------------------------------------------------------------------------------
  # Boundary Policy
  #--------------------------------------------------------------------------------------------------
  GFBoundaryPermissions:
    Type: AWS::IAM::ManagedPolicy
    Properties:
      Description: Policy for Permissions Boundary
      ManagedPolicyName: GFPermissionsBoundary 
      Path: /
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          #--------------------------------------------------------------------------------------------------
          # Allow All
          #--------------------------------------------------------------------------------------------------
          - Effect: Allow
            Action: "*"
            Resource: "*"
            Sid: AllowAll
          #--------------------------------------------------------------------------------------------------
          # Deny Create User
          #--------------------------------------------------------------------------------------------------
          - Effect: Deny
            Action:
              - iam:CreateUser
              - iam:UpdateUser
            Resource: "*"
            Sid: DenyCreateIAMUser

          #--------------------------------------------------------------------------------------------------
          # Deny Modify Policy
          #--------------------------------------------------------------------------------------------------
          - Effect: Deny
            Action:
              - iam:DeletePolicy
              - iam:CreatePolicyVersion
              - iam:DeletePolicyVersion
              - iam:SetDefaultPolicyVersion
            Resource:
              - !Sub arn:aws:iam::${AWS::AccountId}:policy/GFPermissionsBoundary 
            Sid: DenyModifyPolicy

          #--------------------------------------------------------------------------------------------------
          # No Boundary Detach
          #--------------------------------------------------------------------------------------------------
          - Effect: Deny
            Action:
              - iam:DeleteRolePermissionsBoundary
              - iam:DeleteUserPermissionsBoundary
            Resource: "*"
            Condition:
              StringEquals:
                iam:PermissionsBoundary: !Sub arn:aws:iam::${AWS::AccountId}:policy/GFPermissionsBoundary 
            Sid: NOBoundaryDetach

          #--------------------------------------------------------------------------------------------------
          #  Only Create Role GF Boudary
          #--------------------------------------------------------------------------------------------------
          - Effect: Deny
            Action:
              - iam:CreateRole
              - iam:UpdateRole
              - iam:UpdateRoleDescription
            Resource: "*"
            Condition:
              StringNotEquals:
                iam:PermissionsBoundary: !Sub arn:aws:iam::${AWS::AccountId}:policy/GFPermissionsBoundary 
            Sid: OnlyCreateRoleAndGFBoundary

          #--------------------------------------------------------------------------------------------------
          # Deny Accsess To Management Stack
          #--------------------------------------------------------------------------------------------------
          - Effect: Deny
            Action: "cloudformation:*"
            Resource: !Sub arn:aws:cloudformation:*:${AWS::AccountId}:stack/StackSet-GFManagementStack*/*
            Sid: DenyAccessToManagementStack

          #--------------------------------------------------------------------------------------------------
          # Control Instance
          #--------------------------------------------------------------------------------------------------
          - Effect: !If [IsEC2RestrictedAccount, Allow, Deny]
            Action: ec2:RunInstances
            Resource: arn:aws:ec2:*:*:instance/*
            Condition:
              StringNotEquals:
                ec2:InstanceType:
                  - t3a.nano
                  - t3a.micro
                  - t3a.small

          #--------------------------------------------------------------------------------------------------
          # Control Region
          #--------------------------------------------------------------------------------------------------
          - Effect: Deny
            Action: "*"
            Resource: "*"
            Condition:
              StringNotEquals:
                aws:RequestedRegion:
                  - ap-northeast-1
                  - us-east-1

  #--------------------------------------------------------------------------------------------------
  # geekfeed-AssumeRole
  #--------------------------------------------------------------------------------------------------
  GFSSORole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: GFSSORole
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Federated: !Sub arn:aws:iam::${AWS::AccountId}:saml-provider/gf.awsapps
            Action:
              - sts:AssumeRoleWithSAML
            Condition:
              StringEquals:
                SAML:aud: "https://signin.aws.amazon.com/saml"
      Path: /
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AdministratorAccess
      PermissionsBoundary: !Sub arn:aws:iam::${AWS::AccountId}:policy/GFBoundaryPermissions
    DependsOn: GFBoundaryPermissions 



制限についての説明

 

今回作成したテンプレートのそれぞれの制限について個別に解説していきます。

 

まずは全て許可

暗黙的な拒否も含めてすべて許可し、その後、制限したい項目については明示的な拒否をしていきます。

 
#--------------------------------------------------------------------------------------------------
# Allow All
#--------------------------------------------------------------------------------------------------
- Effect: Allow
  Action: "*"
  Resource: "*"
  Sid: AllowAll

 

 

IAMユーザ作成を制限

 

ここでは、「IAMユーザの作成自体を制限する場合」と「IAMユーザの作成は制限せずに、IAMユーザの作成をPermissions Boundaryが付与されたIAMユーザに限定したい場合」について紹介します。こちらを参照し、テンプレートを作成しようと考えている方はどちらかひとつを選択し、テンプレートに書き込んでください。

 

 

  • IAMユーザの作成自体を制限する場合

#--------------------------------------------------------------------------------------------------
# Deny Create User
#--------------------------------------------------------------------------------------------------
- Effect: Deny
  Action:
    - iam:CreateUser
    - iam:UpdateUser
  Resource: "*"
  Sid: DenyCreateIAMUser

 

 

  • Permissions Boundaryが付与されていないIAMユーザの作成を制限したい場合

Conditionというパラメータを利用して、Permissions Boundaryがアタッチされていない場合はIAMユーザの作成を拒否するというものです。

Conditionについて詳しく知りたい方は以下のリンクを参照してください

Conditionの利用方法

#--------------------------------------------------------------------------------------------------
# Deny Create User
#--------------------------------------------------------------------------------------------------
- Effect: Deny
  Action:
    - iam:CreateUser
    - iam:UpdateUser
  Resource: "*"
  Condition:
    StringNotEquals:
      iam:Permissions Boundary: !Sub arn:aws:iam::${AWS::AccountId}:policy/GFPermissionsBoundary 
  Sid: OnlyCreateUserWithGFBoudary

 

Permissions Boundaryのデタッチを制限

 

IAMユーザ(またはロール)から、Permissions Boundaryをデタッチできないようにします。

#--------------------------------------------------------------------------------------------------
# No Boundary Detach
#--------------------------------------------------------------------------------------------------
- Effect: Deny
  Action:
    - iam:DeleteRolePermissionsBoundary
    - iam:DeleteUserPermissionsBoundary
  Resource: "*"
  Condition:
    StringEquals:
      iam:PermissionsBoundary: !Sub arn:aws:iam::${AWS::AccountId}:policy/GFBoundaryPermissions
  Sid: NOBoundaryDetach

 

Permissions Boundaryの変更・削除を制限

 

Permissions Boundaryのポリシーを変更・削除をできないようにします。

#--------------------------------------------------------------------------------------------------
# Deny Modify Policy
#--------------------------------------------------------------------------------------------------
- Effect: Deny
  Action:
    - iam:DeletePolicy
    - iam:CreatePolicyVersion
    - iam:DeletePolicyVersion
    - iam:SetDefaultPolicyVersion
  Resource:
    - !Sub arn:aws:iam::${AWS::AccountId}:policy/GFBoundaryPermissions
  Sid: DenyModifyPolicy

 

Permissions Boundaryが付与されていないロールの作成を制限

 

Permissions Boundaryが付与されていないIAMロールの作成を制限します。

#--------------------------------------------------------------------------------------------------
#  Only Create Role GF Boudary
#--------------------------------------------------------------------------------------------------
- Effect: Deny
  Action:
    - iam:CreateRole
    - iam:UpdateRole
    - iam:UpdateRoleDescription
  Resource: "*"
  Condition:
    StringNotEquals:
      iam:PermissionsBoundary: !Sub arn:aws:iam::${AWS::AccountId}:policy/GFPermissionsBoundary 
  Sid: OnlyCreateRoleAndGFBoundary

 

今回作成されるスタックへのアクセス制限

 

CloudFormationでデプロイする際に作成される、Stackというものを削除してしまった場合、デプロイしたリソースも削除されてしまいます。

Stackを消すことができてしまえば用意したガードレールの意味がなくなってしまうので、万が一に備えてテンプレートに加えておきます。

 

すべてのStackへのアクセスを制限しているわけではないので、CloudFormationの利用は通常通り行うことができます。

#--------------------------------------------------------------------------------------------------
# Deny Accsess To Management Stack
#--------------------------------------------------------------------------------------------------
- Effect: Deny
  Action: "cloudformation:*"
  Resource: !Sub arn:aws:cloudformation:*:${AWS::AccountId}:stack/StackSet-GFManagementStack*/*
  Sid: DenyAccessToManagementStack

 

利用可能なインスタンスタイプ・インスタンスサイズの制限

 

普段利用しないインスタンスタイプやインスタンスサイズは利用できないようにしておきます。

 

また、複数アカウントにPermissions Boundaryデプロイする際、「インスタンスの制限をされては困る」というアカウントに関しては制限しない、といった設定を行います。

 

Conditionsというものを使い、利用の制限をしたくないアカウントのアカウントID(!Equalsのリストの左側)と、デプロイ先のアカウントID(!Equalsのリストの右側)が一致した場合はTrue、そうでない場合はFalseになるようにするIsEC2RestrictedAccountというものを作成しました。

Conditions:
  IsEC2RestrictedAccount:
    !Or [
      !Equals ["************", !Ref AWS::AccountId],
      !Equals ["************", !Ref AWS::AccountId],
    ]

 

 

Effectで条件分岐を行い、IsEC2RestrictedAccountがTrueだった場合はAllow、そうでない場合はDenyとなるように設定しています。

これで、「インスタンスの制限をされたら困る」アカウントに対して、別のテンプレートをわざわざ用意することなく対応することができます。

#--------------------------------------------------------------------------------------------------
# Control Instance
#--------------------------------------------------------------------------------------------------
- Effect: !If [IsEC2RestrictedAccount, Allow, Deny] 
  Action: ec2:RunInstances
  Resource: arn:aws:ec2:*:*:instance/*
  Condition:
    StringNotEquals:
      ec2:InstanceType:
        - t3a.nano
        - t3a.micro
        - t3a.small

 

リージョンの制限

 

普段使わないリージョンでのリソース作成は、不要になった場合に放置されていても発見するまでに時間がかかってしまうので、東京リージョンとバージニアリージョン以外の利用を制限しました。

#--------------------------------------------------------------------------------------------------
# Control Region
#--------------------------------------------------------------------------------------------------
- Effect: Deny
  Action: "*"
  Resource: "*"
  Condition:
    StringNotEquals:
      aws:RequestedRegion:
        - ap-northeast-1
        - us-east-1

 

作成したポリシーをアタッチするロールを作成

 

GeekFeedでは、SAMLを利用したAssumeRoleでマネジメントコンソールにログインしています。そのため、AssumeRole用のロールGFSSORoleを作成し、このロールに上記で作成したPermissions Boundaryをアタッチする必要があります。

 

方式が異なる場合は別の方法でロールを作成してください。

#--------------------------------------------------------------------------------------------------
# geekfeed-AssumeRole
#--------------------------------------------------------------------------------------------------
GFSSORole:
  Type: AWS::IAM::Role
  Properties:
    RoleName: GFSSORole
    AssumeRolePolicyDocument:
      Version: 2012-10-17
      Statement:
        - Effect: Allow
          Principal:
            Federated: !Sub arn:aws:iam::${AWS::AccountId}:saml-provider/gf.awsapps
          Action:
            - sts:AssumeRoleWithSAML
          Condition:
            StringEquals:
              SAML:aud: "https://signin.aws.amazon.com/saml"
    Path: /
    ManagedPolicyArns:
      - arn:aws:iam::aws:policy/AdministratorAccess
    PermissionsBoundary: !Sub arn:aws:iam::${AWS::AccountId}:policy/GFPermissionsBoundary 
  DependsOn: GFBoundaryPermissions

 

以上でユーザに制限のガードレールを設けるためのテンプレートを作成することができました。

次は実際にテンプレートから複数のアカウントに対してデプロイをしていきます。

 

 

CloudFormationで複数アカウントにデプロイする

 

CloudFormationでの複数アカウントへのデプロイ方法については、以前に記事にしてますので、そちらを御覧ください。

CloudFormationのStackSetsを使って複数アカウント・複数リージョンにデプロイする

 

以前の記事では複数リージョンにもデプロイしていますが、今回デプロイするものはIAMなのでリソース自体がグローバルになっています。

 

複数リージョンを選択するとエラーになるので、リージョンはどこか一つを選ぶようにしてください。

 

 

まとめ

 

今回は、権限管理のガードレールを設けるためのPermissions Boundaryについて紹介しました。

少し手間がかかる作業ではありますが、得られるメリットは大きいと思います。

 

今回設けた制限については一例なので、各々アレンジして使用してください。

 

 

一緒に働く仲間を募集中!

ギークフィードではAWSエンジニアを募集しています。

興味がある方はこちらからエントリーをしてぜひ一緒に働きましょう!

AWS・開発エンジニア募集

この記事が気に入ったら
いいね ! しよう

Twitter で
The following two tabs change content below.
櫻井
櫻井
2022年3月にギークフィードに入社。 エンジニア完全未経験からSAP・SAAを三週間で取得することが出来ました。そのためAWSに関することを中心に記事を作成する予定です。 自分が初心者だからこそわかる、エンジニア未経験の方や、エンジニアを始めたばかりの方の躓きポイントをうまく説明できるように頑張ります。

【採用情報】一緒に働く仲間を募集しています

採用情報
ページトップへ