Vault の OpenStack 認証プラグイン
OpenStack インスタンスから Vault に保管されているシークレットを直接取り出すための認証プラグイン vault-plugin-auth-openstack を実装した。
このプラグインを使えば、Vault の GCP 認証 や AWS 認証 などと同様に、OpenStack インスタンスから直接 Vault で認証してシークレットの取得が可能になる。
プラグインの実装にあたって、OpenStack インスタンスをどのように認証するのかが問題になった。 OpenStack には、GCP や AWS にあるようなインスタンス固有の署名付きトークンなどを発行する仕組みが無いため、それに依存しない形でインスタンス認証をしなければならない。そこで今回はインスタンスが持つ複数の情報を組み合わせて、リスクを段階的に抑えて認証をするような実装とした。
このプラグインでは、まずインスタンスの認証に OpenStack インスタンス起動時にランダムに割り当てられる識別子である「インスタンス ID」を使用する。プラグインはインスタンス ID を受け取ると、OpenStack API に問い合わせてインスタンスの存在を確認する。もしインスタンスが存在しなければ、認証に失敗する。なお、インスタンスの内部では OpenStack Metadata Server や Config Drive を通じてインスタンス ID が取得できる。
インスタンス ID はただのランダムな UUID なので、このままではインスタンス ID が漏洩するとそのインスタンスになりすましての認証が可能になってしまう。そこで、プラグインではさらに認証時の要求元 IP アドレスと OpenStack インスタンスに付与された IP アドレスが一致しているかを検証することとした。もし無関係な IP アドレスから認証を要求した場合は、インスタンス ID が存在していても認証に失敗する。Vault とインスタンスの間にゲートウェイや NAT ルーターが存在するようなケースは、今のところサポートしていない。
残念ながら IP アドレスの検証をしても、IP アドレスが偽装されたら認証ができてしまう。そこで、Vault の Cubbyhole のように認証回数と認証時間に制限をかけられるようにした。認証時間はインスタンスが作成された時間からの秒数で指定できる。例えば、あるインスタンスは作成から60秒以内に3回まで認証できる、といったように設定できる。認証時間を短く、また回数を少なくすればそれだけリスクを抑えられる。
こうして段階的に制約をかけることで、Vault で OpenStack インスタンスの認証が可能になった。さらに制約をかけられる要素が見つかれば、追加で実装したいと思う。なお、AWS や GCP を使っている場合と同じように、OpenStack へのアクセス権限を持つユーザーであれば、いくら制約をかけても認証できてしまうので、OpenStack そのものの権限は注意深く管理する必要がある。
先日リリースされた Vault 0.10.4 からは、JWT による認証が可能になった。もし OpenStack の機能に直接手を入れられるのであればインスタンス起動時に署名付きの JWT を発行して付与し、それを使ってインスタンスが認証できる仕組みにするのもいいかもしれない。