Amazon Kinesis Streamの監視方法

Kinesis Streamのシャードには以下のような制限がある。

  • 書き込み 1シャード 最大1秒あたり1,000レコードまたは1MBまで
  • 読み込み 1シャード 最大1秒あたり5回の読み込みまたは2MBまで

シャードへの流入・流出量を上記の値を超えないように・または超えたことを検知できるように
監視していかないといけない。

そのため、CloudWatchでのKinesisの監視項目をまとめる。

どのメトリクスを見るべきか

CloudWatchでどういうメトリクスが見れるかは公式ドキュメントに記載がある。
http://docs.aws.amazon.com/ja_jp/streams/latest/dev/monitoring-with-cloudwatch.html

その中でも以下の項目を見ると、シャードを増やすしきい値が見えてきそう。

WriteProvisionedThroughputExceeded

シャードの書き込み上限の超過が発生しているか否かを判定するのなら、この項目を見ればよい。
これは指定された期間中にストリームの上限超過が発生した件数が出力される。

これが定常的に1以上になった場合は、シャードを増やしたほうが良さそう。

AWS CLIでの取得方法

profile=hoge
stream_name=hoge

aws --profile ${profile} cloudwatch get-metric-statistics 
--namespace AWS/Kinesis 
--metric-name WriteProvisionedThroughputExceeded 
--start-time 2017-06-20T12:00:00 
--end-time 2017-06-20T13:00:00 
--period 60 
--statistics Maximum 
--dimensions Name=StreamName,Value=${stream_name}

ReadProvisionedThroughputExceeded

これは上記に記載した「WriteProvisionedThroughputExceeded」の読み込み版。
こちらも合わせて見たい。

PutRecords.Bytes / PutRecords.Records

これは指定期間内にストリームに送信されたバイト/レコード数を確認することが出来る項目。
周期の最小単位が1分となっているため、指標として使うならこの値を使って1秒あたりの数値に計算しなおすとわかりやすい。

この項目を見ることにより、シャードの上限の超過の発生前に事前にシャードを増やすことができる。

PutRecordというのもあるが、KPLを使用している場合はPutRecordsを使う。

AWS CLIでの取得方法

profile=hoge
stream_name=hoge

aws --profile ${profile} cloudwatch get-metric-statistics 
--namespace AWS/Kinesis 
--metric-name PutRecords.Bytes 
--start-time 2017-06-22T12:00:00 
--end-time 2017-06-22T12:05:00 
--period 60 
--statistics Sum 
--dimensions Name=StreamName,Value=${stream_name} | jq .
response
{
  "Datapoints": [
    {
      "Unit": "Bytes",
      "Timestamp": "2017-06-22T12:02:00Z",
      "Sum": 4777677
    },
    {
      "Unit": "Bytes",
      "Timestamp": "2017-06-22T12:01:00Z",
      "Sum": 4241130
    },
    {
      "Unit": "Bytes",
      "Timestamp": "2017-06-22T12:00:00Z",
      "Sum": 5064734
    },
    {
      "Unit": "Bytes",
      "Timestamp": "2017-06-22T12:04:00Z",
      "Sum": 4647186
    },
    {
      "Unit": "Bytes",
      "Timestamp": "2017-06-22T12:03:00Z",
      "Sum": 4581718
    }
  ],
  "Label": "PutRecords.Bytes"
}
# 1分周期で取っているので、60(秒)で割って、1秒あたりのByteを計算
profile=hoge
stream_name=hoge

aws --profile ${profile} cloudwatch get-metric-statistics 
--namespace AWS/Kinesis 
--metric-name PutRecords.Bytes 
--start-time 2017-06-22T12:00:00 
--end-time 2017-06-22T12:05:00 
--period 60 
--statistics Sum 
--dimensions Name=StreamName,Value=${stream_name} | jq -r '.Datapoints[].Sum' | xargs -i expr {} / 60
response
79627
70685
84412
77453
76361

GetRecords.Bytes / GetRecords.Records

上記の「PutRecords.Bytes / PutRecords.Records」の読み込み版。
こちらも合わせて見たい。

続きを読む

LambdaでAWSの料金を毎日Slackに通知する(Python3)

はじめに

個人アカウントは基本的に無料枠で運用しているので、少しでも請求がある場合はいち早く気づきたいです。
先日、とあるハンズオンイベントで使ったリソースを消し忘れて、最終的に$30ぐらい請求が来てしまいました。。。

CloudWatchで請求アラートは設定していますが、閾値超えが想定の場合、当然見逃すことになり、最終的な請求額に驚くハメになります。

これを防ぐためにLambdaで毎日SlackにAWS料金を通知することにします。

先日LambdaがPython3に対応したので、せっかくだし勉強がてらPython3で実装したい。
ネット上にはNode.jsでの実装例が多いようで、今回はこちらを参考にPython3で実装してみます。

必要なもの

  • Slack

    • incoming-webhooks URL

    • 適当なchannel
  • lambda-uploader
    • requestsモジュールをLambda上でimportするために利用

      • カレントディレクトリにモジュールをインストールして、モジュールごとZipに固めてアップロードでもいけるはずですが、私の環境だとうまくいかなかったので
  • aws cli
    • lambda-uploaderで必要
  • AWS
    • Lambda関数用IAM Role

      • CloudWatchReadOnlyAccessポリシーをアタッチ

事前準備

lambda-uploaderをインストール

$ pip install lambda-uploader 

こちらを参考にさせていただきました。

aws cliをインストール

$ pip install awscli

credential、リージョン設定

$ aws configure

確認
$ aws configure list

コード

ディレクトリ構成

ディレクトリ名は任意です。関数名とは無関係です。

ディレクトリ構成
awscost_to_slack/
|--lambda_function.py
|--requirements.txt
|--lambda.json

lambda_function.py

超過金額に応じて色をつけるようにしています。
\$0.0なら緑、超過したら黄色、\$10超えで赤になります。

lambda_function.py
#!/usr/bin/env python
# encoding: utf-8

import json
import datetime
import requests
import boto3
import os
import logging

logger = logging.getLogger()
logger.setLevel(logging.INFO)

# Slack の設定
SLACK_POST_URL = os.environ['slackPostURL']
SLACK_CHANNEL = os.environ['slackChannel']

response = boto3.client('cloudwatch', region_name='us-east-1')

get_metric_statistics = response.get_metric_statistics(
    Namespace='AWS/Billing',
    MetricName='EstimatedCharges',
    Dimensions=[
        {
            'Name': 'Currency',
            'Value': 'USD'
        }
    ],
    StartTime=datetime.datetime.today() - datetime.timedelta(days=1),
    EndTime=datetime.datetime.today(),
    Period=86400,
    Statistics=['Maximum'])

cost = get_metric_statistics['Datapoints'][0]['Maximum']
date = get_metric_statistics['Datapoints'][0]['Timestamp'].strftime('%Y年%m月%d日')

def build_message(cost):
    if float(cost) >= 10.0:
        color = "#ff0000" #red
    elif float(cost) > 0.0:
        color = "warning" #yellow
    else:
        color = "good"    #green

    text = "%sまでのAWSの料金は、$%sです。" % (date, cost)

    atachements = {"text":text,"color":color}
    return atachements

def lambda_handler(event, context):
    content = build_message(cost)

    # SlackにPOSTする内容をセット
    slack_message = {
        'channel': SLACK_CHANNEL,
        "attachments": [content],
    }

    # SlackにPOST
    try:
        req = requests.post(SLACK_POST_URL, data=json.dumps(slack_message))
        logger.info("Message posted to %s", slack_message['channel'])
    except requests.exceptions.RequestException as e:
        logger.error("Request failed: %s", e)

requirements.txt

pip installしたいモジュール名を書きます。

requirements.txt
requests

lambda.json

Lambda関数名、IAM RoleのARNなどは環境に合わせてください。
スクリプト本体のファイル名とハンドラの前半を一致させないと動きません。地味にハマるので注意!

lambda.json
{
  "name": "LAMBDA_FUNCTION_NAME",
  "description": "DESCRIPTION",
  "region": "ap-northeast-1",
  "handler": "lambda_function.lambda_handler",
  "role": "arn:aws:iam::XXXXXXX:role/ROLE_NAME_FOR_LUMBDA",
  "timeout": 300,
  "memory": 128
}

デプロイ

上記ファイルを配置したディレクトリに移動して、lambda-uploaderを実行します。

$ cd awscost_to_slack
$ lambda-uploader
λ Building Package
λ Uploading Package
λ Fin

Lambda環境変数設定

今回のLambda関数では、通知先SlackチャネルとWebhooks URLを環境変数で渡すようにしたので、設定します。

スクリーンショット 2017-06-23 14.51.30.png

lambda-uploaderのlambda.jsonに書けそうなのですが、書式が分からず、今回はマネコンで設定しました。
lambda-uploaderでLambda関数を更新すると消えてしまうので注意。

Lambda定期実行設定

CloudWatchのスケジュールイベントを定義して、lambda関数をターゲットに指定します。
時刻はUTCなので注意しましょう。
毎日UTC0:00に実行されるよう設定しました。

スクリーンショット 2017-06-23 15.01.27.png

実行イメージ

スクリーンショット 2017-06-23 14.15.54.png
こんな感じで毎朝9:00に通知がきます。
今日も無料!

まとめ

Lambdaはほぼ無料でプログラムが動かせるので楽しいですね!
Python初心者なのでコードが見苦しい点はご容赦ください。

続きを読む

Fresh Install bitnami redmine stack on AWS, then migrate old data and database from old instance.

Fresh Install bitnami redmine stack on AWS, then migrate old data and database from old instance.

目的: Redmine のバージョンアップ と HTTPS化

ですが、新環境の構築手順のみやっていただければ新規構築手順としても使えます。

  • 前回書いた記事から1年ちょっと経過しました。
  • bitnami redmine stack AMI のバージョンも以下のように変化しました。(2017/06/21 現在)
    • Old version 3.2.1
    • New version 3.3.3
  • 前回は GUI でぽちぽち作成しましたが、今回は AWS CLI を中心に進めます。
  • ついでに前回書いてなかった HTTPS化 についても簡単に追記します。
  • 以下の AWS の機能を利用します。
    • Route53: ドメイン名取得、名前解決(DNS)
    • ACM(Amazon Certificate Manager): 証明書発行
    • ELB(Elastic Load Balancer): 本来は複数インスタンスをバランシングする用途に使うものですが今回は EC2 インスタンス 1台 をぶら下げ、ACM で取得した証明書を配布し外部との HTTPS通信 のために利用します。

注意と免責

  • 無料枠でない部分は料金が発生します。
  • データの正常な移行を保証するものではありません。

前提

  • 現環境が正常に動作していること。
  • 新環境を同一リージョン、同一VPC、同一サブネット内に新たにたてます。
    • インスタンス間のデータ転送を SCP で簡易に行いたいと思います。
    • 適宜セキュリティグループを解放してください。
  • aws cli version
% aws --version
aws-cli/1.11.47 Python/2.7.12 Darwin/16.6.0 botocore/1.5.10

段取り

  • 大まかに以下の順序で進めます
  1. Version 3.3.3 の AMI を使って EC2 インスタンスを起動
  2. Version 3.2.1 のデータバックアップ
    • Bitnami Redmine Stack の停止
    • MySQL Dump 取得
  3. Version 3.3.3 へのデータ復元
    • Bitnami Redmine Stack の停止
    • MySQL Dump 復元
    • Bitnami Redmine Stack の開始
  4. 動作確認

参考資料

作業手順

1. Newer Bitnami redmine stack インスタンス作成

以下の条件で作成します。

  • Common conditions

    • AMI: ami-15f98503
    • Type: t2.micro
    • Public IP: あり
  • User defined conditions
    • Region: N.Virginia
    • Subnet: subnet-bd809696
    • Security Group: sg-5b5b8f2a
    • Keypair: aws-n.virginia-default001
    • IAM Role: ec2-001
    • EBS: 20GB

WEB GUI から作るも良し、AWS CLI から作るも良し
以下コマンド実行例

set-env
KEY_NAME=aws-nvirginia-default001.pem
echo $KEY_NAME
check-ami
aws ec2 describe-images \
    --filters "Name=image-id,Values=ami-15f98503"
check-ami-name
aws ec2 describe-images \
    --filters "Name=image-id,Values=ami-15f98503" \
    | jq ".Images[].Name" \
    | grep --color redmine-3.3.3
create-instance
aws ec2 run-instances \
    --image-id ami-15f98503 \
    --count 1 \
    --instance-type t2.micro \
    --key-name aws-n.virginia-default001 \
    --security-group-ids sg-5b5b8f2a \
    --subnet-id subnet-bd809696 \
    --block-device-mappings "[{\"DeviceName\":\"/dev/sda1\",\"Ebs\":{\"VolumeSize\":20,\"DeleteOnTermination\":false}}]" \
    --iam-instance-profile Name=ec2-001 \
    --associate-public-ip-address
set-env
INSTANCE_ID=i-0f8d079eef9e5aeba
echo $INSTANCE_ID
add-name-tag-to-instance
aws ec2 create-tags --resources $INSTANCE_ID \
    --tags Key=Name,Value=redmine-3.3.3

注意書きにもありますが以下に表示される MySQL Database の root パスワードは初期起動時にしか表示されません。
このときに保管しておくか MySQL のお作法にしたがって変更しておいても良いでしょう

check-instance-created
aws ec2 describe-instances --filter "Name=instance-id,Values=$INSTANCE_ID"
wait-running-state
aws ec2 describe-instances \
    --filter "Name=instance-id,Values=$INSTANCE_ID" \
    | jq '.Reservations[].Instances[].State["Name"]'
get-redmine-password
aws ec2 get-console-output \
    --instance-id $INSTANCE_ID \
    | grep "Setting Bitnami application password to"
get-publicip
aws ec2 describe-instances \
    --filter "Name=instance-id,Values=$INSTANCE_ID" \
    | jq '.Reservations[].Instances[].NetworkInterfaces[].Association'
set-env
PUBLIC_IP=54.243.10.66
echo $PUBLIC_IP
site-check
curl -I http://$PUBLIC_IP/
HTTP/1.1 200 OK
(snip)
ssh-connect
ssh -i .ssh/$KEY_NAME bitnami@$PUBLIC_IP
first-login
bitnami@new-version-host:~$ sudo apt-get update -y
bitnami@new-version-host:~$ sudo apt-get upgrade -y
bitnami@new-version-host:~$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04.5 LTS"
bitnami@new-version-host:~$ sudo ./stack/ctlscript.sh status
subversion already running
php-fpm already running
apache already running
mysql already running
bitnami@new-version-host:~$ sudo ./stack/ctlscript.sh help
usage: ./stack/ctlscript.sh help
       ./stack/ctlscript.sh (start|stop|restart|status)
       ./stack/ctlscript.sh (start|stop|restart|status) mysql
       ./stack/ctlscript.sh (start|stop|restart|status) php-fpm
       ./stack/ctlscript.sh (start|stop|restart|status) apache
       ./stack/ctlscript.sh (start|stop|restart|status) subversion

help       - this screen
start      - start the service(s)
stop       - stop  the service(s)
restart    - restart or start the service(s)
status     - show the status of the service(s)

2. 旧バージョンのバックアップ取得

login_to_oldversion
Welcome to Ubuntu 14.04.3 LTS (GNU/Linux 3.13.0-74-generic x86_64)
       ___ _ _                   _
      | _ |_) |_ _ _  __ _ _ __ (_)
      | _ \ |  _| ' \/ _` | '  \| |
      |___/_|\__|_|_|\__,_|_|_|_|_|

  *** Welcome to the Bitnami Redmine 3.2.0-1         ***
  *** Bitnami Wiki:   https://wiki.bitnami.com/      ***
  *** Bitnami Forums: https://community.bitnami.com/ ***
Last login: Sun May 29 07:33:45 2016 from xxx.xxx.xxx.xxx
bitnami@old-version-host:~$
check-status
bitnami@old-version-host:~$ sudo stack/ctlscript.sh status
subversion already running
php-fpm already running
apache already running
mysql already running
stop
bitnami@old-version-host:~$ sudo stack/ctlscript.sh stop
/opt/bitnami/subversion/scripts/ctl.sh : subversion stopped
Syntax OK
/opt/bitnami/apache2/scripts/ctl.sh : httpd stopped
/opt/bitnami/php/scripts/ctl.sh : php-fpm stopped
/opt/bitnami/mysql/scripts/ctl.sh : mysql stopped
start-mysql
bitnami@old-version-host:~$ sudo stack/ctlscript.sh start mysql
170621 10:04:34 mysqld_safe Logging to '/opt/bitnami/mysql/data/mysqld.log'.
170621 10:04:34 mysqld_safe Starting mysqld.bin daemon with databases from /opt/bitnami/mysql/data
/opt/bitnami/mysql/scripts/ctl.sh : mysql  started at port 3306
check-available-filesystem-space
bitnami@old-version-host:~$ df -h /
Filesystem                                              Size  Used Avail Use% Mounted on
/dev/disk/by-uuid/6cdd25df-8610-4f60-9fed-ec03ed643ceb  9.8G  2.7G  6.6G  29% /
load-env-setting
bitnami@old-version-host:~$ . stack/use_redmine
bitnami@old-version-host:~$ echo $BITNAMI_ROOT
/opt/bitnami
dump-mysql
bitnami@old-version-host:~$ mysqldump -u root -p bitnami_redmine > redmine_backup.sql
Enter password:
bitnami@old-version-host:~$ ls -ltrh
  • scp 準備

手元の作業PCから新Redmine環境へssh接続するときに使用した証明書(pem)ファイルを旧Redmine環境にも作成します。

  • 今回は作業PC上で cat で表示させておいて旧環境のコンソール上にコピペしました。
example
bitnami@old-version-host:~$ vi .ssh/aws-nvirginia-default001.pem
bitnami@old-version-host:~$ chmod 600 .ssh/aws-nvirginia-default001.pem
  • ファイル転送
file_transfer
bitnami@old-version-host:~$ scp -i .ssh/aws-nvirginia-default001.pem redmine_backup.sql <new-version-host-ipaddr>:~
  • 新バージョン側にファイルが届いているか確認
check-transfered-files
bitnami@new-version-host:~$ ls -alh redmine*

3. 新バージョンへの復元

stop-stack
bitnami@new-version-host:~$ sudo stack/ctlscript.sh status
subversion already running
php-fpm already running
apache already running
mysql already running

bitnami@new-version-host:~$ sudo stack/ctlscript.sh stop

/opt/bitnami/subversion/scripts/ctl.sh : subversion stopped
Syntax OK
/opt/bitnami/apache2/scripts/ctl.sh : httpd stopped
/opt/bitnami/php/scripts/ctl.sh : php-fpm stopped
/opt/bitnami/mysql/scripts/ctl.sh : mysql stopped
start-mysql
bitnami@new-version-host:~$ sudo stack/ctlscript.sh start mysql
initial-database
bitnami@new-version-host:~$ mysql -u root -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.6.35 MySQL Community Server (GPL)

(snip)

mysql> drop database bitnami_redmine;

mysql> create database bitnami_redmine;

mysql> grant all privileges on bitnami_redmine.* to 'bn_redmine'@'localhost' identified by 'DATAB
ASE_PASSWORD';

mysql> quit
restore-dumpfile
bitnami@new-version-host:~$ mysql -u root -p bitnami_redmine < redmine_backup.sql
Enter password:
bitnami@new-version-host:~$
edit-line-18
bitnami@new-version-host:~$ vi /opt/bitnami/apps/redmine/htdocs/config/database.yml

    18    password: "DATABASE_PASSWORD"
db-migrate
bitnami@new-version-host:~$ cd /opt/bitnami/apps/redmine/htdocs/
bitnami@new-version-host:/opt/bitnami/apps/redmine/htdocs$ ruby bin/rake db:migrate RAILS_ENV=production
bitnami@new-version-host:/opt/bitnami/apps/redmine/htdocs$ ruby bin/rake tmp:cache:clear
bitnami@new-version-host:/opt/bitnami/apps/redmine/htdocs$ ruby bin/rake tmp:sessions:clear
stack-restart
bitnami@new-version-host:/opt/bitnami/apps/redmine/htdocs$ cd
bitnami@new-version-host:~$ sudo stack/ctlscript.sh restart

bitnami@new-version-host:~$ exit
site-check
curl -I http://$PUBLIC_IP/
HTTP/1.1 200 OK
(snip)

ブラウザでも http://$PUBLIC_IP/ でアクセスして旧環境のユーザー名とパスワードでログイン出来ることを確認してください。

この時点で旧環境のインスタンスを停止させておいて良いでしょう。
いらないと判断した時に削除するなりしてください。

4. おまけ HTTPS化

  • 4-1. Route53 でドメイン名を取得してください

    • .net で 年額 11 USドル程度ですので実験用にひとつくらい維持しておくと便利
  • 4-2. Certificate Manager で証明書を取得します
    • コマンドでリクエストしてます
aws acm request-certificate --domain-name redmine.hogefuga.net
check-status-pending
aws acm describe-certificate \
    --certificate-arn "arn:aws:acm:us-east-1:942162428772:certificate/fdf099f9-ced7-4b97-a5dd-f85374d7d112" \
    | jq ".Certificate.Status"
"PENDING_VALIDATION"
  • 4-3. 承認する

    • ドメインに設定しているアドレスにメールが飛んできます
  • 4-4. ステータス確認
check-status-ISSUED
aws acm describe-certificate \
    --certificate-arn "arn:aws:acm:us-east-1:942162428772:certificate/fdf099f9-ced7-4b97-a5dd-f85374d7d112" \
    | jq ".Certificate.Status"
"ISSUED"
  • 4-5. Classic タイプの HTTPS ELB をつくる
example
aws elb create-load-balancer \
    --load-balancer-name redmine-elb1 \
    --listeners "Protocol=HTTPS,LoadBalancerPort=443,InstanceProtocol=HTTP,InstancePort=80,SSLCertificateId=arn:aws:acm:us-east-1:942162428772:certificate/fdf099f9-ced7-4b97-a5dd-f85374d7d112" \
    --availability-zones us-east-1a \
    --security-groups sg-3c90f343
  • 4-6. インスタンスをくっつける
example
aws elb register-instances-with-load-balancer \
    --load-balancer-name redmine-elb1 \
    --instances i-0f8d079eef9e5aeba
  • 4-7. State が InService になるまで待ちます
example
aws elb describe-instance-health \
    --load-balancer-name redmine-elb1
  • 4-8. DNS Name を確認する(4-10. で使います)
example
aws elb describe-load-balancers \
    --load-balancer-name redmine-elb1 \
  | jq ".LoadBalancerDescriptions[].DNSName"
  • 4-9. 今の設定を確認
example
aws route53 list-resource-record-sets \
    --hosted-zone-id Z3UG9LUEGNT0PE | jq .
  • 4-10. 投入用の JSON をつくる
example
vi change-resource-record-sets.json
example
{
  "Comment": "add CNAME for redmine.hogefuga.net",
  "Changes": [
    {
      "Action": "CREATE",
      "ResourceRecordSet": {
        "Name": "redmine.hogefuga.net",
        "Type":"CNAME",
        "TTL": 300,
        "ResourceRecords": [
          {
            "Value": <DNSName>
          }
        ]
      }
    }
  ]
}

4-11. 設定投入

example
aws route53 change-resource-record-sets \
    --hosted-zone-id Z3UG9LUEGNT0PE \
    --change-batch file://change-resource-record-sets.json

4-12. 設定確認

example
aws route53 list-resource-record-sets \
    --hosted-zone-id Z3UG9LUEGNT0PE

4-13. ブラウザ確認

https://redmine.hogefuga.net

4-14. EC2 インスタンスのセキュリティグループ再設定

  • グローバルの TCP:80 削除
  • サブネット内の TCP:80 許可
check
aws ec2 describe-security-groups --group-ids sg-b7d983c8
change
aws ec2 modify-instance-attribute \
    --instance-id i-0f8d079eef9e5aeba \
    --groups sg-b7d983c8

4-15. 再度ブラウザからアクセス可能か確認

続きを読む

IAMでクロスアカウントスイッチロール設定メモ

軽くテストしたので個人的な備忘録です。

★クロスアカウントスイッチロールすると嬉しいこと

複数のAWSアカウント間を認証画面介さず行き来できる
個人用IAMアカウント作るのは一か所でよくアカウント毎でなくなる
SDKつかってるような一部のツールではスイッチできないものもあるがawscliくらいならスイッチロールでいける
スイッチ先で権限を限定してスイッチ元でアカウントの増減を制御できるので
別会社間のメンバーの増減のアカウント管理のやり取りが生じなくてたぶんべんり

アカウント番号はサポート画面の右上に出てる。

★参考

Swith Roleで複数のAWSアカウント間を切替える – Qiita
超簡単!今すぐ使える「クロスアカウントアクセス」 | Developers.IO
AWS Black Belt Techシリーズ AWS IAM
【小ネタ】複数のSwitch Roleでのクロスアカウントアクセスをブラウザのブックマークで管理する | Developers.IO

一番したのやつ履歴が5こくらいまでできえることに憤慨している人は幸せになれそう。

★実際のクロスアカウントスイッチロール実装手順の簡易なメモ

0.テストするアカウントを2つようい

アカウント1
※スイッチ元
Account Number 1234zzzzzzzz

アカウント2
※スイッチ先
アカウント番号 5678xxxxxxxx

1.スイッチ先でロールを作成する

※お客様先にスイッチする場合お客様作業

IAMサービスを選択してロールを作る

新しいロールの作成
 >ロールの選択(クロスアカウントアクセスのロールで外部IDの使用を許可しないほうを選択)
  (※外部ID許可とはldapやadなどのIAMクレデンシャルでないID連携を許可するものと思われ)
  >このアカウントにアクセスできる IAM ユーザーの AWS アカウントの ID を入力(スイッチ元のIDを入力)
   (MFAが必要にチェックはデバイスやアプリの用意が可能な場合に入れる)
   >ポリシーのアタッチ(既存から選ぶのでカスタムにしたいならあらかじめ調べておく)
    (とりあえず試験用なので適当な権限にする(arn:aws:iam::aws:policy/AdministratorAccess ))
    >ロール名を入力:mygroup-admin

2.スイッチ元でロールを設定する

とりあえずユーザとグループを作る

グループ:mygroup
ユーザ:とりあえず二人くらいを作成

グループのインラインポリシーを作成しスイッチ先のアカウントとロールを設定する
ポリシー名:switch-to-otheraccount-name

{
  "Version": "2012-10-17",
  "Statement": {
    "Effect": "Allow",
    "Action": "sts:AssumeRole",
    "Resource": "arn:aws:iam::5678xxxxxxxx:role/mygroup-admin"
  }
}

3.スイッチ元で自分のユーザで入りなおしてから右上からスイッチロールを選択してスイッチする

アカウント:5678xxxxxxxx
ロール:mygroup-admin

お客様先にスイッチする場合、
・スイッチ元のアカウントIDをお伝えする
・作成したロール名とわたる先のアカウント名とアカウントIDを聞いて設定
・スイッチロールしてみる
・スイッチ履歴は5個くらいしか残らないので便利なリンクを作っておく

ということになります。

★証跡を追えるようにするためにスイッチ元でCloudTrailの設定

見た感じすでに設定済みな模様でござったのでリンク先をどうぞ。S3もみたところ数年前からログがあった。
Amazon Web Services ブログ: 【AWS発表】 AWS CloudTrail – AWS APIコールの記録を保存
AWSの操作履歴を記録するCloudTrailを試してみた « サーバーワークス エンジニアブログ

★アカウントのエイリアスの設定

あんまり関係ないがIDだと視認性が微妙なので設定したほうがよさそう(なくてもいい)

AWS アカウント ID とその別名 – AWS Identity and Access Management

変えたたらサブドメインがアカウント番号からエイリアス名になる(アカウント番号でもアクセスできるまま)
https://my-alias.signin.aws.amazon.com/console

★アカウント設定(パスワードポリシー)

ISMS的なアレ(または顧客要望)にのっとって適宜。
Account settingsから実施。

Minimum password length: x(x文字を要する)
Require at least one non-alphanumeric character(記号を要する)
Allow users to change their own password (自分で更新する)
Enable password expiration
Password expiration period (in days): xx(xx(日)で期限がきれる)

★ルートアカウントでアクセスしない

スイッチロールの設定時にrootアカウントにアクセスできるように設定しなければ
メニューにスイッチロールでないので物理的にルートアカウントにアクセスは不可能。
クラスメソッドのリンクが詳しい(rootでも設定するといけるけどやらないほうがいい))
単に運用上パスワード変えて限定共有する、クレデンシャル無効化する、MFAデバイス用意等。
あとCloudTrail的に個人IAMで操作したほうが証跡が追いやすい。

★クレデンシャルの書き方

たぶん以下のようになる。

[account2]
role_arn = arn:aws:iam::5678xxxxxxxx:role/mygroup-admin
source_profile = account1
region=us-xxxx-x

★スイッチロールのポリシーアタッチされてるグループにいるユーザをcliでだす

$ aws iam get-group --group-name mygroup --profile account1|jq -c -r '.Users[].UserName'

以上

続きを読む