コンテナ開発へのDevSecOpsの適用

2020年8月4日(火)
宮崎 悟
連載5回目となる今回は、コンテナ開発におけるDevSecOpsの適用について解説します。

コンテナ開発へのDevSecOpsの適用

前回は、コンテナ環境におけるネットワークセキュリティの課題について説明しました。今回はコンテナ開発におけるDevSecOpsの適用について説明します。

DevOpsとは

DevOpsとは開発(Developments)と運用(Operations)をまとめたプロセスとして考え、開発・運用のスピードを早めるという考え方です。DevOpsにより迅速な開発リリースと、シフトレフト(Shift Left:従来後工程で行われていたテストなどを開発の工程で実施)が求められます。

現在でもよくあることですが、開発と運用のメンバーは、技術レイヤの違い・リリース速度・求められる役割が異なることから対立しがちです。まずは、今までの開発プロセスと運用プロセスをまとめます。

ウォーターフォール開発フロー

初期のウォーターフォール開発では、分析→設計→開発→テスト→運用という流れで開発を行います。半年から1年程度でこの開発サイクルを回すことが多く、後にこの開発サイクルを短くしたスパイラルと呼ばれる開発方法も出てきました。

ウォーターフォール

ウォーターフォール

テスト駆動開発フロー

最近使われるようになったテスト駆動開発時をする際の、典型的な開発フローを考えてみます(現場により異なることがあります)。

  1. 新機能追加・機能修正・バグ発見・運用からのリクエストを契機として、課題(issue)を上げる
  2. 開発者が課題を引き受ける
  3. 開発者がその課題を解決するテストを書く
  4. 開発者がテストに見合うコードを書く
  5. テストを実施
  6. テスト結果に問題がある場合、3または4に戻りテストとコードを修正
  7. テスト結果に問題ない場合、レビューをリクエストする
  8. レビューに問題なければ全テストを実施し、他機能への影響がないか確認する(リグレッションテスト)
  9. リファクタリングを実施し、5まで戻り再テストを行う
  10. 全テストに問題ない場合、製品責任者が本体へのマージを承認
  11. 新たに作成したプロダクトのリリースを、運用へリクエスト
テスト駆動開発(TDD)

テスト駆動開発(TDD)

運用フロー

典型的な運用フローを考えてみます。

  1. リリースされたプロダクトを、ステージング環境で機能テスト
  2. ステージング環境での負荷テスト
  3. プロダクトリリースに問題がある場合は、開発に問題解決をリクエスト
  4. プロダクトのリリース環境へのデプロイ
  5. サービスの正常性確認(監視・ロギング)
  6. マシン負荷の高低によって、スケールアウト/スケールインを実施
  7. 異常動作が確認された場合の対処
  8. 場合によっては開発に問題解決をリクエスト
典型的な運用フロー

典型的な運用フロー

DevOpsフロー

現在ではリードタイムの短縮が重要視されるようになり、開発とデプロイをより高速に行う必要が出てきました。そのために出てきたのがDevOpsの考え方です。継続的インテグレーション/継続的デリバリー(Continuous Integration/Continuous Delivery)略してCI/CDが、DevOpsの中心となる技術です。

DevOps

DevOps

クラウドネイティブな開発では、開発環境/ステージング環境/デプロイ環境を使用するときだけ、開発者自身で容易に準備できるようになりました。そのため、今まで運用側で行っていたステージング環境でのデプロイテスト/負荷テストなどを開発者側で行うことが可能になりました。開発者はリリース時までにバグを対処でき、運用者は運用だけに専念できます。通常、運用者がバグを発見し対処するのは、コストがかかります。そこで開発者がステージング環境でのテストを行うことにより、バグ発見のコストを下げることができます。これを、シフトレフトと呼びます。

シフトレフトでは、運用手順やデプロイ方法なども考えるため、開発者の負担が大きくなります。しかしウォーターフォールの時代から、上流工程でバグを見つけるほうが、容易かつコスト現象に繋がることが知られています。そのためクラウドネイティブが前提となる現在では、DevOpsによる運用が主流になるでしょう。

DevOpsによる、テストからデプロイを手動で行うのは大変です。また、課題管理やソースのバージョン管理も必要です。これらの課題の追加→コード作成→テスト→デプロイというワークフローを管理するために、CI/CDツールが使用されます。CI/CDツールとしては、Jenkins/GitHub/GitLab/Circle CI/Travis CIなどが有名です。

コンテナ環境におけるDevOps

コンテナ環境では、サービス単位でコンテナを作成するようになり、使用するコンテナも多くなります。そのため、コンテナでサービスを開発/運用する場合、このDevOpsの考え方がより重要になります。

コンテナ環境としてKubernetesを使用する場合、デプロイ/監視/ロギング/スケールイン/スケールアウト/異常動作の検知を、Kubernetesで行うことができます。デプロイは、KubernetesのリソースとしてDeploymentなどを定義しておけば、サービスを停止することなく新しいコンテナイメージに置き換えることができます。監視項目/スケールイン/スケールアウト/正常性確認の方法をKubernetesへ定義すれば、自動的な運用も実現可能です。もちろん同様のことは、マネージドコンテナ環境やマネージドKubernetesなどでも実現できます。

DevOpsではステージングテストにおいて、デプロイ/監視/ロギング/スケールイン/スケールアウト/異常動作の検査が、事前に可能です。負荷テストもテスト用のサービスを一時的に増やすことが容易になり、想定以上の負荷に近づけることが可能です。

コンテナを使用することでサービスがマイクロサービスやサービスメッシュに近くなり、複数コンテナの組み合わせとなるため、正常性テストの必要性は高まります。コンテナが増えることで開発対象は細かくなる一方で、その分開発者のメンテナンス負荷が高くなります。課題管理からリリースまでをDevOpsツールに任せ、CI/CDを自動化することで開発者の負担を減らすことができます。

DevSecOpsとは

近年のサービスはWebサービスが多くなり、個人情報を保護するためのセキュリティが問題になっています。2020年の新型コロナウィルスの感染拡大を契機としたリモートワークが加速する中、いくつかの情報共有/リモート会議アプリケーションが多く使われるようになりました。しかし、今まで多く使われていなかったがために発覚したセキュリティ問題で、使用を敬遠されたアプリケーションもあります。

セキュリティ問題が重要というのは以前から提唱されており、DevOps開発サイクルでもセキュリティを考えなければならないという機運が高まりました。ここで登場するのがDevSecOpsです。

DevSecOpsは、セキュリティをセキュリティ設計者や運用者だけでなく、開発から運用に関わるすべての人が担当するサイクルです。アプリケーションを動作させるインフラストラクチャが、物理マシンから仮想マシンに移ったことで、物理からサービスまでのレイヤはより多くなったと言えます。そのすべてのレイヤでセキュリティを確保するのは、年々難しくなっています。そのため、開発から運用までのすべてのフローを、セキュアに行う必要が出てきました。

セキュリティを考えるには、最初に提供するサービスが守るべきセキュリティ基準を決定します。CIS benchmarkは、セキュリティ基準の業界標準と言えるでしょう。クレジットカード情報を扱うサービスならばPCI DSSに準拠する必要が、日本の金融業ではFISCに対応する必要が、米国で個人情報を伴うヘルスケアサービスを行うならHIPAAに準拠する必要があります。日本でも個人情報の保護に関する法律があり、個人情報を扱うサービスではこの法律に準拠する必要があります。どのようなサービスを提供するかによって、セキュリティ基準は変わってきます。

また、現在ではマイニングツールやbotなどのマルウェアへの感染を防ぐ必要があります。マイニングツールを埋め込まれた場合は、コンピュータリソースを大量に使用することになり、意図しない料金発生のリスクがあります。botなどで攻撃者の踏み台にされた場合、攻撃者の共犯とみなされる場合があるため、より注意が必要です。

セキュリティを一貫としたものとして捉えると、一番弱い部分が人間自身であると言うことも、意識に置かなければなりません。現在でも、ソーシャルハックを用いた個人を対象にした詐術によるハッキングの危険性は高いままです。また、人間の誤操作の問題も検討しなければなりません。かと言って厳密にセキュリティ基準を定めても、それが現場の運用体制とかけ離れたものであれば、人間はその通りに作業しなくなりがちです。

コンテナ時代のDevSecOps

外部からの攻撃を防ぐためには、今まではファイアウォール/WAF/侵入者検知ツールが必要でした。では、コンテナ環境ではどうでしょうか。コンテナ時代では、開発対象がコンテナ単位になり、どのようにコンテナにおける開発→デプロイ→運用を行うかを考える必要があります。

DevSecOps

DevSecOps

セキュリティ基準の作成

提供するサービスによって、セキュリティの基準を決める必要があります。

  • 最低限のセキュリティ
    • コンテナホストの外部からの分離
    • コンテナやKubernetesのAPIを外部公開しない
    • 外部公開するサービスポートの制限
    • コンテナ間ネットワークの暗号化
    • コンテナを扱う際のロールベースのアクセス制御
  • 個人情報を扱う場合のセキュリティ(上記の内容に加え以下の項目が必要)
    • DBの暗号化
    • コンテナホスト間ネットワークの暗号化
  • クレジットカードを扱う場合のセキュリティ(上記の内容に加え以下の項目が必要)
    • データセンターがPCI DSS対応施設であること
    • 開発プロセスのセキュリティ定義

個人情報の管理やクレジットカードサービスとして、外部サービスを使用することで管理を行わないという選択肢もあります。その場合、使用する外部サービスとどのような通信を行うか、というチェックポイントが追加されます。

アプリケーション開発時のセキュリティ

アプリケーションコンテナを作成する場合、いくつかの方法がありますが、ベースとなる既存のコンテナを元にするのが一般的です。例えばPHP/Python/Rubyの言語ライブラリを含むコンテナ、httpdやデータベースなどサービスを起動するコンテナ、Alpine/Debian/UBIなどのOSのみ提供するコンテナなどがあります。ベースとなるコンテナを選定する場合、機能だけでなくそのベースコンテナに含まれるパッケージや言語ライブラリに、脆弱性やマルウェアが含まれていないかどうかを確認する必要があります。

ここで使用されるのが、第3回で説明したコンテナの静的スキャンです。これによりパッケージに含まれている脆弱性やマルウェアを検知し、開発段階で脆弱性に対処可能です。また、パッケージのスキャンだけではなくアプリケーションのテスト段階で、使用している言語ライブラリまで脆弱性を検知できるツールもあります。

Webアプリケーションなど外部へ情報を送信するサービスの場合、外部からのペネトレーション(侵入)テストなどを行ったほうがよいでしょう。ペネトレーションテストツールは、Kari LinuxOWASP ZAPNiktoを始め、オープンソース/プロプライエタリを問わず有名なツールがあるので、それらを利用するとよいでしょう。

このような静的スキャンをアプリケーションのテストと同時に実施することで、開発段階でセキュアな状態のコンテナを作成可能になります。また新しい脆弱性は日々発見され、脆弱性情報も更新され続けます。正常性テストとともにデプロイ済みのイメージを再スキャンすることで、脆弱性やマルウェアの発見を早い段階で知り、イメージの更新作業を行えます。

特にコンテナ独自のセキュリティとして、以下のことを考える必要があります。

  • 実行ユーザ/グループの非特権ユーザ化
  • Privilegedモードで動作させない
  • systemdなどのsuper daemonを動作させない
  • 不要なコマンドを含まない

デプロイ時のセキュリティ

コンテナイメージを実際にデプロイする際にも、気をつけるべき点があります。

  • デプロイするイメージがスキャン済みのものか
  • デプロイが許可されたイメージか
  • デプロイを許可された役割を持ったユーザか

上記は、想定外のコンテナデプロイを防ぐ施策です。作成時や以前デプロイしたときの静的スキャンで問題がなくても、デプロイ時に脆弱性ありとなったイメージはデプロイするべきでありません。また、悪意のある第三者による攻撃や内部犯を絞り込むため、許可されていないコンテナ、許可されていないユーザによるデプロイを防ぐ必要があります。

これらに加えて、以下の項目を不可にする施策も有効です。

  • 特権ユーザでの起動
  • ホストネット内部ネットワークへのアクセス
  • ホストIPC名前空間の使用
  • ホストPID名前空間の使用
  • ホストユーザ名前空間の使用不可
  • ホストボリュームのマウント制限

運用時のセキュリティ

さらにコンテナ運用時には、いくつもの気をつけるべき点があります。

コンテナホスト

コンテナを稼働するコンテナホストは、それ自体も脆弱性検査の対象となります。また、ユーザのログインすることを許可するべきではありません。コンテナのAPIもしくはKubernetesのAPIを許可し、sshでのアクセスを拒否するなどの処置が必要です。マネージドKubernetesにNodeの管理を任せるのも1つの手です。

コンテナの不変性

稼働中のコンテナは、外部からの攻撃にさらされる危険性があります。そのため、稼働中のコンテナは不変(イミュータブル)である必要があり、変更がある部分(ミュータブル)はパーシステントボリューム(PV)やDB上に配置し、配置されたファイルの実行を許さないことが必要です。

これを実現するには、実行するコマンドや設定ファイルが含まれるrootボリュームを、リードオンリーマウントすることにより対処できる場合があります。また一部のセキュリティツールには、コマンドやシステムコールの実行について許可/不許可リストを使用して実行コマンドを制限できるほか、コンテナ実行後も変更されたファイルを実行不能にするなどの機能があります。

コンテナ内ネットワーク

コンテナ内部ネットワークは制限をかけなければ、フラットなネットワークのままです。サービス間の通信は事前に設定することが必要です。また、設定ミスなどによる間違った通信を防ぐため、Kubernetesのネットワークポリシーだけでなく、コンテナセキュリティツールでも不要な通信がないかを機械的にチェックする必要があります。

終わりに

今回はコンテナ開発におけるDevSecOpsの適用について説明しました。最近は法律の変更などもあり、よりセキュリティを守ったサービスが必要になってきました。コンテナを用いたサービスのDevSecOpsによって各機能の細分化が進み、ツールを使用することでその負荷を下げることがより必要になっています。

今までの環境での開発に慣れたアプリケーション開発者にとっては負荷が高くなります。しかし、セキュリティはもはや必要要件になっていることと、セキュリティは開発時に対処するのが最も低コストであるということを念頭に置きましょう。

次回は、今までの連載のおさらいとして、コンテナのセキュアな運用をするために必要なことをまとめます。次回をお楽しみに。

国立函館高専を卒業後、UNIX、Windowsアプリケーションの開発、 Solaris/Linuxでのシステム構築に従事した。 OS、仮想化技術、セキュリティを得意とする。 https://www.slideshare.net/satorumiyazaki
https://speakerdeck.com/smiyaza/

連載バックナンバー

セキュリティ技術解説
第6回

コンテナのセキュアな運用のために

2020/11/2
連載6回目となる今回は、これまでのまとめと最新の情報について説明いたします。
セキュリティ技術解説
第5回

コンテナ開発へのDevSecOpsの適用

2020/8/4
連載5回目となる今回は、コンテナ開発におけるDevSecOpsの適用について解説します。
セキュリティ技術解説
第4回

コンテナのネットワーク制限

2020/7/2
連載4回目となる今回は、コンテナのネットワーク通信の制限について解説します。

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています