運用自動化に向けて行ったこと
実運用にあたって、ネットワーク構成図の作成と更新に加え、CloudMapper自体のバージョンアップ反映もすべて自動化することにしました。
-
ネットワーク構成図の更新
- CloudMapperは起動時に最新の情報を取得して構成図を更新するため、毎朝7時に再起動するようにした
- 再起動処理は、CloudWatch Events -> Lambdaで実装
-
CloudMapperのバージョンアップや設定変更の反映
- 公式サイトのセットアップ手順を参考にしてDockerfileやentrypoint.shを作成し、これらのファイルをGitHubのリポジトリで管理
- ECS上でサービスとして稼働させた。ECSに関するAWSのリソースはTerraformでコード化しGitHubのリポジトリで管理
- CodePipelineを利用し、GitHubのmasterにコミットがあったら、Docker Imageをbuildし、ECSのサービスにdeployを行うように設定
これにより、ネットワーク構成図が毎日最新化されるのに加え、CloudMapperのバージョンアップや、情報取得対象のAWSのアカウント追加があった場合も、設定ファイルをコミットするだけで自動反映されるようになりました。
セキュリティとコスト上の工夫
nginxによるアクセス制御
CloudMapperへのアクセスは社内のみに制限していましたが、それだけでは社内の誰でも参照できてしまうのでアクセス制限をかける必要がありました。CloudMapper自体にはユーザー管理や権限制御の機能はなかったため、CloudMapperとALBの間にnginxを挟み、Basic認証を入れるようにしました。
AWSアカウントごとの制御と、コスト節約のためのECSサービス化
担当しているサービスでは複数のAWSアカウント(本番、検証など)を管理しており、これらすべてのアカウントでCloudMapperを利用するにあたり、閲覧制限をアカウント単位でかける必要がありました。このため、アカウント別にCloudMapperを構築することで、アカウント単位での閲覧制限をかけられるようにしました。しかし、アカウントの数だけECSのサービスを構築すると金銭的なコストもかかるため、サービスとしては1つ、タスク側でアカウント単位のコンテナを構築しました。また、1つのサービスで複数のCloudMapperにリクエストを分散させるため、nginxのproxyを利用しました。
{
"name": "sandbox", #sandboxサービス
"image": "xxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/cloudmapper:latest",
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/aws/ecs/task/cloudmapper",
"awslogs-region": "ap-northeast-1"
}
},
"memory": 512,
"portMappings": [
{
"hostPort": 8010,
"containerPort": 8000,
"protocol": "tcp"
}
],
"environment": [
{
"name": "ACCOUNT",
"value": "sandbox"
},
{
"name": "AWS_DEFAULT_REGION",
"value": "ap-northeast-1"
},
{
"name": "AWS_REGION",
"value": "ap-northeast-1"
}
],
"essential": true
},
{
"name": "sandbox-us", #sandbox-usサービス
"image": "xxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/cloudmapper:latest",
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/aws/ecs/task/cloudmapper",
"awslogs-region": "ap-northeast-1"
}
},
"memory": 512,
"portMappings": [
{
"hostPort": 8020,
"containerPort": 8000,
"protocol": "tcp"
}
],
"environment": [
{
"name": "ACCOUNT",
"value": "sandbox-us"
},
{
"name": "AWS_DEFAULT_REGION",
"value": "us-east-1"
},
{
"name": "AWS_REGION",
"value": "us-east-1"
}
],
"essential": true
},
{
"name": "cloudmapper-nginx-proxy",
"image": "xxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/cloudmapper-nginx-proxy:latest",
"links": ["sandbox", "sandbox-us"],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/aws/ecs/task/cloudmapper-nginx-proxy",
"awslogs-region": "ap-northeast-1"
}
},
"memory": 256,
"portMappings": [
{
"hostPort": 0,
"containerPort": 80,
"protocol": "tcp"
}
],
"environment": [
{
"name": "SANDBOX",
"value": "sandbox:8000"
},
{
"name": "SANDBOX_US",
"value": "sandbox-us:8000"
}
],
"essential": true
}
location /sandbox {
# for sandbox
auth_basic "Welcome to sandbox";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_set_header Host ${DOLLAR}host;
proxy_set_header X-Real-IP ${DOLLAR}remote_addr;
proxy_set_header X-Forwarded-For ${DOLLAR}proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto ${DOLLAR}scheme;
proxy_set_header X-Forwarded-Host ${DOLLAR}http_host;
proxy_pass http://${SANDBOX}/;
}
