AWS CLIを利用して、AWS Configの設定をしてみます。
前提条件
Configへの権限
Configに対してフル権限があること。
S3への権限
S3に対してフル権限があること。
SNSへの権限
SNSに対してフル権限があること。
IAMへの権限
IAMに対してフル権限があること。
AWS CLIのバージョン
以下のバージョンで動作確認済
- AWS CLI 1.7.28
aws --version
結果(例):
aws-cli/1.7.28 Python/2.7.5 Darwin/13.4.0
- 事前作業
===========
0.1. リージョンの決定
作成するS3バケットのリージョンを決めます。
(カレントユーザが利用するカレントリージョンも切り変わります。)
export AWS_DEFAULT_REGION='ap-northeast-1'
0.2. 変数の確認
プロファイルとリージョンが想定のものになっていることを確認します。
aws configure list
結果(例)
Name Value Type Location
---- ----- ---- --------
profile administrator-prjZ-mbp13 env AWS_DEFAULT_PROFILE
access_key ****************XXXX shared-credentials-file
secret_key ****************XXXX shared-credentials-file
region ap-northeast-1 env AWS_DEFAULT_REGION
- 事前作業
===========
1.1. AWS IDの取得
AWS_ID=`aws iam get-user --query 'User.Arn' --output text 2>&1 | sed 's/^.*:://' | sed 's/:.*$//'` \
|| AWS_ID=`aws iam get-user --query 'User.Arn' --output text 2>&1 | sed 's/^.* User: arn:aws:iam:://' |sed 's/:.*$//' | tr -d '\n'` \
&& echo ${AWS_ID}
結果(例):
XXXXXXXXXXXX
1.2. S3バケット名の決定
S3_BUCKET_NAME="config-bucket-${AWS_ID}-${AWS_DEFAULT_REGION}" \
&& echo ${S3_BUCKET_NAME}
バケット名が空いていることを確認します。
aws s3 ls s3://${S3_BUCKET_NAME}/
結果:
A client error (NoSuchBucket) occurred when calling the ListObjects operation: The specified bucket does not exist
1.3. SNSバケット名の決定
SNS_TOPIC_NAME="config-topic"
トピック名が空いていることを確認します。
SNS_TOPIC_ARN=$(aws sns list-topics --query "Topics[?contains(TopicArn,\`${SNS_TOPIC_NAME}\`)].TopicArn" --output text) \
&& echo ${SNS_TOPIC_ARN}
結果:
(戻り値なし)
1.4. IAMロール名の決定
IAM_ROLE_NAME="config-role-${AWS_DEFAULT_REGION}" \
&& echo ${IAM_ROLE_NAME}
同じ名前のIAMロールが存在しないことを確認します。
aws iam get-role \
--role-name ${IAM_ROLE_NAME}
結果(例):
A client error (NoSuchEntity) occurred when calling the GetRole operation: The role with name config-role-ap-northeast-1 cannot be found.
1.5. ロールドキュメントの作成
FILE_ROLE_DOC="iam-role-${IAM_ROLE_NAME}.json" \
&& echo ${FILE_ROLE_DOC}
cat << EOF > ${FILE_ROLE_DOC}
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "config.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
JSONファイルを作成したら、フォーマットが壊れてないか必ず確認します。
jsonlint -q ${FILE_ROLE_DOC}
1.6. ロールポリシードキュメントの作成
FILE_ROLE_POLICY_DOC="iam-role-${IAM_ROLE_NAME}-policy.json" \
&& echo ${FILE_ROLE_POLICY_DOC}
cat << ETX
AWS_ID: ${AWS_ID}
ETX
cat << EOF > ${FILE_ROLE_POLICY_DOC}
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"appstream:Get*",
"autoscaling:Describe*",
"cloudformation:DescribeStacks",
"cloudformation:DescribeStackEvents",
"cloudformation:DescribeStackResource",
"cloudformation:DescribeStackResources",
"cloudformation:GetTemplate",
"cloudformation:List*",
"cloudfront:Get*",
"cloudfront:List*",
"cloudtrail:DescribeTrails",
"cloudtrail:GetTrailStatus",
"cloudwatch:Describe*",
"cloudwatch:Get*",
"cloudwatch:List*",
"directconnect:Describe*",
"dynamodb:GetItem",
"dynamodb:BatchGetItem",
"dynamodb:Query",
"dynamodb:Scan",
"dynamodb:DescribeTable",
"dynamodb:ListTables",
"ec2:Describe*",
"elasticache:Describe*",
"elasticbeanstalk:Check*",
"elasticbeanstalk:Describe*",
"elasticbeanstalk:List*",
"elasticbeanstalk:RequestEnvironmentInfo",
"elasticbeanstalk:RetrieveEnvironmentInfo",
"elasticloadbalancing:Describe*",
"elastictranscoder:Read*",
"elastictranscoder:List*",
"iam:List*",
"iam:Get*",
"kinesis:Describe*",
"kinesis:Get*",
"kinesis:List*",
"opsworks:Describe*",
"opsworks:Get*",
"route53:Get*",
"route53:List*",
"redshift:Describe*",
"redshift:ViewQueriesInConsole",
"rds:Describe*",
"rds:ListTagsForResource",
"s3:Get*",
"s3:List*",
"sdb:GetAttributes",
"sdb:List*",
"sdb:Select*",
"ses:Get*",
"ses:List*",
"sns:Get*",
"sns:List*",
"sqs:GetQueueAttributes",
"sqs:ListQueues",
"sqs:ReceiveMessage",
"storagegateway:List*",
"storagegateway:Describe*",
"trustedadvisor:Describe*"
],
"Effect": "Allow",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject*"
],
"Resource": [
"arn:aws:s3:::config-bucket-${AWS_ID}-ap-northeast-1/AWSLogs/${AWS_ID}/*"
],
"Condition": {
"StringLike": {
"s3:x-amz-acl": "bucket-owner-full-control"
}
}
},
{
"Effect": "Allow",
"Action": [
"s3:GetBucketAcl"
],
"Resource": "arn:aws:s3:::config-bucket-${AWS_ID}-ap-northeast-1"
},
{
"Effect": "Allow",
"Action": "sns:Publish",
"Resource": "arn:aws:sns:ap-northeast-1:${AWS_ID}:config-topic"
}
]
}
EOF
JSONファイルを作成したら、フォーマットが壊れてないか必ず確認します。
jsonlint -q ${FILE_ROLE_POLICY_DOC}
- S3バケットの作成
===================
1.1. S3バケットの作成
cat << ETX
S3_BUCKET_NAME: ${S3_BUCKET_NAME}
ETX
aws s3 mb s3://${S3_BUCKET_NAME}
結果(例):
make_bucket: s3://config-bucket-XXXXXXXXXXXX-ap-northeast-1/
1.2. S3バケットの確認
aws s3 ls s3://${S3_BUCKET_NAME}
結果:
(戻り値なし)
- SNSトピックの作成
====================
2.1. SNSトピックの作成
手順: http://qiita.com/tcsh/items/e05e21e7338668cbf3b8
2.2. SNSトピックの購読
手順: http://qiita.com/tcsh/items/ca81576b0018bfa32cbe
- IAMロールの作成
==================
参考: http://docs.aws.amazon.com/config/latest/developerguide/iamrole-
permissions.html
3.1. ロールの作成
cat << ETX
IAM_ROLE_NAME: ${IAM_ROLE_NAME}
FILE_ROLE_DOC: ${FILE_ROLE_DOC}
ETX
aws iam create-role \
--role-name ${IAM_ROLE_NAME} \
--assume-role-policy-document file://${FILE_ROLE_DOC}
結果(例):
{
"Role": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "config.amazonaws.com"
}
}
]
},
"RoleId": "AROAJKX6IMJRSEEVCOO5C",
"CreateDate": "2015-05-25T06:54:10.914Z",
"RoleName": "config-role-ap-northeast-1",
"Path": "/",
"Arn": "arn:aws:iam::XXXXXXXXXXXX:role/config-role-ap-northeast-1"
}
}
3.2. ロールの確認
aws iam get-role \
--role-name ${IAM_ROLE_NAME}
結果(例):
{
"Role": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "config.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
},
"RoleId": "AROAJYWFXLVCHHE5VT6LI",
"CreateDate": "2015-05-25T06:54:10Z",
"RoleName": "config-role-ap-northeast-1",
"Path": "/",
"Arn": "arn:aws:iam::XXXXXXXXXXXX:role/config-role-ap-northeast-1"
}
}
3.3. ロールポリシーの作成
IAM_ROLE_POLICY_NAME="policy_CloudTrail_CloudWatchLogs_Role_${AWS_DEFAULT_REGION}"
cat << ETX
IAM_ROLE_NAME: ${IAM_ROLE_NAME}
IAM_ROLE_POLICY_NAME: ${IAM_ROLE_POLICY_NAME}
FILE_ROLE_POLICY_DOC: ${FILE_ROLE_POLICY_DOC}
ETX
aws iam put-role-policy \
--role-name ${IAM_ROLE_NAME} \
--policy-name ${IAM_ROLE_POLICY_NAME} \
--policy-document file://${FILE_ROLE_POLICY_DOC}
結果(例):
(戻り値なし)
3.4. ロールポリシーの確認
aws iam get-role-policy \
--role-name ${IAM_ROLE_NAME} \
--policy-name ${IAM_ROLE_POLICY_NAME}
結果(例):
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"appstream:Get*",
"autoscaling:Describe*",
"cloudformation:DescribeStacks",
"cloudformation:DescribeStackEvents",
"cloudformation:DescribeStackResource",
"cloudformation:DescribeStackResources",
"cloudformation:GetTemplate",
"cloudformation:List*",
"cloudfront:Get*",
"cloudfront:List*",
"cloudtrail:DescribeTrails",
"cloudtrail:GetTrailStatus",
"cloudwatch:Describe*",
"cloudwatch:Get*",
"cloudwatch:List*",
"directconnect:Describe*",
"dynamodb:GetItem",
"dynamodb:BatchGetItem",
"dynamodb:Query",
"dynamodb:Scan",
"dynamodb:DescribeTable",
"dynamodb:ListTables",
"ec2:Describe*",
"elasticache:Describe*",
"elasticbeanstalk:Check*",
"elasticbeanstalk:Describe*",
"elasticbeanstalk:List*",
"elasticbeanstalk:RequestEnvironmentInfo",
"elasticbeanstalk:RetrieveEnvironmentInfo",
"elasticloadbalancing:Describe*",
"elastictranscoder:Read*",
"elastictranscoder:List*",
"iam:List*",
"iam:Get*",
"kinesis:Describe*",
"kinesis:Get*",
"kinesis:List*",
"opsworks:Describe*",
"opsworks:Get*",
"route53:Get*",
"route53:List*",
"redshift:Describe*",
"redshift:ViewQueriesInConsole",
"rds:Describe*",
"rds:ListTagsForResource",
"s3:Get*",
"s3:List*",
"sdb:GetAttributes",
"sdb:List*",
"sdb:Select*",
"ses:Get*",
"ses:List*",
"sns:Get*",
"sns:List*",
"sqs:GetQueueAttributes",
"sqs:ListQueues",
"sqs:ReceiveMessage",
"storagegateway:List*",
"storagegateway:Describe*",
"trustedadvisor:Describe*"
],
"Effect": "Allow",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject*"
],
"Resource": [
"arn:aws:s3:::config-bucket-XXXXXXXXXXXX-ap-northeast-1/AWSLogs/XXXXXXXXXXXX/*"
],
"Condition": {
"StringLike": {
"s3:x-amz-acl": "bucket-owner-full-control"
}
}
},
{
"Effect": "Allow",
"Action": [
"s3:GetBucketAcl"
],
"Resource": "arn:aws:s3:::config-bucket-XXXXXXXXXXXX-ap-northeast-1"
},
{
"Effect": "Allow",
"Action": "sns:Publish",
"Resource": "arn:aws:sns:ap-northeast-1:XXXXXXXXXXXX:config-topic"
}
]
}
3.5. IAMロールのARN取得
IAM_ROLE_ARN=`aws iam get-role --role-name ${IAM_ROLE_NAME} --query 'Role.Arn' --output text` \
&& echo ${IAM_ROLE_ARN}
結果(例):
arn:aws:iam::XXXXXXXXXXXX:role/config-role-ap-northeast-1
- Configの有効化
=================
4.1. subscribeの実施
cat << ETX
S3_BUCKET_NAME: ${S3_BUCKET_NAME}
SNS_TOPIC_ARN: ${SNS_TOPIC_ARN}
IAM_ROLE_ARN: ${IAM_ROLE_ARN}
ETX
aws configservice subscribe \
--s3-bucket ${S3_BUCKET_NAME} \
--sns-topic ${SNS_TOPIC_ARN} \
--iam-role ${IAM_ROLE_ARN}
結果(例):
Using existing S3 bucket: config-bucket-XXXXXXXXXXXX-ap-northeast-1
Using existing SNS topic: arn:aws:sns:ap-northeast-1:XXXXXXXXXXXX:config-topic
Subscribe succeeded:
Configuration Recorders: [
{
"roleARN": "arn:aws:iam::XXXXXXXXXXXX:role/config-role-ap-northeast-1",
"name": "default"
}
]
Delivery Channels: [
{
"snsTopicARN": "arn:aws:sns:ap-northeast-1:XXXXXXXXXXXX:config-topic",
"name": "default",
"s3BucketName": "config-bucket-XXXXXXXXXXXX-ap-northeast-1"
}
]
4.2. ステータスの確認
aws configservice get-status
結果:
Configuration Recorders:
name: default
recorder: ON
last status: SUCCESS
Delivery Channels:
name: default
last stream delivery status: SUCCESS
- 確認
=======
5.1. デリバリチャネルの確認
aws configservice describe-delivery-channels
結果(例):
{
"DeliveryChannels": [
{
"snsTopicARN": "arn:aws:sns:ap-northeast-1:XXXXXXXXXXXX:config-topic",
"name": "default",
"s3BucketName": "config-bucket-XXXXXXXXXXXX-ap-northeast-1"
}
]
}
5.2. デリバリチャネル名の取得
CONF_DELIVERY_CHANNEL=` aws configservice describe-delivery-channels --query 'DeliveryChannels[].name' --output text` \
&& echo ${CONF_DELIVERY_CHANNEL}
5.3. 設定レコーダの確認
aws configservice describe-configuration-recorders
結果(例):
{
"ConfigurationRecorders": [
{
"roleARN": "arn:aws:iam::XXXXXXXXXXXX:role/config-role-ap-northeast-1",
"name": "default"
}
]
}
5.4. 設定レコーダの状態確認
aws configservice describe-configuration-recorder-status
結果(例):
{
"ConfigurationRecordersStatus": [
{
"recording": true,
"lastStatusChangeTime": 1432175805.699,
"lastStartTime": 1428460592.195,
"lastStatus": "SUCCESS",
"name": "default"
}
]
}
5.5. 設定レコーダ名の取得
CONF_RECORD_NAME=` aws configservice describe-configuration-recorders --query 'ConfigurationRecorders[].name' --output text` \
&& echo ${CONF_RECORD_NAME}
- 動作確認
===========
6.1. VPCの作成
aws ec2 create-vpc --cidr-block 10.1.0.0/20
結果(例):
{
"Vpc": {
"InstanceTenancy": "default",
"State": "pending",
"VpcId": "vpc-xxxxxxxx",
"CidrBlock": "10.1.0.0/18",
"DhcpOptionsId": "dopt-xxxxxxxx"
}
}
VPC_ID=vpc-xxxxxxxx
CONF_RESOURCE_ID=${VPC_ID}
6.2. 履歴の確認
CONF_RESOURCE_TYPE='AWS::EC2::VPC'
aws configservice get-resource-config-history \
--resource-type ${CONF_RESOURCE_TYPE} \
--resource-id ${CONF_RESOURCE_ID}
結果(例):
{
"configurationItems": [
{
"configurationItemCaptureTime": 1432538711.476,
"relationships": [
{
"resourceType": "AWS::EC2::NetworkAcl",
"resourceId": "acl-xxxxxxxx",
"relationshipName": "Contains NetworkAcl"
},
{
"resourceType": "AWS::EC2::RouteTable",
"resourceId": "rtb-xxxxxxxx",
"relationshipName": "Contains RouteTable"
},
{
"resourceType": "AWS::EC2::SecurityGroup",
"resourceId": "sg-xxxxxxxx",
"relationshipName": "Contains SecurityGroup"
}
],
"availabilityZone": "Multiple Availability Zones",
"tags": {},
"resourceType": "AWS::EC2::VPC",
"resourceId": "vpc-xxxxxxxx",
"configurationStateId": "1",
"relatedEvents": [
"xxxxxxxx-xxxx-xxxx-xxxx-c83c9ba78b53"
],
"arn": "arn:aws:ec2:ap-northeast-1:XXXXXXXXXXXX:vpc/vpc-xxxxxxxx",
"version": "1.0",
"configurationItemMD5Hash": "347d45e5c147842ec20f02309d66a4a2",
"configuration": "{"vpcId":"vpc-xxxxxxxx","state":"available","cidrBlock":"10.1.0.0/18","dhcpOptionsId":"dopt-xxxxxxxx","tags":[],"instanceTenancy":"default","isDefault":false}",
"configurationItemStatus": "ResourceDiscovered",
"accountId": "XXXXXXXXXXXX"
}
],
"nextToken": "eyJlbmNyeXB0ZWREYXRhIjpbMTEzLDU0LC0xMTMsMTIsLTUwLC0xMDcsNTcsOTYsLTkxLC03MywtMjEsOCwtNDAsNzQsOTAsMzUsLTIsODYsLTY1LDcxLC03LC05XSwzNCwyMSw5MywtMzIsLTk2LDgwLDQsODksLTMwLC05NCwtNjQsLTQsNDgsLTExMCw1Nyw5LC05Myw4MywzNCwxMjQsLTkwLDE0LDIwLC0xMDUsMTAzLC0xMjAsLTkxLC0xMjcsMTI0LC0xMjEsLTExMywtOTUsLTkyLC0yMiwxNCw4NiwtMzUsLTM5LDExNywtMTYsMTEsNjgsNjAsLTkxLDYsNzgsMTE2LC03MiwxMjIsMTA0LC0zNSw4MCwtNjAsLTUxLDE1LDI0LDExMSwtMTAsNjYsLTEyMSwtOTUsLTI3LC01OCwzMSw4OSwtMTksLTc2LC0zOSw3NiwtMjYsLTMzLDMyLC03MSwtNjMsLTExLC0yMCw3NCwxNCwtMzAsNjEsLTEyNywtMTUsNDEsNTgsLTIxLC00OSw1MCwtMzcsLTY1LC05LC0xMjgsLTc4LDExMSw0LC02OSw1OCwtNjMsMTE2LC02NywtOTMsMTA2LC0yNywxMjUsMTcsOTQsLTI5LC0yMSwtNywtMzQsLTM4LDM4LC0xMDAsLTYzLDY1LDEwLDgsLTc5LDEyNCw1LC02NCwtMzEsLTEwMCwyNiwtODAsLTExNiwtNTksNSwyMSw2MywzOCwtODUsMTI2LDYzLC04NCwtNCw1NCw1NywtMTA0LC00NCwtMTIzLDI0LDU4LC0zLDMyXSwibWF0ZXJpYWxTZXRTZXJpYWxOdW1iZXIiOjEsIml2UGFyYW1ldGVyU3BlYyI6eyJpdiI6WzUxLC0xMDIsMTA5LDQ4LDE3LC0xMjIsLTEyMiw5MiwtNTgsMTI0LC04MiwtODQsLTIxLC05MiwyLC00X119fQ=="
}
6.3. VPCの削除
aws ec2 delete-vpc --vpc-id ${VPC_ID}
結果:
(戻り値なし)
- 記録の停止、再開
===================
7.1. 記録の停止
cat << ETX
CONF_RECORD_NAME: ${CONF_RECORD_NAME}
ETX
aws configservice stop-configuration-recorder \
--configuration-recorder-name ${CONF_RECORD_NAME}
結果(例):
(戻り値なし)
aws configservice get-status
結果:
Configuration Recorders:
name: default
recorder: OFF
Delivery Channels:
name: default
last stream delivery status: SUCCESS
last snapshot delivery status: SUCCESS
7.2. 記録の再開
cat << ETX
CONF_RECORD_NAME: ${CONF_RECORD_NAME}
ETX
aws configservice start-configuration-recorder \
--configuration-recorder-name ${CONF_RECORD_NAME}
結果(例):
(戻り値なし)
aws configservice get-status
結果:
Configuration Recorders:
name: default
recorder: ON
last status: SUCCESS
Delivery Channels:
name: default
last stream delivery status: SUCCESS
- スナップショットの取得
=========================
8.1. スナップショットの確認
cat << ETX
CONF_DELIVERY_CHANNEL: ${CONF_DELIVERY_CHANNEL}
ETX
aws configservice deliver-config-snapshot \
--delivery-channel-name ${CONF_DELIVERY_CHANNEL}
結果(例):
{
"configSnapshotId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
8.2. ステータスの確認
aws configservice describe-delivery-channel-status \
--query 'DeliveryChannelsStatus[].configSnapshotDeliveryInfo'
結果:
[
{
"lastSuccessfulTime": 1432541300.012,
"lastStatus": "SUCCESS",
"lastAttemptTime": 1432541300.012
}
]
8.3. スナップショットの確認
S3のバケットスナップショットがあることを確認します。
(例) s3://config-bucket-XXXXXXXXXXXX-ap-northeast-1/AWSLogs/XXXXXXXXXXXX/Config/ap-northeast-1/2015/5/25/ConfigSnapshot/XXXXXXXXXXXX-northeast-1_ConfigSnapshot_20150525T080818Z_ca395e18-ef27-40b2-839d-2cab2bcab226.json.gz
完了
AWS Configは無料枠が無いので、ハンズオン完了後は課金を避けたい場合は記録を停止してください。