ablog

不器用で落着きのない技術者のメモ

Route53 で特定のホストゾーンとトラフィックポリシーのみ編集できるIAMポリシー

IAMユーザー/ロールに対して、特定のホストゾーンと

  • 特定のホストゾーンとトラフィックポリシーのみ編集できるIAMポリシー
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowPublicHostedZonePermissions",
            "Effect": "Allow",
            "Action": [
                "route53:ListHostedZones",
                "route53:GetHostedZoneCount",
                "route53:ListHostedZonesByName",
                "route53:ListTrafficPolicies",
                "route53:ListTrafficPolicyVersions",
                "route53:GetTrafficPolicy",
                "route53:ListTrafficPolicyInstancesByPolicy",
                "route53:ListTrafficPolicyInstances"
            ],
            "Resource": "*"
        },
        {
            "Sid": "AllowPublic",
            "Effect": "Allow",
            "Action": [
                "route53:CreateTrafficPolicy",
                "route53:UpdateTrafficPolicy",
                "route53:CreateTrafficPolicyInstance",
                "route53:UpdateTrafficPolicyInstance",
                "route53:DeleteTrafficPolicyInstance"
            ],
            "Resource": [
                "arn:aws:route53:::trafficpolicy/ec******-****-****-****-**********f3", ★編集できるトラフィックポリシーを限定する
                "arn:aws:route53:::trafficpolicyinstance/*"
            ]
        },
        {
            "Sid": "AllowPublicHostedZonePermissions2",
            "Effect": "Allow",
            "Action": [
                "route53:CreateTrafficPolicyInstance",
                "route53:UpdateTrafficPolicyInstance",
                "route53:UpdateHostedZoneComment",
                "route53:GetHostedZone",
                "route53:ChangeResourceRecordSets",
                "route53:ListResourceRecordSets"
            ],
            "Resource": "arn:aws:route53:::hostedzone/Z2**********QF" ★編集できるホストゾーンを限定する
        }
    ]
}
$ aws route53 list-traffic-policies
{
    "IsTruncated": false,
    "TrafficPolicySummaries": [
        {
            "TrafficPolicyCount": 1,
            "LatestVersion": 1,
            "Type": "A",
            "Id": "ec******-****-****-****-**********f3",
            "Name": "TraficPolicyA"
        },
        {
            "TrafficPolicyCount": 1,
            "LatestVersion": 1,
            "Type": "A",
            "Id": "e1******-****-****-****-**********1a",
            "Name": "traficpolicy1"
        }
    ],
    "MaxItems": "100"
}
  • 許可しているホストゾーンにはポリシーレコードを作成できるが、

  • 許可していないホストゾーンにはポリシーレコードを作成できない。


許可していないトラフィックポリシーの編集もできない。

PostgreSQLのオプティマイザ統計情報を確認する

PostgreSQLオプティマイザ統計情報を確認する

  • pg_stat_user_tables
    • n_live_tup: 行数
    • n_dead_tup: 不要な(ガベージとなっている)行数
    • last_analyze: ANALYZE された日時
aurora-postgres107 awsuser 13:44 => select * from pg_stat_user_tables;
 relid | schemaname |     relname      | seq_scan | seq_tup_read | idx_scan | idx_tup_fetch | n_tup_ins | n_tup_upd | n_tup_del | n_tup_hot_upd | n_live_tup | n_dead_tup | n_mod_since_analyze | last_vacuu
m | last_autovacuum | last_analyze | last_autoanalyze | vacuum_count | autovacuum_count | analyze_count | autoanalyze_count
-------+------------+------------------+----------+--------------+----------+---------------+-----------+-----------+-----------+---------------+------------+------------+---------------------+-----------
--+-----------------+--------------+------------------+--------------+------------------+---------------+-------------------
 20499 | public     | pgbench_accounts |     3982 |    636618770 |        0 |             0 |         0 |         0 |         0 |             0 |          0 |          0 |                   0 |
  |                 |              |                  |            0 |                0 |             0 |                 0
 20502 | public     | pgbench_history  |        0 |            0 |          |               |         0 |         0 |         0 |             0 |          0 |          0 |                   0 |
  |                 |              |                  |            0 |                0 |             0 |                 0
 20496 | public     | pgbench_tellers  |        0 |            0 |        0 |             0 |         0 |         0 |         0 |             0 |          0 |          0 |                   0 |
  |                 |              |                  |            0 |                0 |             0 |                 0
 20493 | public     | pgbench_branches |        0 |            0 |        0 |             0 |         0 |         0 |         0 |             0 |          0 |          0 |                   0 |
  |                 |              |                  |            0 |                0 |             0 |                 0
(4 rows)

Time: 11.534 ms
aurora-postgres107 awsuser 13:45 => analyze pgbench_accounts;
ANALYZE
Time: 51023.555 ms
aurora-postgres107 awsuser 13:49 => analyze pgbench_history;
ANALYZE
Time: 4.838 ms
aurora-postgres107 awsuser 13:49 => analyze pgbench_tellers;
ANALYZE
Time: 861.631 ms
aurora-postgres107 awsuser 13:49 => analyze pgbench_branches;
ANALYZE
Time: 97.672 ms
aurora-postgres107 awsuser 13:49 => select * from pg_stat_user_tables;
 relid | schemaname |     relname      | seq_scan | seq_tup_read | idx_scan | idx_tup_fetch | n_tup_ins | n_tup_upd | n_tup_del | n_tup_hot_upd | n_live_tup | n_dead_tup | n_mod_since_analyze | last_vacuu
m | last_autovacuum |         last_analyze          | last_autoanalyze | vacuum_count | autovacuum_count | analyze_count | autoanalyze_count
-------+------------+------------------+----------+--------------+----------+---------------+-----------+-----------+-----------+---------------+------------+------------+---------------------+-----------
--+-----------------+-------------------------------+------------------+--------------+------------------+---------------+-------------------
 20499 | public     | pgbench_accounts |     3982 |    636618770 |        0 |             0 |         0 |         0 |         0 |             0 | 1000000023 |          0 |                   0 |
  |                 | 2019-10-13 13:48:29.577544+00 |                  |            0 |                0 |             1 |                 0
 20502 | public     | pgbench_history  |        0 |            0 |          |               |         0 |         0 |         0 |             0 |          0 |          0 |                   0 |
  |                 | 2019-10-13 13:49:25.797489+00 |                  |            0 |                0 |             1 |                 0
 20496 | public     | pgbench_tellers  |        0 |            0 |        0 |             0 |         0 |         0 |         0 |             0 |     100000 |          0 |                   0 |
  |                 | 2019-10-13 13:49:34.146215+00 |                  |            0 |                0 |             1 |                 0
 20493 | public     | pgbench_branches |        0 |            0 |        0 |             0 |         0 |         0 |         0 |             0 |      10000 |          0 |                   0 |
  |                 | 2019-10-13 13:49:39.786877+00 |                  |            0 |                0 |             1 |                 0
(4 rows)

Time: 11.658 ms
  • pg_stats で列統計を参照できる。
aurora-postgres107 awsuser 13:53 => ¥x
aurora-postgres107 awsuser 13:53 => select * from pg_stats where tablename = 'pgbench_accounts' and attname = 'aid';
-[ RECORD 1 ]----------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
schemaname             | public
tablename              | pgbench_accounts
attname                | aid
inherited              | f
null_frac              | 0
avg_width              | 4
n_distinct             | -1
most_common_vals       |
most_common_freqs      |
histogram_bounds       | {60814,10795715,21463216,30907670,42117763,52106907,61207613,70576084,80914430,91131376,100753925,110990754,121482625,132236843,142541838,151836882,161107926,169972558,180409363,189444879,199185870,209956656,219778236,230635774,240069437,250570290,259938531,269520728,279549323,289115868,299506440,308917267,318976934,328960455,338130309,348795979,358585995,368564674,379147261,389401241,398876550,408622750,419746424,430218119,441160716,451956639,462649650,473153342,482273474,491900892,501782995,512139033,522341040,531138199,541530720,551181427,561493083,571169975,581023579,591554462,599739834,609944740,621003108,631427193,641984893,651345974,661666172,671714772,682136209,691457107,701453860,710621601,720645788,729302265,739518578,749859090,759000386,769988872,779889944,790362142,800606393,810024605,819391048,829388826,839126779,849413480,860658902,869786870,880113980,889940523,900308333,910800021,919503190,928953277,938412306,949723183,959391357,970382364,979643943,990236561,999965815}
correlation            | 1
most_common_elems      |
most_common_elem_freqs |
elem_count_histogram   |

Time: 1.774 ms

Lambda + node.js のデバッグでオブジェクトの中身を見る

util.inspect を使って、console.log(util.inspect(<オブジェクト>,false,null)) とするとオブジェクトの中身を CloudWatch Logs に出力できる。

'use strict';

const AWS = require('aws-sdk');
const util = require('util'); // util モジュールを読み込む

exports.handler = (event, context, callback) => {
    console.log(util.inspect(event,false,null)); // event オブジェクトの中身を CloudWatch Logs に出力する
    callback(null, `Successfully processed records.`);
};

DynamoDB Streams + AWS Lambda Triggers で連携すると Item は event オブジェクトで渡される

DynamoDB Streams + AWS Lambda Triggers で連携すると Item のデータは event オブジェクトで渡されることを確認した。

  • Lambda (node.js) のコード
'use strict';

const AWS = require('aws-sdk');
const util = require('util'); // util モジュールを読み込む

exports.handler = (event, context, callback) => {
    console.log(util.inspect(event,false,null)); // event オブジェクトの中身を CloudWatch Logs に出力する
    callback(null, `Successfully processed records.`);
};
  • マネジメントコンソールから Item を追加する。


  • CloudWatch Logs を確認する。
START RequestId: e244136e-f013-4370-8eaa-cbb5e7eeb17c Version: $LATEST
2019-10-12T18:22:49.014Z e244136e-f013-4370-8eaa-cbb5e7eeb17c { Records:
[ { eventID: '0a137cbf32e847170dc7a2678022f9ce',
eventName: 'INSERT',
eventVersion: '1.1',
eventSource: 'aws:dynamodb',
awsRegion: 'ap-northeast-1',
dynamodb:
{ ApproximateCreationDateTime: 1570904568,
Keys:
{ page_id: { S: 'az2c7az-4cbe-4cb8-ba57-aza9e48662az' },
activity_dt: { S: '2019-10-13 03:22:00' } }, 
NewImage:
{ page_id: { S: 'az2c7az-4cbe-4cb8-ba57-aza9e48662az' }, ★追加した Item が出力されている
activity_dt: { S: '2019-10-13 03:22:00' }, ★
payload:
{ S: '{"Hits": 5,"device": { "make": "Haltheon", "platform": { "name": "Android", "version": "4.0.3" }, "location": { "latitude": "69.290003", "longitude": "-130.506449", "country": "LA" }},"session": { "session_id": "459d25a9-03da-46d3-b447-2a649d52aa45", "start_timestamp": "147544967644", "stop_timestamp": "1507239966595"}}\n' } }, ★
SequenceNumber: '707844700000000030212725492',
SizeBytes: 512,
StreamViewType: 'NEW_IMAGE' },
eventSourceARN: 'arn:aws:dynamodb:ap-northeast-1:123456780123:table/web_analytics/stream/2019-05-16T23:33:44.183' } ] }
END RequestId: e244136e-f013-4370-8eaa-cbb5e7eeb17c
REPORT RequestId: e244136e-f013-4370-8eaa-cbb5e7eeb17c Duration: 78.63 ms Billed Duration: 100 ms Memory Size: 128 MB Max Memory Used: 72 MB Init Duration: 196.79 ms

参考

aws.amazon.com

Lambda は、ストリームからレコードを読み取り、ストリームレコードを含むイベントを使用して関数を同期的に呼び出します。Lambda は、バッチ単位でレコードを読み取り、関数を呼び出してバッチからレコードを処理します。

例 DynamoDB ストリーム レコードイベント

{
  "Records": [
    {
      "eventID": "1",
      "eventVersion": "1.0",
      "dynamodb": {
        "Keys": {
          "Id": {
            "N": "101"
          }
        },
        "NewImage": {
          "Message": {
            "S": "New item!"
          },
          "Id": {
            "N": "101"
          }
        },
        "StreamViewType": "NEW_AND_OLD_IMAGES",
        "SequenceNumber": "111",
        "SizeBytes": 26
      },
      "awsRegion": "us-west-2",
      "eventName": "INSERT",
      "eventSourceARN": eventsourcearn,
      "eventSource": "aws:dynamodb"
    },
    {
      "eventID": "2",
      "eventVersion": "1.0",
      "dynamodb": {
        "OldImage": {
          "Message": {
            "S": "New item!"
          },
          "Id": {
            "N": "101"
          }
        },
        "SequenceNumber": "222",
        "Keys": {
          "Id": {
            "N": "101"
          }
        },
        "SizeBytes": 59,
        "NewImage": {
          "Message": {
            "S": "This item has changed"
          },
          "Id": {
            "N": "101"
          }
        },
        "StreamViewType": "NEW_AND_OLD_IMAGES"
      },
      "awsRegion": "us-west-2",
      "eventName": "MODIFY",
      "eventSourceARN": sourcearn,
      "eventSource": "aws:dynamodb"
    }

Lambda は、レコードの DynamoDB ストリーム ストリームにあるシャードを 1 秒あたり 4 回の基本レートでポーリングします。レコードが利用可能になると、Lambda は関数を呼び出し、結果を待機します。処理が成功すると、Lambda は、レコードをさらに受け取るまでポーリングを再開します。

AWS Lambda を Amazon DynamoDB に使用する - AWS Lambda

Node.js
次の例では、DynamoDB からメッセージを処理し、その内容をログ記録します。

例 ProcessDynamoDBStream.js

console.log('Loading function');

exports.lambda_handler = function(event, context, callback) {
    console.log(JSON.stringify(event, null, 2));
    event.Records.forEach(function(record) {
        console.log(record.eventID);
        console.log(record.eventName);
        console.log('DynamoDB Record: %j', record.dynamodb);
    });
    callback(null, "message"); 
};

サンプルコードを圧縮してデプロイパッケージを作成します。手順については、「Node.js の AWS Lambda デプロイパッケージ」を参照してください。

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/with-ddb-create-package.html:tit;e

DynamoDB の AWS 管理 CMK のキーポリシー

  • aws/dynamodb のキーIDを確認
$ aws kms list-aliases|jq -r '.Aliases[]|select(.AliasName=="alias/aws/dynamodb")'
{
  "AliasArn": "arn:aws:kms:ap-northeast-1:123456780123:alias/aws/dynamodb",
  "AliasName": "alias/aws/dynamodb",
  "TargetKeyId": "9d******-****-****-****-*********ee"
}
  • キーIDからキーポリシーを確認
$ aws kms get-key-policy --key-id 9d******-****-****-****-*********ee --policy-name default|perl -pe 's/\\"/"/g;s/\\n/\n/g'
{
    "Policy": "{
  "Version" : "2012-10-17",
  "Id" : "auto-dynamodb-1",
  "Statement" : [ {
    "Sid" : "Allow access through Amazon DynamoDB for all principals in the account that are authorized to use Amazon DynamoDB",
    "Effect" : "Allow",
    "Principal" : {
      "AWS" : "*"
    },
    "Action" : [ "kms:Encrypt", "kms:Decrypt", "kms:ReEncrypt*", "kms:GenerateDataKey*", "kms:CreateGrant", "kms:DescribeKey" ],
    "Resource" : "*",
    "Condition" : {
      "StringEquals" : {
        "kms:CallerAccount" : "123456780123",
        "kms:ViaService" : "dynamodb.ap-northeast-1.amazonaws.com"
      }
    }
  }, {
    "Sid" : "Allow direct access to key metadata to the account",
    "Effect" : "Allow",
    "Principal" : {
      "AWS" : "arn:aws:iam::123456780123:root"
    },
    "Action" : [ "kms:Describe*", "kms:Get*", "kms:List*", "kms:RevokeGrant" ],
    "Resource" : "*"
  }, {
    "Sid" : "Allow DynamoDB Service with service principal name dynamodb.amazonaws.com to describe the key directly",
    "Effect" : "Allow",
    "Principal" : {
      "Service" : "dynamodb.amazonaws.com"
    },
    "Action" : [ "kms:Describe*", "kms:Get*", "kms:List*" ],
    "Resource" : "*"
  } ]
}"
}

RDSのスナップショット成功を確認する

イベントサブスクリプション

RDS のスナップショット作成はイベントサブスクリプションで通知することができる。

カテゴリ RDS イベント ID 説明
作成 RDS-EVENT-0042 手動 DB スナップショットが作成されました。
Amazon RDS イベント通知の使用 - Amazon Relational Database Service
  • スナップショット取得時のメール
Event Source : db-cluster-snapshot

Identifier Link: https://console.aws.amazon.com/rds/home?region=ap-northeast-1#snapshot:engine=aurora;id=aurora-postgres107-instance-1-20191010-4

SourceId: aurora-postgres107-instance-1-20191010-4

Notification time : 2019-10-09 23:50:11.804

Message : Creating manual cluster snapshot

Event ID : http://docs.amazonwebservices.com/AmazonRDS/latest/UserGuide/USER_Events.html#RDS-EVENT-0074
  • スナップショット取得完了時のメール
Event Source : db-cluster-snapshot

Identifier Link: https://console.aws.amazon.com/rds/home?region=ap-northeast-1#snapshot:engine=aurora;id=aurora-postgres107-instance-1-20191010-4

SourceId: aurora-postgres107-instance-1-20191010-4

Notification time : 2019-10-09 23:51:14.101

Message : Manual cluster snapshot created

Event ID : http://docs.amazonwebservices.com/AmazonRDS/latest/UserGuide/USER_Events.html#RDS-EVENT-0075

AWS CLI で確認

  • Aurora PostgreSQL互換のスナップショットを取得する。まずは API 発行が成功していることを確認。
$ aws rds create-db-cluster-snapshot --db-cluster-identifier aurora-postgres107 --db-cluster-snapshot-identifier aurora-postgres107-instance-1-20191010-1
{
    "DBClusterSnapshot": {
        "Engine": "aurora-postgresql",
        "SnapshotCreateTime": "2019-10-09T23:26:38.531Z",
        "VpcId": "vpc-e...",
        "DBClusterIdentifier": "aurora-postgres107",
        "DBClusterSnapshotArn": "arn:aws:rds:ap-northeast-1:1234567890123:cluster-snapshot:aurora-postgres107-instance-1-20191010-1",
        "MasterUsername": "awsuser",
        "LicenseModel": "postgresql-license",
        "Status": "creating",
        "PercentProgress": 0,
        "DBClusterSnapshotIdentifier": "aurora-postgres107-instance-1-20191010-1",
        "KmsKeyId": "arn:aws:kms:ap-northeast-1:1234567890123:key/2ebae6df-2bf5-****-****-********996",
        "ClusterCreateTime": "2019-09-15T18:37:32.844Z",
        "StorageEncrypted": true,
        "AllocatedStorage": 1,
        "EngineVersion": "10.7",
        "SnapshotType": "manual",
        "AvailabilityZones": [
            "ap-northeast-1a",
            "ap-northeast-1c",
            "ap-northeast-1d"
        ],
        "IAMDatabaseAuthenticationEnabled": false,
        "Port": 0
    }
}
  • スナップショット取得成功を確認する。
$ aws rds describe-db-cluster-snapshots --db-cluster-identifier aurora-postgres107 --db-cluster-snapshot-identifier aurora-postgres107-instance-1-20191010-1|jq -r '.DBClusterSnapshots[]|@text "\(.DBClusterSnapshotIdentifier)\t\(.SnapshotCreateTime)\t\(.Status)\t\(.PercentProgress)"'
aurora-postgres107-instance-1-20191010-1	2019-10-09T23:26:38.531Z	creating	0 ★作成中
$ aws rds describe-db-cluster-snapshots --db-cluster-identifier aurora-postgres107 --db-cluster-snapshot-identifier aurora-postgres107-instance-1-20191010-1|jq -r '.DBClusterSnapshots[]|@text "\(.DBClusterSnapshotIdentifier)\t\(.SnapshotCreateTime)\t\(.Status)\t\(.PercentProgress)"'
aurora-postgres107-instance-1-20191010-1	2019-10-09T23:26:38.531Z	available	100 ★完了

CLoudWatch Logs のロググループを S3 にエクスポートする

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "logs.ap-northeast-1.amazonaws.com"
            },
            "Action": "s3:GetBucketAcl",
            "Resource": "arn:aws:s3:::exp-cloudwatchlogs"
        },
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "logs.ap-northeast-1.amazonaws.com"
            },
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::exp-cloudwatchlogs/*",
            "Condition": {
                "StringEquals": {
                    "s3:x-amz-acl": "bucket-owner-full-control"
                }
            }
        }
    ]
}
  • CloudWatch Logs でロググループを指定して、[データをAmazon S3にエクスポート]を選択する。

  • 期間とエクスポート先のS3バケットを選択して、エクスポートする。