PackerがIAM RoleとMFAに対応していました

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

大栗です。

AWSでAMIを作成する時にはPackerをよく使います。多数のアカウントを管理するためSwitch Roleをして操作をすることが多いのですが、今までPackerではSwitch Roleに対応していませんでした。最近PackerでIAM Roleに対応していたことを知ったので試してみます。

PackerのIAM Role対応

今までは、以下のリンク先のようにaws sts assume-roleコマンドで一時クレデンシャルを発行してPackerテンプレートに設定していました。

(小ネタ)Packerを用いてAssumeRoleのAWSアカウントにカスタムAMIを作成する方法

2017年6月にリリースされたPackerバージョン1.0.1でMFA付きのAssume Roleに対応しました。

builder/amazon: Support Assume Role with MFA and ECS Task Roles. Also updates to a newer version of aws-sdk-go. [GH-4996]

使ってみる

事前準備

Packerの準備

こちらを参考にPackerをインストールします。

今回は最新のバージョン1.0.4のPackerで試しています。

$ packer --version
1.0.4

IAMの設定

下記の内容でIAMユーザをIAM Roleを作成します。

  • Switch元
    • AWSアカウントID:111111111111
    • IAMユーザ:arn:aws:iam::111111111111:user/origin
    • MFA:設定する
  • Switch先
    • AWSアカウントID:222222222222
    • IAM Role:arn:aws:sts::222222222222:role/switch
    • MFA が必要:チェックする

AWS CLIの設定

こちらを参考にcredentialsファイルとconfigファイルを設定します。

AWS CLIで使える認証情報とオプションの設定方法まとめ

credentialsファイルは以下の形式で記述します。

~/.aws/credentials

[default]
aws_access_key_id = AKIAIOSFODNN7EXAMPLE
aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
region=ap-northeast-1

configファイルは以下の形式で記述します。

~/.aws/config

[default]
region = ap-northeast-1

[profile switch]
role_arn = arn:aws:iam::222222222222:role/switch
source_profile = default
region = ap-northeast-1
mfa_serial = arn:aws:iam::111111111111:mfa/origin

CLIで設定を確認します。プロファイルがswitchの時にはMFAコードが求められます。

$ aws sts get-caller-identity
{
    "Account": "111111111111",
    "UserId": "AKIAIOSFODNN7EXAMPLE",
    "Arn": "arn:aws:iam::111111111111:user/origin"
}
$ aws --profile switch sts get-caller-identity
Enter MFA code:
{
    "Account": "222222222222",
    "UserId": "AKIAIOSFODNN7EXAMPLE-CLI-session-1234567890",
    "Arn": "arn:aws:sts::222222222222:assumed-role/switch/AWS-CLI-session-1234567890"
}

Packerの設定

テンプレートを以下のように記述します。ポイントとしてはbuildersでprofilemfa_codeのオプションを指定することです。mfa_codeは入力ごとに値が異なるため外部から指定できるようにしています。

sample.json

{
  "variables": {
    "mfa_code": "000000"
  },
  "builders": [{
    "type": "amazon-ebs",
    "region": "ap-northeast-1",
    "source_ami": "ami-3bd3c45c",
    "instance_type": "t2.small",
    "ssh_username": "ec2-user",
    "ami_name": "role-example",
    "profile": "switch",
    "mfa_code": "{{user `mfa_code`}}"
  }],
 "provisioners": [{
    "type": "shell",
    "inline": [
      "sudo yum -y update",
      "sudo yum -y install nginx"
    ]
  }]
}

AMIを作成する

以下のようにmfa_codeの値にMFAトークンの値を設定してPackerを実行します。

$ packer build -var "mfa_code=123456" sample.json
amazon-ebs output will be in this color.

==> amazon-ebs: Prevalidating AMI Name...
    amazon-ebs: Found Image ID: ami-3bd3c45c
・
・
・
・
・
==> amazon-ebs: Deleting temporary security group...
==> amazon-ebs: Deleting temporary keypair...
Build 'amazon-ebs' finished.

==> Builds finished. The artifacts of successful builds are:
--> amazon-ebs: AMIs were created:

ap-northeast-1: ami-a1b2c3d4

次にmfa_codeの値にでたらめな値を設定してみます。ちゃんとエラーが発生しました。

$ packer build -var "mfa_code=987654" ./sample.json
amazon-ebs output will be in this color.

==> amazon-ebs: Prevalidating AMI Name...
==> amazon-ebs: Error querying AMI: AccessDenied: MultiFactorAuthentication failed with invalid MFA one time pass code.
==> amazon-ebs: 	status code: 403, request id: 1234a567-89bc-01d2-e345-f678g9h01234
Build 'amazon-ebs' errored: Error querying AMI: AccessDenied: MultiFactorAuthentication failed with invalid MFA one time pass code.
	status code: 403, request id: 1234a567-89bc-01d2-e345-f678g9h01234

==> Some builds didn't complete successfully and had errors:
--> amazon-ebs: Error querying AMI: AccessDenied: MultiFactorAuthentication failed with invalid MFA one time pass code.
	status code: 403, request id: 1234a567-89bc-01d2-e345-f678g9h01234

==> Builds finished but no artifacts were created.

さいごに

今までは自分でAssume Roleを発行する必要がありましたが、Packerが対応したため設定を簡潔にできるようになりました。セキュリティを高めるためにはMFAも必要であるため、IAM Roleの対応とともにMFAに対応しており助かりました。