かべぎわブログ

ブログです

AssumeRoleするときに外部IDをもとめるようにする

概要

クロスアカウントでAssumeRoleするときに外部IDを使用させる方法です。
悪意のある第三者にロール名、アカウントIDが漏洩しても、外部IDがわからなければAssumeRoleされないようになり、セキュリティの向上が見込めます。

手順

IAMロール作成

以下のような信頼ポリシーでIAMロールを作成します。
アカウントIDは自分の環境にあわせて変えてあげます。

"sts:ExternalId": "gaibu_id"の箇所が外部IDです。今回外部IDはgaibu_idとしています。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::123456789012:root"
            },
            "Action": "sts:AssumeRole",
            "Condition": {
                "StringEquals": {
                    "sts:ExternalId": "gaibu_id"
                }
            }
        }
    ]

AssumeRoleする

マネジメントコンソールでは外部ID付きでのスイッチロールができない(20220702時点)ため、AWSCLI等で実施します。以下はAWSCLIでの例です。

 sts assume-role \
    --role-arn arn:aws:iam::123456789012:role/externalIdTestRole \
    --role-session-name test-session \
    --external-id gaibu_id

fluentdからfluentdにとばす

概要

fluentd(td-agent)からfluentdにログを飛ばす方法です。

こんなかんじ

送信する側

飛ばしたいログファイル等は適当に変更しちゃってください。

@type forward , port 24224 でログを飛ばしてあげます。

<source>
  @type tail
  path /path/to/log.log
  pos_file /path/to/td-agent/log.pos
  tag test.tobasu
  <parse>
    @type json
  </parse>
</source>

<match test.tobasu>
  @type forward
  <server>
    host private_ip_addr
    port 24224
  </server>
</match>

受け取る側

格納先は適当に変更しちゃってください。

<source>@type forwardport 24224 で受け取ってあげればOKです。

<source>
  @type forward
  port 24224
  bind 0.0.0.0
  tag mongo.test
</source>

<match mongo.test>
    @type copy
  <store>
    @type mongo
    host 127.0.0.1
    port 27017
    database test_db
    collection test_db
  </store>
</match>

よく使う利用方法

AWS外からLBを経由してプライベートサブネット内のfluentdに飛ばす、そこからS3やDocumentDBに格納するみたいな使い方ができる。

送る側

<source>
  @type tail
  path /path/to/log.log
  pos_file /path/to/td-agent/log.pos
  tag test.tobasu
  <parse>
    @type json
  </parse>
</source>

<match test.tobasu>
  @type forward
  <server>
    host LBのアドレス
    port 24224
  </server>
</match>

受け取る側

<source>
  @type forward
  port 24224
  bind 0.0.0.0
  tag s3.test
</source>

<match s3.test>
  @type copy
  <store>
    @type s3
    s3_bucket my-bucket
    s3_region ap-northeast-1
    path logs/
    time_slice_format %Y/%m/%d/%Y%m%d-%H.log
  </store>
</match>

CloudFormation DeletionPolicy

CloudFormationのDeletionPolicyをつかうと、スタックを削除してもリソースをそのまま保持することができる。

  • DeletionPolicyの項目
    • Delete(削除)
    • Retain(保持)
    • Snapshot(スナップショット)

デフォルトのDeletionPolicyはDelete(削除)である。例外として、AWS::RDS::DBCluster リソースと、DBClusterIdentifier プロパティを指定しない AWS::RDS::DBInstance リソースのデフォルトポリシーは Snapshotである。

  • Snapshotポリシーがつかえるリソース
    • AWS::EC2::Volume
    • AWS::ElastiCache::CacheCluster
    • AWS::ElastiCache::ReplicationGroup
    • AWS::Neptune::DBCluster
    • AWS::RDS::DBCluster
    • AWS::RDS::DBInstance
    • AWS::Redshift::Cluster

ためしてみる

RetainとDelete

以下のCloudFormationテンプレートでスタックを作成した。

AWSTemplateFormatVersion: '2010-09-09'
Resources:
  kabegiwaRetainBucket:
    Type: AWS::S3::Bucket
    DeletionPolicy: Retain
  kabegiwaDeleteBucket:
    Type: AWS::S3::Bucket
$ aws cloudformation list-stacks --output text
STACKSUMMARIES  2022-05-10T07:54:30.891Z                        arn:aws:cloudformation:ap-northeast-1:0123456789012:stack/s3-test/6c6fa430-d036-11ec-811c-0e354ab8e31b       s3-test CREATE_COMPLETE

S3バケットが作成されている。

$ aws s3 ls
2022-05-10 07:53:47 cf-templates-1tsgh42ubih7m-ap-northeast-1
2022-05-10 07:54:37 s3-test-kabegiwadeletebucket-897fbs8hgspr
2022-05-10 07:54:37 s3-test-kabegiwaretainbucket-14jg9ttckhtue

CloudFormationスタックを削除する。

$ aws cloudformation delete-stack --stack-name s3-test

スタックの削除が完了。

$ aws cloudformation list-stacks --output text
STACKSUMMARIES  2022-05-10T07:54:30.891Z        2022-05-10T08:10:41.727Z                arn:aws:cloudformation:ap-northeast-1:0123456789012:stack/s3-test/6c6fa430-d036-11ec-811c-0e354ab8e31b       s3-test DELETE_COMPLETE

DeletionPolicyにRetainを設定したS3バケットは削除されずに保持されていることがわかる。

$ aws s3 ls
2022-05-10 07:53:47 cf-templates-1tsgh42ubih7m-ap-northeast-1
2022-05-10 07:54:37 s3-test-kabegiwaretainbucket-14jg9ttckhtue

Snapshot

以下のCloudFormationテンプレートでRDSインスタンスを作成した。

Resources:
  SnapshotDB:
    Type: AWS::RDS::DBInstance
    Properties:
      VPCSecurityGroups:
        - Fn::GetAtt: [ SnapshotDBSecurityGroup , GroupId ]
      AllocatedStorage: '5'
      DBInstanceClass: db.t2.small
      Engine: MySQL
      MasterUsername: MyName
      MasterUserPassword: MyPassword
    DeletionPolicy: Snapshot

  SnapshotDBSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: RDS
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 3306
          ToPort: 3306
          CidrIp: 0.0.0.0/0
$ aws cloudformation list-stacks --output text
STACKSUMMARIES  2022-05-10T09:01:24.275Z                        arn:aws:cloudformation:ap-northeast-1:0123456789012:stack/snapshot-test/c49949a0-d03f-11ec-98c3-0633c5fc036d snapshot-test   CREATE_COMPLETE

DBインスタンスが作成されている。

$ aws rds describe-db-instances | jq .DBInstances[].DBInstanceIdentifier
"sssu7dja6ka60k"

CloudFormationスタックを削除する。

$ aws cloudformation delete-stack --stack-name snapshot-test

スタックの削除が完了。

$ aws cloudformation list-stacks --output text
STACKSUMMARIES  2022-05-10T09:01:24.275Z        2022-05-10T09:20:13.138Z                arn:aws:cloudformation:ap-northeast-1:0123456789012:stack/snapshot-test/c49949a0-d03f-11ec-98c3-0633c5fc036d snapshot-test   DELETE_COMPLETE

スタックの削除時にDBのスナップショットが作成されている。

そしてそれはスタックが削除されても保持される。

IAMポリシーを更新してくれるシェルスクリプトを書いた

IAMポリシーを更新してくれるシェルスクリプトです。
バージョン数が5を超えていると最も古いバージョンを削除してくれます。

シェルスクリプトは最近書く機会があんまりないんだけれどもやっぱり楽しいですね。

Kinesis Data Streamsになにかデータつっこんで確認してみる

Kinesis Data Streamsにてきとーなデータをつっこんでみます。

手順

1. データストリームの作成

aws kinesis create-stream --stream-name kabegiwa-stream --shard-count 1

確認

aws kinesis list-streams
{
    "StreamNames": [
        "kabegiwa-stream"
    ]
}

2. レコードをストリームにPUTする

AWSCLIv2の場合は--cli-binary-format raw-in-base64-outオプションをつけないとInvalid base64になる。

 aws kinesis put-record --stream-name kabegiwa-stream --partition-key 123 --data file://test.json --cli-binary-format raw-in-base64-out

3. シャードイテレータを取得する

 aws kinesis get-shard-iterator --shard-id shardId-000000000000 --shard-iterator-type TRIM_HORIZON --stream-name kabegiwa-stream

出力されたShardIteratorの値をコピーしておく。

4. ストリームからレコードを取得する

さっきの手順で取得したシャードイテレータをわたしてget-recordしてあげる。

aws kinesis get-records --shard-iterator シャードイテレータ
{
    "Records": [
        {
            "SequenceNumber": "496073672870212182446181045",
            "ApproximateArrivalTimestamp": "2020-05-26T14:11:12.435000+00:00",
            "Data": "eyJuYW1lIjogImthYmVnaXdhIiwgImFnZSI6IDI4fQo=",
            "PartitionKey": "123"
        }
    ],
    "NextShardIterator": "AAAAAAAAAAGer6NTuyaqLamS1d57xdbhuhHoSEPN7h9f+LBKhMLWAiz6dZb1hzVc8BljWNZniBgo05xKmtQdrWBOA2O2C",
    "MillisBehindLatest": 0
}

5. 人間の目で確認する

Dataをbase64デコードしてあげる。

echo 'eyJuYW1lIjogImthYmVnaXdhIiwgImFnZSI6IDI4fQo=' | base64 -d
{"name": "kabegiwa", "age": 28}

AWSの月間利用料を取得するPythonを書いた

概要

PythonでAWSの月間利用料を取得するスクリプトをかきました。
今回のものは他のPythonスクリプトから読み込ませることも意識しています。

成果物

これです。 github.com

usage

Command line

python get_monthly_cost.py --help
usage: get_monthly_cost.py [-h] [--profile [PROFILE]] [--year [YEAR]]
                           [--month [MONTH]]

optional arguments:
  -h, --help           show this help message and exit
  --profile [PROFILE]  Use a specific profile from your credential file.
  --year [YEAR]        Sets the year for retrieving AWS costs.
  --month [MONTH]      Sets the month for retrieving AWS costs.
$ python get_monthly_cost.py
9.4029780888 USD
$ python get_monthly_cost.py --year 2020 --month 1
10.2359175577 USD

Programming

import get_monthly_cost
response = get_monthly_cost.cost().get()
# ('9.4029780888', 'USD')
import get_monthly_cost
response = get_monthly_cost.cost(2020,1).get()
# ('10.2359175577', 'USD')

図解即戦力 Amazon Web Servicesのしくみと技術がこれ1冊でしっかりわかる教科書

図解即戦力 Amazon Web Servicesのしくみと技術がこれ1冊でしっかりわかる教科書

  • 作者:小笠原 種高
  • 出版社/メーカー: 技術評論社
  • 発売日: 2019/11/07
  • メディア: 単行本(ソフトカバー)