«前の日記(2015-07-15 (Wed)) 最新 次の日記(2015-08-04 (Tue))» 編集

雑記帳


2015-07-22 (Wed) [長年日記]

[AWS] AWS CLIではじめるVPC Flow Logs

VPC内の通信のログを取ることができる、VPC Flow Logsを使ってみたいという要望があったので、設定してみる。

まずは、ドキュメントを参照する。

ドキュメントによると、ログ自体はCloudWatch Logsに格納されるようになっており、それに対するアクセス権限は、IAM Roleを使って管理をするようだ。

ということで、設定してみる。

AWS CLIの確認

AWS CLIがVPC Flow Logsに対応したのは、1.7.33である。手元のAWS CLIのバージョンを確認する。

% aws --version
aws-cli/1.7.39 Python/2.7.6 Darwin/14.4.0

1.7.39は現時点の最新版なので、VPC Flow Logsは使えるようになっている。

% aws ec2 help |grep flow
       o create-flow-logs
       o delete-flow-logs
       o describe-flow-logs

AWS CLIの準備はできているので、次に進む。

IAM Roleの作成

VPC Flow Logsでは、IAM Roleを割り当てる必要があるので、まずはIAM Roleを作成する。

ところで、AWS Management ConsoleでしかIAMを触ったことがない向きは、ぜひ一度はAWS CLIで作成してみることをお勧めする。その理由は、AWS Management Consoleは簡単に扱えるようにするため、詳細を結構隠蔽しているからだ。

IAM RoleをVPC Flow Logsで使えるようにするには、下記のステップを踏まないといけない。

  • Assume Role Policy Documentを用意する
  • IAM Roleを作成する
  • Instance Profileを作成する
  • IAM RoleとInstance Profileを関連付ける
  • PolicyをRoleに関連付ける

順番に見ていこう。

Assume Role Policy Documentを用意する

作成するIAM Roleの種類はvpc-flow-logsとなるため、下記のAssume Role Policy Documentを使う。

{
  "Version": "2012-10-17",
    "Statement": {
      "Effect": "Allow",
      "Principal": {
        "Service": "vpc-flow-logs.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
}
IAM Roleを作成する

create-roleを実行する際に、このポリシーを設定する。

% aws iam create-role --role-name flowlogs \
  --assume-role-policy-document '{"Version": "2012-10-17","Statement":{"Effect": "Allow","Principal":{"Service":"vpc-flow-logs.amazonaws.com"},"Action":"sts:AssumeRole"}}'

実行が成功すると、下記のような結果が返る。

{
  "Role": {
    "AssumeRolePolicyDocument": {
      "Version": "2012-10-17",
        "Statement": {
          "Action": "sts:AssumeRole",
          "Effect": "Allow",
          "Principal": {
            "Service": "vpc-flow-logs.amazonaws.com"
          }
        }
    },
      "RoleId": "xxxxxxxxxxxxxxxxxxxxx",
      "CreateDate": "2015-07-21T09:44:40.192Z",
      "RoleName": "flowlogs",
      "Path": "/",
      "Arn": "arn:aws:iam::000000000000:role/flowlogs"
  }
}
Instance Profileを作成する

これは余談だが、AWS Management Consoleを使っていると、Instance Profileについて意識する必要はない。AWS Management Consoleは、Instance Profileを独立したリソースとして扱わないからだ。EC2を対象としたIAM Roleの情報を表示すると、Instance ProfileのARNが表示されるのか確認できる。

AWS Management Consoleは、IAM RoleとInstance Profileを同時に取り扱う(ライフタイムが同一となる)。また、全く同じ名前であることを前提としているようなので注意が必要となる。APIでは個別に取り扱うことができるのだが、IAM RoleとInstance Profileが別の名前になっていると、AWS Management Console上では、IAM Roleを削除したりできなくなってしまう。そういった場合は、AWS CLIなどを使って、直接APIを使わないといけない。

ということで、Instance Profileを作成する。前述のような問題があるため、IAM Roleと全く同じ名前で作成する。

% aws iam create-instance-profile --instance-profile-name flowlogs

作成に成功すると、下記のような結果が返る。

{
    "InstanceProfile": {
        "InstanceProfileId": "xxxxxxxxxxxxxxxxxxxxx",
        "Roles": [],
        "CreateDate": "2015-07-21T10:13:30.953Z",
        "InstanceProfileName": "flowlogs",
        "Path": "/",
        "Arn": "arn:aws:iam::000000000000:instance-profile/flowlogs"
    }
}
IAM RoleとInstance Profileを関連付ける

IAM RoleとInstance Profileができたので、それぞれ関連付ける。

% aws iam add-role-to-instance-profile --instance-profile-name flowlogs --role-name flowlogs

成功した場合は、特に何も表示されない。

PolicyをRoleに関連付ける

VPC Flow Logsが、CloudWatch Logsにアクセスのに必要な権限を付与する。ドキュメントに記載のある権限を付与すれば良い。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents",
        "logs:DescribeLogGroups",
        "logs:DescribeLogStreams"
      ],
      "Effect": "Allow",
      "Resource": "*"
    }
  ]
}

ポリシーを付与する。

% aws iam put-role-policy --role-name flowlogs --policy-name flowlogs --policy-document '{ "Version": "2012-10-17", "Statement": [ { "Action": [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents", "logs:DescribeLogGroups", "logs:DescribeLogStreams" ], "Effect": "Allow", "Resource": "*" } ] }'

こちらも、成功した場合はなにも出力されない。

以上で、IAM Roleの設定が完了した。ちなみに、AWS Management Consoleを使った場合は、VPC Flow Logsを作成するときに、この辺りの設定をまとめてやってくれるようになっている。

CloudWatch Logsのグループを作成する

VPC Flow Logsの出力先となる、CloudWatch Logsのグループを作成する。

% aws logs create-log-group --log-group-name flow-logs

成功した場合の出力はない。結果を確認する。

% aws logs describe-log-groups
{
    "logGroups": [
        {
            "arn": "arn:aws:logs:ap-northeast-1:000000000000:log-group:flow-logs:*",
            "creationTime": 1437472183580,
            "metricFilterCount": 0,
            "logGroupName": "flow-logs",
            "storedBytes": 0
        }
    ]
}
VPC Flow Logsの作成

仕上げに、VPC Flow Logsを作成する。

% aws --profile iret ec2 create-flow-logs \
  --resource-ids vpc-deadbeaf \
  --resource-type VPC \
  --traffic-type ALL \
  --log-group-name flow-logs \
  --deliver-logs-permission-arn arn:aws:iam::000000000000:role/flowlogs

ここでは、対象をVPC全体とし、VPC IDをパラメータに渡している。d

--resource-typeをVPCとしている。対象はVPCだけでなく、Elastic Network Interface (ENI) にしたり、Subnetにしたりできる。

--traffic-typeは、ロギング対象となるトラフィックの種類を指定する。ACCEPT, REJECT, ALLがしていできる。ここではALLとしている。

ちなみに、--traffic-typeと--resource-typeは、ともにすべて大文字でないと失敗するようだ。

--deliver-logs-permission-arnは、分かりづらいが、先ほど作成したIAM RoleのARNを指定する。

実行した結果は、以下のような出力が得られる。

{

   "Unsuccessful": [],
   "FlowLogIds": [
       "fl-deadbeaf"
   ],
   "ClientToken": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

}

失敗した場合は、Unsuccessfulに理由が入るようだ。今回は何も含まれていないので、成功したということになる。

Log Streamsの確認

これで準備ができたので、あとはログが取得できるようになる。設定した直後はすぐにデータが流れてこないかと思うが、数分待てば出てくると思う。

先ほどは、Log Groupしか作成していないが、VPC Flow Logsが自動的にLog Streamを作成して、そこにログが入るようだ。ということで、Log Streamの確認をする。

% aws --profile iret logs describe-log-streams --log-group-name flow-logs

--log-group-nameに、作成したLog Groupの名前を渡す。Log Streamができていれば、下記のような出力になる。

{
    "logStreams": [
        {
            "firstEventTimestamp": 1437533334000,
            "lastEventTimestamp": 1437533881000,
            "creationTime": 1437533963999,
            "uploadSequenceToken": "49545657805925472387080468314713352704393428876698583762",
            "logStreamName": "eni-deadbeaf-all",
            "lastIngestionTime": 1437533964445,
            "arn": "arn:aws:logs:ap-northeast-1:000000000000:log-group:flow-logs:log-stream:eni-0081af59-all",
            "storedBytes": 0
        },
        {
            "firstEventTimestamp": 1437533370000,
            "lastEventTimestamp": 1437533854000,
            "creationTime": 1437534000225,
            "uploadSequenceToken": "49545657805657863444698057630133068269334483145861366802",
            "logStreamName": "eni-baadf00d-all",
            "lastIngestionTime": 1437534000659,
            "arn": "arn:aws:logs:ap-northeast-1:000000000000:log-group:flow-logs:log-stream:eni-04833872-all",
            "storedBytes": 0
        },
...

LogStreamNameを見ると、ENI単位でLog Streamが作成され、ログが格納されるようだ。実際に格納されているログを見てみよう。

% aws logs get-log-events --log-group-name flow-logs --log-stream-name eni-deadbeaf-all --limit 1
{
    "nextForwardToken": "f/32058076794435842183738125314793503818359848154310770799",
    "events": [
        {
            "ingestionTime": 1437533964445,
            "timestamp": 1437533881000,
            "message": "2 000000000000 eni-deadbeaf 10.0.2.7 10.0.132.91 59163 3306 6 29 2438 1437533881 1437533932 ACCEPT OK"
        }
    ],
    "nextBackwardToken": "b/32058076794435842183738125314793503818359848154310770799"
}

--limit 1として、一行だけ取得している。messageの部分に、スペース区切りでログが出力されている。それぞれの値の意味は、version, account-id, interface-id, srcaddr, dstaddr, srcport, dstport, protocol, packets, bytes, start, end, action, log-statusとなる。

このログは、FlowLogs version 2が取得したデータで、AWSアカウント000000000000の、eni-deadbeafにおいて、10.0.2.7から10.0.132.91に、ポート59163から、3306ポートに、TCPで、29パケット、2438 byets, UNIX Timeで、1437533881 から 1437533932 までの間に送信され、ACCEPTされた。ログの取得も成功した、ということが示されている。実際のデータの中身については記録されていない。

詳細は、ドキュメントを参照のこと。

ENIのリストを見ていて気がついたのだが、EC2はもとより、RDS、ELB、Directory Service、WorkspacesなどもENIがあるため、ログが取得できるようだ。

まとめ

VPC Flow Logsを使うと、VPC内にあるEC2だけでなく、ENIが存在しているサービスすべてについて、ログを取得することができるので、とても便利だ。特に、REJECTのログも取得できるので、セキュリティグループでブロックされた通信の状態をみれる。トラブルシュートが捗ると思われる。