サーバレスなDBクエリクライアントを作った

# 何を作ったか

# What

簡単にいうと以下のようなアーキテクチャでサーバレスでDBにクエリできるクライアントを作った

+------------------------+            +--------------------------+          +-------------------------+
|                        |  invoke    |                          |  query   |                         |
|                        |            |                          |          |                         |
|                        +----------->+                          +---------->                         |
|      lambda-query      |            |       lambda function    |          |          RDS            |
|                        |            |                          |          |                         |
|                        <------------+                          +<---------+                         |
|                        |            |                          |          |                         |
+------------------------+  result    +--------------------------+  result  +-------------------------+

# 出来ること

  • Lambda経由でのサーバレスでのDBへのクエリ発行とその結果の取得, フォーマット

    • CSVまたはテーブル形式での出力サポート
    • ファイル出力もしくは標準出力サポート
    • タイムアウト設定でロングランニングクエリ可
    • 数百万件などのデータexportも可(内部的にクエリをoffsetで分割する)

e.g.

$ lambda-query -f function_name \
  -q "select * from users" \
  --limit 10000 -t 120 --format csv
  --output result.csv

以下に作ったモチベーションなど

# Motivation

結論から言うと踏み台というソリューションを無くすことができないかというモチベーションを元に作った

というのはプロジェクトを進めて佳境に入ってくると大抵セキュリティ監査を受けたりセキュリティについて見直す機会が出てくるのだけど、そういった時に踏み台のようなものがあると割と問題になることが多いのだ

踏み台というのはシステムへの唯一の入り口であり堅牢化が必要なところではあるが通常そういったインスタンスは何らかのOSを持つサーバでありそうするとユーザ管理、Permission管理、鍵管理、実行可能コマンド等かなり管理するべき項目が多く堅牢化のためにコストがとてもかかってくる

# なぜ踏み台が必要だったのか?

そこで考えたのがそもそも踏み台のような状態を持ったインスタンスが必要なのはなぜか?ということで改めて考えてみると

  • 構成変更
  • インシデント調査
  • クエリ実行

といったオペレーションでの必要性でしかほぼ使うことはなく、また構成変更、インシデント調査に関しては既に各種IaC支援環境(Terrafor, CloudFormation, Ansible, Chef...etc)やログ管理SaaS環境(CloudWatch等)は十分出揃っているためサーバレスで十分オペレーションできるレベルになっており、実質クエリ実行ぐらいでしか近年の(ある程度IaC化された)インフラ環境では使っていないのだ

そこでクエリ実行さえサーバレスで実行出来れば完全サーバレスでのオペレーションが実現出来るだろうという考えのもとシステムHardeningを実現するためlambda-query (opens new window)を作った

# ナイーブなソリューション

それでも我々が未だに踏み台という文化から完全に逃れられないのはそれがナイーブだけどリスク受容しつつも日々のオペレーションを実行するためにある程度実用的というのがある

結局はセキュリティ上のリスクと利便性とのトレードオフというところはあるが、運用コストとリスクを勘案した結果ナイーブなソリューションを選択してしまうことがよくある

そういった選択をしてしまうのは得てしてリスクと運用コストを過小評価してしまうからで次第に運用コストの増大とセキュリティリスクの増加の曲線が利便性の曲線を追い越してしまう

画像

以下でそれぞれのオペレーションについて本当にBastionがいらないのか検討してみる

# 構成変更

まず構成変更に関してはAWS等のクラウドインフラは基本的にAPIで全て変更なため本質的にはほとんどのケースでBastionは要らない

またコンテナオーケストレーションの利用の広がりやk8sのような状態をAPIでコントロールするIaCの文脈でサーバに入って何かを行うというようなオペレーションはアンチパターンになってきており、むしろ避けるべきものになってきている。何かしらの状態をサーバに保持するということは、その状態を再現可能なコードを書かない限りサーバが滅失すると状態が再現不可になってしまうからだ

コンテナによるImmutable Infrastructureが必用なのは状態を持ったサーバは冪等性が確保できないからであり秘伝のタレでの人手の暖かみのあるデプロイがDevとOps, そしてSecの距離をお互いに遠くしてしまう

# インシデント調査

インシデント調査に関しても監査ログ, クエリログ, エラーログ, フローログ, パケットログ, 各種メトリクスなど外部ストレージに保存しておけば基本的にそれ以上調査するべきところはない。というよりはそうするべきといった方が正確かもしれない。ログは発生と同時に外部ストレージに保存するべきでログが発生した主体と同一の記憶領域に置くのは常に滅失リスクと改ざんリスクが存在する。

# クエリ実行

クエリ実行に関してはAurora Serverlessのクエリエディタ (opens new window)のように任意のクエリをRDSのWebコンソールで実行出来るソリューションも既にあり、十分優れたWeb UIとセキュリティ、モニタリングが確保出来れば本質的にはWebで問題ない

というのはDBにおけるオペレーションではクエリというInputと→クエリ結果というOutputを出力出来ることが要件でありCLIを使うのは一つのインターフェースに過ぎないからだ

# まとめ

以上のように現代のインフラオペレーションにおいてはインフラ自体を直接触らないということが一つの目標でありそのためにk8sにおける宣言的インフラの実現やIaCによるAPI経由での構成管理が進化してきた

直近でHashicorpがBoundaryを発表 (opens new window)するなど構成管理におけるセキュリティをどう確保するかというDevSecOpsの文脈でのソリューションが成熟したインフラ環境で求められてきているというのもあり、今後もセキュリティ面を確保しつつどう宣言的なDevOpsを実現するかというのは重要なテーマになると思われる

BeyondProd (opens new window)のような包括的なDevSecOpsセキュリティモデルをGoogleが発表するなどDevOpsからDevSecOpsモデルへの転換という流れは止まらなそうなので今後もその流れは注視していきたい