「NATゲートウェイ」をAWSマネジメントコンソールから構築すると何が起きるか

NATゲートウェイ

概要

NAT GatewayAWS のフルマネージド NAT(ネットワークアドレス変換)サービスである。自前でNATインスタンスをオモリする必要がないのがウリ。控えめに言えば、最高である。詳細は、公式ドキュメントを参照する。

構築手順

おおまかに3つのリソースの作成・変更が必要である。

  1. EIPの作成
  2. NATゲートウェイの作成
  3. ルートテーブルの変更
続きを読む

SlackのGitHub連携の手順

通知したいチャンネルで、Slackのスラッシュコマンドを叩いて、通知設定を行う。

Sign in

Sign in しておかないと、GitHubと連携できない。最初、コレに気づかずハマった。

/github signin

すると、こんなボタンが出てくるのでクリック。

f:id:tmknom:20180812132503p:plain

で、接続が完了したらこんな感じで表示される。

f:id:tmknom:20180812132517p:plain

Subscribe

プルリクエストのコメントも含めて通知するには、明示的にオプションを指定しないといけない

/github subscribe <your_org>/<repo_name> reviews comments

こんなのデフォルトで有効にしといてよって気持ちだが、公式がそうなっているので仕方がない。

get.slack.help

最初コメントが通知されず、しばらく悩んだ。

Help

基本的にこれだけ知ってれば十分だが、ヘルプも用意されている。

/github help

なにか困ったことがあったら、とりあえず見てみよう。

coinbase/assume-role でシュッと多要素認証を突破して、マルチアカウント環境で快適にTerraformライフを送る

なにこれ?

CLIコンソールで、AWSのIAMユーザの多要素認証(MFA)を簡単に実行できる。

背景

Terraform 単体だと、多要素認証したうえで AssumeRole することができない。terraform-provider-aws リポジトリIssue も立てられているが、しばらく対応予定はないらしい。

At this time we do not have plans to support interactive authentication to providers since it would require some significant changes to the provider model.

とはいえ、AWS Organizationsなどを使って、マルチアカウント管理する環境だと、これでは困る。そんなわけで、coinbase/assume-roleの出番である。

続きを読む

IntelliJが「Not a valid command: idea-shell (similar: shell)」とか言って死ぬ

そのときは突然に

突然IntelliJさんがエラーを吐くようになった。何もしてないのに!

[error] Not a valid command: idea-shell (similar: shell)
[error] Not a valid project ID: idea-shell
[error] Expected ':' (if selecting a configuration)
[error] Not a valid key: idea-shell (similar: daemon-shell, daemonShell)
[error] idea-shell
[error]

いや、よく考えたら何もしてないわけじゃなかった。build.sbtを変更し、おなじみの↓が出たので、「Refresh project」押したらエラー吐いて死んだのだ。

f:id:tmknom:20180812133609p:plain

ググると同じ症状の人いた。

なんか、sbtのバージョンを上げ下げしろ!って言ってる。

I downgraded my project SBT Version from 0.13.16 to 0.13.15 and it all work fines. 

And if I upgrade up to 0.13.16 again it all works for fine.

マジかよ…って半信半疑ながらproject/build.propertiesを修正して、sbtのバージョンを0.13.15から0.13.16に変更してみた。

こいつ… 動くぞ…!

一応、0.13.16から0.13.15に戻してもう一回動かしてみる。

……動いた。マジかよ。意味わかんねーよ。キモすぎだよ。

結論

IntelliJが「Not a valid command: idea-shell (similar: shell)」ってエラーが出たら、何も考えずsbtのバージョンを変更しろ!

一回変更して、無事動作したら、(たぶん)sbtのバージョンを元に戻しても大丈夫。

最もシンプルに「macOS High Sierra」をクリーンインストールする全手順

f:id:tmknom:20180429180639j:plain

Macクリーンインストールしたのでその全手順を公開する。 コンセプトは、極力余計な設定は入れないである。後追いで可能な、Apple IDの入力や、各種設定は全部スキップする。

続きを読む

terraformのaws_default_network_aclリソースを素人が安易に使ってはいけない

最初組み込んでたんだけど、調べてみるとなんかキワイ。

公式ドキュメント

カッコ書きは、Google翻訳を使いながら、適当に翻訳したものである。(残念英語力なので、間違ってたらゴメンね

https://www.terraform.io/docs/providers/aws/r/default_network_acl.html

概要

Each VPC created in AWS comes with a Default Network ACL that can be managed, but not destroyed. This is an advanced resource, and has special caveats to be aware of when using it. Please read this document in its entirety before using this resource.

AWSで作成された各VPCには、管理可能なデフォルトネットワークACLがありますが、削除することはできません。 これは高度なリソースであり、使用時に注意すべき特別な注意点があります。 このリソースを使用する前に、この文書全体をお読みください。」

にじみ出る玄人向け感。初っ端から、初心者お断りオーラ出してきてる。

The aws_default_network_acl behaves differently from normal resources, in that Terraform does not create this resource, but instead attempts to "adopt" it into management.

aws_default_network_aclは通常のリソースとは異なる動作をします。Terraformは、aws_default_network_aclはこのリソースを作成せず、その代わりに管理下に置くことを試みます。」

繰り返される、aws_default_network_acl氏による、オレは特別だぞアピール

When Terraform first adopts the Default Network ACL, it immediately removes all rules in the ACL. It then proceeds to create any rules specified in the configuration.

「Terraformはまず、デフォルトネットワークACLすべてのルールを直ちに削除します 。 次に、設定されたルールを組み込みます。」

デフォルトのネットワーク ACLって影響が甚大なのに、なんとも思い切った動きをしやがる。か、漢だ…。

This resource treats its inline rules as absolute; only the rules defined inline are created, and any additions/removals external to this resource will result in diffs being shown. For these reasons, this resource is incompatible with the aws_network_acl_rule resource.

「このリソースは、そのインラインルールを絶対のものとして扱います。 インラインで定義されたルールのみが作成され、このリソースの外部で追加/削除が行われると、差分が表示されます。 これらの理由から、このリソースはaws_network_acl_ruleリソースと互換性がありません。」

漢は黙ってインライン定義のaws_default_network_aclパイセンの、aws_network_acl_ruleとは違いますからアピール。そろそろウゼーな、コイツ

デフォルトネットワークACLでのサブネット管理

Within a VPC, all Subnets must be associated with a Network ACL. In order to "delete" the association between a Subnet and a non-default Network ACL, the association is destroyed by replacing it with an association between the Subnet and the Default ACL instead.

VPC内では、すべてのサブネットをネットワークACLに関連付ける必要があります。 サブネットとデフォルト以外のネットワークACLとの関連付けを「削除」すると、サブネットの関連付けはデフォルトACLと差し替えられ、もとの関連付けが破棄されます。」

AWSの仕様上、すべてのサブネットはネットワークACLに紐付けないといけないから、関連付けが明示されないサブネットは、暗黙的にデフォルトネットワークACLに紐付けられるっぽい。そりゃ、そうかって感じである。

When managing the Default Network ACL, you cannot "remove" Subnets. Instead, they must be reassigned to another Network ACL, or the Subnet itself must be destroyed. Because of these requirements, removing the subnet_ids attribute from the configuration of a aws_default_network_acl resource may result in a reoccurring plan, until the Subnets are reassigned to another Network ACL or are destroyed.

「デフォルトネットワークACLを管理する場合、サブネットを「削除」することはできません。 別のネットワークACLに改めて関連付けるか、サブネット自体を破棄する必要があります。 これらの要件のため、subnet_ids属性をaws_default_network_aclリソースの設定から削除すると、サブネットが別のネットワークACLに再度関連付けられるか破棄されるまで、 繰り返し差分が出る可能性があります。」

なんつーか、スッゲーじゃじゃ馬感あるな、コイツ

aws_default_network_acl の設定を削除する

Each AWS VPC comes with a Default Network ACL that cannot be deleted. The aws_default_network_acl allows you to manage this Network ACL, but Terraform cannot destroy it. Removing this resource from your configuration will remove it from your statefile and management, but will not destroy the Network ACL. All Subnets associations and ingress or egress rules will be left as they are at the time of removal. You can resume managing them via the AWS Console.

「各VPCには、削除不可のデフォルトネットワークACLが紐付いている。 aws_default_network_acl を使用すると、このネットワークACLを管理できますが、Terraformは削除までは行なえません。 このリソースを設定から削除すると、stateファイルから削除され、管理下からは外れますが、ネットワークACLは破棄されません。 すべてのサブネットの関連付けとインバウンド/アウトバウンドのルールは、削除時のまま残ります。 その後も、AWS コンソールで管理を再開することができます。」

仕様上、デフォルトネットワークACLの削除はできないから、こんな振る舞いになるらしい。分かるっちゃあ、分かるけど、なんとも微妙な振る舞いである

結論

aws_default_network_aclはterraform上の挙動が複雑なので、安易に使わないほうが良さげ。そもそも、ネットワークACL自体が、AWSでは制約が大きく扱いが難しい。

ネットワークACLの設定を変更したい場合は、aws_network_aclリソースを使って、別途ネットワークACLを定義する。ちゃんと検証してないが、おそらく意図したとおりに動くと思う。少なくとも、aws_default_network_aclよりはマシな挙動をするはずだ。

Terraformのバックエンド用のS3バケットは、Terraformで管理してはいけない

新規にAWSアカウントを取得するにあたって、極力AWSリソースの管理はterraformに寄せようと思ったのだが、ふとterraformのtfstateファイルを置くS3は、terraform管理していいのか気になった。ので、調べてみた。

公式ソース

結論としてはタイトルどおりなわけだが、公式に言及されていた。

www.terraform.io

Terraform is an administrative tool that manages your infrastructure, and so ideally the infrastructure that is used by Terraform should exist outside of the infrastructure that Terraform manages.

雑にGoogle翻訳してみる。

Terraformはインフラストラクチャを管理する管理ツールです。したがって、Terraformで使用されるインフラストラクチャは、Terraformが管理するインフラストラクチャの外部に存在する必要があります。

というわけで、Terraformのバックエンド用のS3バケットを、Terraformの管理対象にするのはやめたほうがよさそう。

さらに読み進めると、次のように書いてある。

This can be achieved by creating a separate administrative AWS account which contains the user accounts used by human operators and any infrastructure and tools used to manage the the other accounts.

雑にGoogle翻訳してみる。

これは、人間のオペレータが使用するユーザアカウントと、他のアカウントを管理するために使用されるインフラストラクチャとツールを含む別の管理 AWSアカウントを作成することで実現できます。

Terraformのバックエンド用のS3バケットの管理をするためのアカウントを作れと言っている。AWS Organizationsと組み合わせればできそうである。

雑にS3バケットを作成する

AWS Organizationsを使えばできそうだが、それすらメンドウなら、雑にS3バケットを作ろう。もちろん、AWSコンソールから作ってもいいのだが、AWSアカウントを取得するたびにやることになるので、シェルスクリプト化しておく。

なお、これを動かすためには、事前にAWS CLIはインストールする必要がある。

#!/bin/sh

set -ex

BUCKET_NAME=$1
LEGION=${2:-ap-northeast-1}

# バケットの作成
# リージョンを指定しないとエラーになるので明示的に指定している
# https://dev.classmethod.jp/cloud/aws/jaws-ug-cli-1/
aws s3api create-bucket --bucket $BUCKET_NAME --create-bucket-configuration LocationConstraint=$LEGION

# バケットのバージョニング設定
# 何かやらかしたときに、復元できるようにしておく
aws s3api put-bucket-versioning --bucket $BUCKET_NAME --versioning-configuration Status=Enabled

# バケットのデフォルト暗号化設定
# http://tech.withsin.net/2017/12/05/s3-bucket-encryption/
aws s3api put-bucket-encryption --bucket $BUCKET_NAME --server-side-encryption-configuration '{
  "Rules": [
    {
      "ApplyServerSideEncryptionByDefault": {
        "SSEAlgorithm": "AES256"
      }
    }
  ]
}'

aws s3api get-bucket-location --bucket $BUCKET_NAME
aws s3api get-bucket-versioning --bucket $BUCKET_NAME
aws s3api get-bucket-encryption --bucket $BUCKET_NAME

適当にinit_terraform_bucket.shとかってファイルに保存して実行する。

./init_terraform_bucket.sh my-cloudtrail-bucket

これで、毎回ポチポチしなくても済むようになった。