AWSとGCPのCloudShell
GCPのCloudShellに慣れてしまうとAWSのCloudShellは使い勝手が後退しているように感じる。
特に以下のようなポイントになかなか慣れない。
- リージョンの切り替えに伴いCloudShellがストレージごと切り替わる。(ap-northeast1のCloudShellで作ったファイルが参照できなくなる)
- 標準だとTerraformが入っていない。(自動、スクリプト関わらずCloudShell再起動のたびインストールすることになる)
- 便利なCloud IDEがCloudShellから使えない。
- vimへのコピペがオートフォーマットオプションに邪魔され崩れる(.vimrcにset pasteを入れておけば回避は可能)
そんなときにAWSのCloud9を使ってみたところGCP CloudShellの操作感にかなり近く、AWSにおけるQoLの向上を実感した。
Cloud9で困ったところ
Cloud9からTerraformでテスト環境をデプロイしようとしたところ
EC2のインスタンスプロファイルを作成するところでエラーがでてデプロイに失敗した。
resource "aws_spot_instance_request" "spot_vm" {
ami = data.aws_ami.amzlinux2.id
...
iam_instance_profile = aws_iam_instance_profile.instance_profile.id
depends_on=[aws_iam_instance_profile.instance_profile]
}
resource "aws_iam_instance_profile" "instance_profile" {
name = "my_vm_ssm_instance_profile"
role = data.aws_iam_role.ssm_role.id
}
data "aws_iam_role" "ssm_role" {
name ="MySSMRole"
}
発生したエラー
インスタンスプロファイルを作成する権限がなくCloud9からリソースをデプロイすることができないといった内容である。
│ Error: creating IAM Instance Profile (my_vm_ssm_instance_profile): InvalidClientTokenId: The security token included in the request is invalid
│ status code: 403, request id: uuid
│
│ with aws_iam_instance_profile.instance_profile,
│ on vm.tf line 66, in resource "aws_iam_instance_profile" "instance_profile":
│ 66: resource "aws_iam_instance_profile" "instance_profile" {
...
原因
調べてみたところCloud9のEC2インスタンスに適用されるAWS マネージド一時認証情報の制限が原因であった。
- Cloud9はデフォルトでAWS マネージド一時認証情報(AWS Managed Temporary Credentials->AMTC)というクレデンシャルの権限で動作する
- AMTCはログインユーザーと同等の権限を持つものの、一部操作が制限されている
AWS マネージド一時認証情報によってサポートされるアクション
https://docs.aws.amazon.com/ja_jp/Cloud9/latest/user-guide/security-iam.html#auth-and-access-control-temporary-managed-credentials-supported
ロールとやりとりするすべての IAM アクションは、Cloud9- で始まるロール名に対してのみ許可されます。
回避策
アクセスするため EC2 環境が必要となるアクションまたはリソースを AWS Cloud9 がサポートしないか、
...場合は、代わりに以下の方法を検討してください。
- EC2 環境に接続する Amazon EC2 インスタンスにインスタンスプロファイルを添付
- 特殊な環境変数を設定するか、aws configure コマンドを実行するなどして、永続的な AWS アクセス認証情報を EC2 環境に保存
ここでは一つ目の選択肢であるCloud9用EC2へのインスタンスプロファイルインスタンスプロファイルのアタッチにより事象を回避することにする。
Cloud9のAMTC無効化
メニューバーからCloud9 Preference > AWS Settings > Credentialsとたどり、AMTCを無効化する。
インスタンスプロファイル用ロールの作成
aws cliで インスタンスプロファイル用ロールを作成する。
aws iam create-role --role-name Cloud9-Administrator-Role --assume-role-policy-document file://AssumeRolePolicy2.json
#カスタマイズしたポリシーを適用する場合はJSONファイルを指定
#aws iam create-policy --policy-name Cloud9AdministratorAccessPolicy --policy-document Cloud9AdministratorAccessPolicy.json
aws iam attach-role-policy --policy-arn arn:aws:iam::aws:policy/AdministratorAccess --role-name Cloud9-Administrator-Role
インスタンスプロファイルの作成
同様にaws cliで インスタンスプロファイルを作成し、先ほど作ったCloud9用ロールをアタッチする。
aws iam create-instance-profile --instance-profile-name Cloud9InstanceProfile
aws iam add-role-to-instance-profile --role-name Cloud9-Administrator-Role --instance-profile-name Cloud9InstanceProfile
インスタンスプロファイルのアタッチ
Cloud9インスタンスにCloud9用ロールのついたインスタンスプロファイルをアタッチする。これでAMTCでは許可されなかった操作がCloud9からできるようになる。
$ aws ec2 associate-iam-instance-profile --iam-instance-profile Name=Cloud9InstanceProfile --instance-id i-instanceid
{
"IamInstanceProfileAssociation": {
"AssociationId": "iip-assoc-associationid",
"InstanceId": "i-instanceid",
"IamInstanceProfile": {
"Arn": "arn:aws:iam::accountid:instance-profile/Cloud9InstanceProfile",
"Id": "id"
},
"State": "associating"
}
}
インスタンスプロファイルの確認(オプション)
Stateがassociatedとなっていることを確認できる。
$ aws ec2 describe-iam-instance-profile-associations
{
"IamInstanceProfileAssociations": [
{
"AssociationId": "iip-assoc-associationid",
"InstanceId": "i-instanceid",
"IamInstanceProfile": {
"Arn": "arn:aws:iam::accountid:instance-profile/Cloud9InstanceProfile",
"Id": "id"
},
"State": "associated"
}
]
}
再度terraform apply
EC2に対するinstance_profileの作成をアタッチを含むterraform deployをCloud9からできるようになった。
$ terraform apply
...
Terraform will perform the following actions:
# aws_iam_instance_profile.instance_profile will be created
+ resource "aws_iam_instance_profile" "instance_profile" {
+ arn = (known after apply)
+ create_date = (known after apply)
+ id = (known after apply)
+ name = "my_vm_ssm_instance_profile"
+ name_prefix = (known after apply)
+ path = "/"
+ role = "MySSMRole"
+ tags_all = (known after apply)
+ unique_id = (known after apply)
}
...
Plan: 10 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
...
Apply complete! Resources: 10 added, 0 changed, 0 destroyed.