1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Cloud9共有環境に、最小権限でチームメンバーを招待してみた

Last updated at Posted at 2024-01-21

はじめに

Cloud9には環境を共有する機能があります。
この機能を利用することでリモートでもペア・モブプロが可能となります。

この時、共有相手用のIAMが必要となります。

ポリシーは最小権限にせよ、という無視しがちなベストプラクティスを守る練習として、この時用意する共有相手用のIAMを最小権限で用意してみたいと思います。

アーキテクチャ

cap.png

cloud9環境の共有用に、以下のリソースを用意します。

  • Cloud9被共有者用ポリシーのみをアタッチしたロール
  • 上記ロールへのみスイッチできるユーザーグループ
  • 上記ユーザーグループにのみ所属し、パスワード変更以外のallowポリシーを持たない共有相手用のIAM

この時、共有相手のIAMは、Readを含む全てのポリシーを許可されていないため、AWSアカウントが持つすべてのリソースにアクセスできません。
唯一、スイッチロールのみが利用可能で、スイッチロール後は、共有されたCloud9環境での作業のみ行うことができるようになります。

tfコード

ディレクトリ構成

.
├── main.tf
├── variable.tf
├── terraform.tfvars
├── cloud9.tf
└── IAM.tf

variable.tf

variable.tf
######################################
## terraform.tfvarsから変数取得
######################################
variable "cloud9_subnet_id" {
  type = string
}

variable "owner_arn" {
  type    = string
  description = "If default, terraform execution arn becomes the owner of the cloud9 instance"
  default = ""
}
  • Cloud9にはownerというユーザーを指す属性が存在します。
  • 招待機能はこのownerしか使用できません。
  • デフォルトではownerはリソース作成者(この場合はterraform実行ユーザー)となります。
  • ownerをterraform実行ユーザー以外に設定する場合に指定するvarを定義しています。

main.tf

main.tf
############################################################################
## terraformブロック
############################################################################
terraform {
  # Terraformのバージョン指定
  required_version = "~> 1.7.0"

  # Terraformのaws用ライブラリのバージョン指定
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.33.0"
    }
  }
}

############################################################################
## providerブロック
############################################################################
provider "aws" {
  # リージョンを指定
  region = "ap-northeast-1"
}
  • Cloud9のimageに「amazonlinux-2023-x86_64」を使いたかったので、terraform、providerのverを最新にしています

cloud9.tf

cloud9.tf
data "aws_caller_identity" "default" {}

resource "aws_cloud9_environment_ec2" "main" {
  instance_type = "t2.micro"
  name          = "example-env"
  image_id      = "amazonlinux-2023-x86_64"
  subnet_id     = var.cloud9_subnet_id
  owner_arn     = coalesce(var.owner_arn, data.aws_caller_identity.default.arn)
}
  • 引数のうち、nullやブランクでない最初の値を返却するcoalesce関数を使用しています。
> coalesce("a", "b")
a
> coalesce("", "b")
b
> coalesce(1,2)
1

IAM.tf

IAM.tf
############################################################################
## AWSCloud9EnvironmentMemberポリシーのみをアタッチしたロール
############################################################################
# アカウント情報を取得
data "aws_caller_identity" "account" {}

# アカウントユーザーを対象とするassumeポリシー
data "aws_iam_policy_document" "assume" {
  statement {
    actions = ["sts:AssumeRole"]

    principals {
      type        = "AWS"
      identifiers = [data.aws_caller_identity.account.account_id]
    }
  }
}

# Cloud9共有用ロールを作成する
resource "aws_iam_role" "role" {
  name               = "cloud9_shared_role"
  assume_role_policy = data.aws_iam_policy_document.assume.json
}

# マネージドポリシー取得
data "aws_iam_policy" "policy" {
  arn = "arn:aws:iam::aws:policy/AWSCloud9EnvironmentMember"
}

# ポリシーをロールにアタッチ
resource "aws_iam_role_policy_attachment" "cloud9" {
  role       = aws_iam_role.role.name
  policy_arn = data.aws_iam_policy.policy.arn
}

############################################################################
## ロールにスイッチできる許可をあたえるIAMグループを作成
############################################################################
# IAMグループ
resource "aws_iam_group" "group" {
  name = "cloud9_shared_members"
  path = "/users/"
}

# cloud9ロールへのスイッチロールのみを許可するポリシードキュメント
data "aws_iam_policy_document" "sts" {
  statement {
    sid = "1"

    actions = [
      "sts:AssumeRole",
    ]

    resources = [
      aws_iam_role.role.arn,
    ]
  }
}

# グループにアタッチする独自ポリシー作成
resource "aws_iam_policy" "sts" {
  name   = "sts-cloud9-shared-policy"
  policy = data.aws_iam_policy_document.sts.json
}

# グループにポリシーをアタッチ
resource "aws_iam_group_policy_attachment" "sts" {
  group      = aws_iam_group.group.name
  policy_arn = aws_iam_policy.sts.arn
}
  • 前述した、「Cloud9被共有者用ポリシーのみをアタッチしたロール」「左記ロールへのみスイッチできるユーザーグループ」を作成しています。

動作確認

cap1.PNG

test-no-policy-userというユーザーをテスト用に作成します。

cap2.PNG

動作確認のためグループに所属させず、初期ポリシーのみで作成を完了させます。

cap3..PNG

ログインしてみると、Read権限すらないことが確認できます。

cap3.PNG

Cloud9コンソールもエラーが多発します。

cap4.PNG

確認のため、Cloud9の共有環境に招待してみます。

cap6.PNG

IDEにアクセスできますが、エラーメッセージが表示されます。

cap7.PNG

用意したユーザーグループに「test-no-policy-user」を所属させます。

cap8.PNG

スイッチロールができました。Cloud9コンソールでのエラーも発生していません。

cap9.PNG

招待してみます。ロールにスイッチしたユーザーを招待する場合は、ユーザー名ではなく、arn:aws:sts::${account_id}:assumed-role/${roll_id}/${user_id}を招待します。
今回の場合、arn:aws:sts::123456789012:assumed-role/cloud9_shared_role/test-no-policy-userです。

参考:

cap10.PNG

無事エラーが発生しない状態で共有されました!

cap11.PNG

また、その他リソースについては依然Readすらできない状態であることが確認できます。

おわりに

Cloud9の環境共有機能、なかなか良いですよね。
ペア・モブプログラミングの土壌をクラウド上でサクッと構築できるのはありがたいです。

また、おまけとして、つい適当にしてしまっているIAMの最小権限化にも挑戦してみました。
FullAccessにしないことで必要なポリシーも自然と意識できるようになると思うので、今後もきちんと実施できればなと思います。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?