サイバー攻撃による個人情報の流出が多数ニュースになっている状況で、お客様に安心してサービスを利用してもらうためには防御を一層高める必要があります。今回はインフラチームが主導して、Goで書かれたサービスをセキュリティが高く安全な状態で稼働できるように改善したのでその内容を紹介します。
改善前の状況
Goで書かれたサービスをDocker公式のDebianイメージを使いGKE上で稼働させていました。このDebianイメージは長年更新されておらず、バージョンはDebian 8 (Jessie) で2020年6月にEOLを迎えています。加えて脆弱性のスキャンも行っておらず、たくさんの脆弱性が入っているイメージを使用していました。
また、PodのSecurityContextは指定しておらずデフォルトのまま稼働させていました。
distrolessへの移行
まずはコンテナのセキュリティを高めるうえで大きな効果があるdistrolessへの移行を考えました。
distrolessとは公式のGitHubで以下のように説明されています。
"Distroless" images contain only your application and its runtime dependencies. They do not contain package managers, shells or any other programs you would expect to find in a standard Linux distribution.
以下はGoogle翻訳の結果です。
「Distroless」イメージには、アプリケーションとそのランタイム依存関係のみが含まれます。パッケージマネージャー、シェル、その他標準的なLinuxディストリビューションに搭載されているプログラムは含まれていません。
ということでアプリケーションを動かすために必要な最低限のものしか含まれておらずセキュリティが高いイメージになっています。なかでもシングルバイナリで動くGo用のイメージにはほとんど何も入っていません。
基本的には言語に合わせたイメージに置き換えるだけで移行が完了しますがいくつか妨げとなるポイントがあります。
注意点
distrolessに移行するうえで注意しなければならないのはshellや一般的なコマンドが含まれていないことです。例として以下のような運用が存在している場合は代替策を用意するか移行を諦めることになります。
- コンテナに入ってコマンドを実行する
- lifecycleのpreStop等でコマンドを実行している
コンテナに入ってコマンドを実行する
日常の運用としてkubectl execを使用しているのであれば諦めたほうが無難ですが、障害時の調査が目的であればk8sの機能としてkubectl debugコマンドが使用できます。
今回のGoのサービスでは障害時の調査以外でkubectl execを使用する機会は無いので、社内のドキュメントをkubectl debugに書き換えることで対応完了としました。
lifecycleのpreStop等でコマンドを実行している
DockerのENTRYPOINTで初期化処理を実行していたり、k8sのlifecycleのpreStopでGraceful Shutdownを行っているのはよくあることだと思います。これらの処理もdistrolessだと難しくなってきます。
起動処理であればInit Containerで代替できる可能性がありますが、Graceful Shutdownをk8sの機能で代替するのは難しいためアプリケーションに実装する必要があります。
今回のGoのサービスではpreStopでGraceful Shutdownを行っていたため、アプリケーションでSIGTERMをハンドリングしてGraceful Shutdownを行うように改修を行いました。
脆弱性が見つかったらアラートする
継続的に安全なコンテナを使い続けるためには脆弱性がないか定期的に確認する必要があります。
脆弱性のスキャンに使うツールや実行するタイミングなど考慮することはいくつかありますが、今回はGCPのArtifact RegistryのArtifact Analysisを使用することにしました。
Artifact Analysisはイメージのpush時だけでなくpushしてから30日間は定期的に再スキャンされるため、リリース頻度が少ないサービスでも安定して脆弱性を見つけることができます。CI/CDに組み込むだけだとリリース後に公表された脆弱性を見つけることができないため、再スキャンを自動的に行ってくれるのはとても助かります。また、GCPのwebコンソールから脆弱性のレベルや内容、修正されたバージョンなどの詳細が確認できるのも便利です。
より厳密に行うのであれば、push時に脆弱性が見つかったらエラーにしてリリースを止めるような仕組みにするべきなのでしょうが、一般的なwebサービスではやり過ぎと判断して、アラートを検知したら可能な限り素早く修正リリースを行う方針にしました。
さらなる安全性を求めて
ここまでの対応で既知の脆弱性を狙われる可能性は低くなりましたが、未知の脆弱性やヒューマンエラーによるリスクは存在します。それらのリスクを軽減するためには多層的に防御をする必要があり、その1つとしてコンテナの権限を最小限にするという方法があります。この対応は少し複雑になるため、別の機会に共有できればと思います。
さいごに
ホワイトプラスでは、ビジョンやバリューに共感していただけるエンジニアを募集しています!
ネットクリーニングの「リネット」など、「生活領域×テクノロジー」で事業を展開しています。
弊社に興味がある方は、オウンドメディア「ホワプラSTYLE」をご覧ください。オンラインでのカジュアル面談も可能ですので、ぜひお気軽にお問い合わせください。