開発環境のセキュリティを守ろう! Red Hat Trusted Software Supply Chain/Trusted Application Pipeline

こんにちは。Specialist Solution Architect の瀬戸です。

Red Hatから去年発表されたRed Hat Trusted Software Supply ChainおよびTrusted Application Pipelineという製品群をご存知でしょうか?

ご存知でなくても、これらの製品が実現したいことはとても簡単なので、簡単に学んでみましょう。

どこにでもある「脅威」

これらはTrusted (信頼できる程度の意味)という名前がついている通り、セキュリティを担保するための製品群です。 ソフトウェアを開発して、本番環境でアプリケーションを動作させるまでをセキュアに保ちます。

実はRed Hat はソフトウェアを提供しているアプリケーション開発会社だということはご存じでしょうか?

Red Hat は Red Hat Enterprise Linux をはじめとした多くのユーザーがいるソフトウェアを開発しており、それらをセキュアに保つための活動をしています。 今回、 Red Hat ではそれらで培ったソフトウェアリリースをセキュアに行うための方法論を製品としてリリースしました。

セキュアにしましょうとだけ言われても、なんで?となってしまうので、開発環境にどのような問題がありがちなのかを見ていきましょう。

ソフトウェア開発環境は狙われている!

本番環境はセキュリティ対策がしっかりしていると思います。アンチウィルスソフト等を動作させ監視させ、変更には手続きが必要で何が動いているかをきちんと管理できるようにする。 手作業が必要な場合も事前に申請をし、何を行うのかを確認の上で、手順書通りに行い、余計なことがされてないことを保証していると思います。

しかし、開発環境はどうでしょうか?

開発者個人に支給されたPCで作業をし、好きなソフトウェアを使用し、ソフトウェア開発を行っている場合が多いです。

大多数である事務用のPCの場合は最低限のOfficeスイート製品や、別途必要になるいくつかの製品だけあればよい場合が多いですが、 開発者の場合は特殊なソフトウェアが必要になる場合があります。 また、Officeスイート製品等はベンダーから提供される自動アップデート機能が有効だったりもしますが、 開発者が使うようなソフトウェアの場合は個人が開発している場合もあり、自動アップデート機能が存在しない場合もあります。

そのような状態で開発者の開発環境が狙われ、そこが踏み台とされ企業内のデータ漏洩事故等が発生するようになっています。

依存しているライブラリも狙われている!

本番環境で動いているシステムがいくつのサードパーティー製のライブラリに依存しているかを数えたことがある人はいるでしょうか? ある程度の規模になると数十~数百は含まれているはずです。

もし調べたことがない人は、JavaでMavenを使用している場合は次のコマンドで簡単に調べることができます。

mvn dependency:tree

今、ためしに手元にあったアプリケーションに対してかけてみたら次のような結果になりました。

1行が1依存ライブラリなので、119個(テスト用を含めると159個)のサードパーティー製のライブラリに依存しています。

C:\git\camel-example>mvn dependency:tree
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< com.redhat:camel-example >----------------------
[INFO] Building A Camel Spring Boot Route 1.0-SNAPSHOT
[INFO]   from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- dependency:3.7.0:tree (default-cli) @ camel-example ---
[INFO] com.redhat:camel-example:jar:1.0-SNAPSHOT
[INFO] +- org.springframework.boot:spring-boot-starter-web:jar:2.7.4:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter:jar:2.7.4:compile
[INFO] |  |  +- org.springframework.boot:spring-boot:jar:2.7.4:compile
[INFO] |  |  +- org.springframework.boot:spring-boot-autoconfigure:jar:2.7.4:compile
[INFO] |  |  +- org.springframework.boot:spring-boot-starter-logging:jar:2.7.4:compile
[INFO] |  |  |  +- ch.qos.logback:logback-classic:jar:1.2.11:compile
[INFO] |  |  |  |  \- ch.qos.logback:logback-core:jar:1.2.11:compile
[INFO] |  |  |  +- org.apache.logging.log4j:log4j-to-slf4j:jar:2.17.2:compile
[INFO] |  |  |  |  \- org.apache.logging.log4j:log4j-api:jar:2.17.2:compile
[INFO] |  |  |  \- org.slf4j:jul-to-slf4j:jar:1.7.36:compile
[INFO] |  |  +- jakarta.annotation:jakarta.annotation-api:jar:1.3.5:compile
[INFO] |  |  \- org.yaml:snakeyaml:jar:1.30:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter-json:jar:2.7.4:compile
[INFO] |  |  +- com.fasterxml.jackson.core:jackson-databind:jar:2.13.4:compile
[INFO] |  |  |  +- com.fasterxml.jackson.core:jackson-annotations:jar:2.13.4:compile
[INFO] |  |  |  \- com.fasterxml.jackson.core:jackson-core:jar:2.13.4:compile
[INFO] |  |  +- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:jar:2.13.4:compile
[INFO] |  |  +- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:jar:2.13.4:compile
[INFO] |  |  \- com.fasterxml.jackson.module:jackson-module-parameter-names:jar:2.13.4:compile
[INFO] |  +- org.springframework:spring-web:jar:5.3.23:compile
[INFO] |  |  \- org.springframework:spring-beans:jar:5.3.23:compile
[INFO] |  \- org.springframework:spring-webmvc:jar:5.3.23:compile
[INFO] |     +- org.springframework:spring-aop:jar:5.3.23:compile
[INFO] |     +- org.springframework:spring-context:jar:5.3.23:compile
[INFO] |     \- org.springframework:spring-expression:jar:5.3.23:compile
[INFO] +- org.springframework.boot:spring-boot-starter-undertow:jar:2.7.4:compile
[INFO] |  +- io.undertow:undertow-core:jar:2.2.19.Final:compile
[INFO] |  |  +- org.jboss.logging:jboss-logging:jar:3.4.3.Final:compile
[INFO] |  |  +- org.jboss.xnio:xnio-api:jar:3.8.7.Final:compile
[INFO] |  |  |  +- org.wildfly.common:wildfly-common:jar:1.5.4.Final:compile
[INFO] |  |  |  \- org.wildfly.client:wildfly-client-config:jar:1.0.1.Final:compile
[INFO] |  |  +- org.jboss.xnio:xnio-nio:jar:3.8.7.Final:runtime
[INFO] |  |  \- org.jboss.threads:jboss-threads:jar:3.1.0.Final:compile
[INFO] |  +- io.undertow:undertow-servlet:jar:2.2.19.Final:compile
[INFO] |  +- io.undertow:undertow-websockets-jsr:jar:2.2.19.Final:compile
[INFO] |  +- jakarta.servlet:jakarta.servlet-api:jar:4.0.4:compile
[INFO] |  +- jakarta.websocket:jakarta.websocket-api:jar:1.1.2:compile
[INFO] |  \- org.apache.tomcat.embed:tomcat-embed-el:jar:9.0.65:compile
[INFO] +- org.springframework.boot:spring-boot-starter-actuator:jar:2.7.4:compile
[INFO] |  +- org.springframework.boot:spring-boot-actuator-autoconfigure:jar:2.7.4:compile
[INFO] |  |  \- org.springframework.boot:spring-boot-actuator:jar:2.7.4:compile
[INFO] |  \- io.micrometer:micrometer-core:jar:1.9.4:compile
[INFO] |     +- org.hdrhistogram:HdrHistogram:jar:2.1.12:compile
[INFO] |     \- org.latencyutils:LatencyUtils:jar:2.0.3:runtime
[INFO] +- org.apache.camel.springboot:camel-spring-boot-starter:jar:3.14.5.redhat-00012:compile
[INFO] |  +- org.apache.camel.springboot:camel-spring-boot:jar:3.14.5.redhat-00012:compile
[INFO] |  |  +- org.apache.camel:camel-spring:jar:3.14.5:compile
[INFO] |  |  |  +- org.apache.camel:camel-management-api:jar:3.14.5:compile
[INFO] |  |  |  \- org.springframework:spring-tx:jar:5.3.23:compile
[INFO] |  |  +- org.apache.camel:camel-spring-main:jar:3.14.5:compile
[INFO] |  |  |  \- org.apache.camel:camel-main:jar:3.14.5:compile
[INFO] |  |  |     \- org.apache.camel:camel-base:jar:3.14.5:compile
[INFO] |  |  +- org.apache.camel:camel-xml-jaxb-dsl:jar:3.14.5:compile
[INFO] |  |  |  +- org.apache.camel:camel-core-model:jar:3.14.5:compile
[INFO] |  |  |  |  \- org.apache.camel:camel-core-processor:jar:3.14.5:compile
[INFO] |  |  |  \- org.apache.camel:camel-dsl-support:jar:3.14.5:compile
[INFO] |  |  |     \- org.apache.camel:camel-endpointdsl:jar:3.14.5:compile
[INFO] |  |  +- org.apache.camel:camel-cloud:jar:3.14.5.redhat-00009:compile
[INFO] |  |  +- org.apache.camel:camel-cluster:jar:3.14.5.redhat-00009:compile
[INFO] |  |  |  \- org.apache.camel:camel-base-engine:jar:3.14.5.redhat-00009:compile
[INFO] |  |  \- org.apache.camel:camel-health:jar:3.14.5.redhat-00009:compile
[INFO] |  +- org.apache.camel.springboot:camel-core-starter:jar:3.14.5.redhat-00012:compile
[INFO] |  |  \- org.apache.camel:camel-core-engine:jar:3.14.5.redhat-00009:compile
[INFO] |  |     +- org.apache.camel:camel-api:jar:3.14.5.redhat-00009:compile
[INFO] |  |     +- org.apache.camel:camel-core-reifier:jar:3.14.5.redhat-00009:compile
[INFO] |  |     \- org.apache.camel:camel-util:jar:3.14.5.redhat-00009:compile
[INFO] |  +- org.apache.camel.springboot:camel-bean-starter:jar:3.14.5.redhat-00012:compile
[INFO] |  |  \- org.apache.camel:camel-bean:jar:3.14.5.redhat-00009:compile
[INFO] |  +- org.apache.camel.springboot:camel-browse-starter:jar:3.14.5.redhat-00012:compile
[INFO] |  |  \- org.apache.camel:camel-browse:jar:3.14.5.redhat-00009:compile
[INFO] |  +- org.apache.camel.springboot:camel-controlbus-starter:jar:3.14.5.redhat-00012:compile
[INFO] |  |  \- org.apache.camel:camel-controlbus:jar:3.14.5.redhat-00009:compile
[INFO] |  +- org.apache.camel.springboot:camel-dataformat-starter:jar:3.14.5.redhat-00012:compile
[INFO] |  |  \- org.apache.camel:camel-dataformat:jar:3.14.5.redhat-00009:compile
[INFO] |  +- org.apache.camel.springboot:camel-dataset-starter:jar:3.14.5.redhat-00012:compile
[INFO] |  |  \- org.apache.camel:camel-dataset:jar:3.14.5.redhat-00009:compile
[INFO] |  +- org.apache.camel.springboot:camel-direct-starter:jar:3.14.5.redhat-00012:compile
[INFO] |  |  \- org.apache.camel:camel-direct:jar:3.14.5.redhat-00009:compile
[INFO] |  +- org.apache.camel.springboot:camel-directvm-starter:jar:3.14.5:compile
[INFO] |  |  \- org.apache.camel:camel-directvm:jar:3.14.5:compile
[INFO] |  +- org.apache.camel.springboot:camel-file-starter:jar:3.14.5.redhat-00012:compile
[INFO] |  |  \- org.apache.camel:camel-file:jar:3.14.5.redhat-00009:compile
[INFO] |  +- org.apache.camel.springboot:camel-language-starter:jar:3.14.5.redhat-00012:compile
[INFO] |  |  \- org.apache.camel:camel-language:jar:3.14.5.redhat-00009:compile
[INFO] |  +- org.apache.camel.springboot:camel-log-starter:jar:3.14.5.redhat-00012:compile
[INFO] |  |  \- org.apache.camel:camel-log:jar:3.14.5.redhat-00009:compile
[INFO] |  +- org.apache.camel.springboot:camel-mock-starter:jar:3.14.5.redhat-00012:compile
[INFO] |  |  \- org.apache.camel:camel-mock:jar:3.14.5.redhat-00009:compile
[INFO] |  +- org.apache.camel.springboot:camel-ref-starter:jar:3.14.5.redhat-00012:compile
[INFO] |  |  \- org.apache.camel:camel-ref:jar:3.14.5.redhat-00009:compile
[INFO] |  +- org.apache.camel.springboot:camel-rest-starter:jar:3.14.5.redhat-00012:compile
[INFO] |  |  \- org.apache.camel:camel-rest:jar:3.14.5.redhat-00009:compile
[INFO] |  |     \- org.apache.camel:camel-tooling-model:jar:3.14.5.redhat-00009:compile
[INFO] |  |        \- org.apache.camel:camel-util-json:jar:3.14.5.redhat-00009:compile
[INFO] |  +- org.apache.camel.springboot:camel-saga-starter:jar:3.14.5.redhat-00012:compile
[INFO] |  |  \- org.apache.camel:camel-saga:jar:3.14.5.redhat-00009:compile
[INFO] |  +- org.apache.camel.springboot:camel-scheduler-starter:jar:3.14.5.redhat-00012:compile
[INFO] |  |  \- org.apache.camel:camel-scheduler:jar:3.14.5.redhat-00009:compile
[INFO] |  +- org.apache.camel.springboot:camel-seda-starter:jar:3.14.5.redhat-00012:compile
[INFO] |  |  \- org.apache.camel:camel-seda:jar:3.14.5.redhat-00009:compile
[INFO] |  +- org.apache.camel.springboot:camel-stub-starter:jar:3.14.5.redhat-00012:compile
[INFO] |  |  \- org.apache.camel:camel-stub:jar:3.14.5.redhat-00009:compile
[INFO] |  +- org.apache.camel.springboot:camel-timer-starter:jar:3.14.5.redhat-00012:compile
[INFO] |  |  \- org.apache.camel:camel-timer:jar:3.14.5.redhat-00009:compile
[INFO] |  +- org.apache.camel.springboot:camel-validator-starter:jar:3.14.5.redhat-00012:compile
[INFO] |  |  \- org.apache.camel:camel-validator:jar:3.14.5.redhat-00009:compile
[INFO] |  +- org.apache.camel.springboot:camel-vm-starter:jar:3.14.5:compile
[INFO] |  |  \- org.apache.camel:camel-vm:jar:3.14.5:compile
[INFO] |  +- org.apache.camel.springboot:camel-xpath-starter:jar:3.14.5.redhat-00012:compile
[INFO] |  |  \- org.apache.camel:camel-xpath:jar:3.14.5.redhat-00009:compile
[INFO] |  +- org.apache.camel.springboot:camel-xslt-starter:jar:3.14.5.redhat-00012:compile
[INFO] |  |  \- org.apache.camel:camel-xslt:jar:3.14.5.redhat-00009:compile
[INFO] |  \- org.apache.camel.springboot:camel-xml-jaxp-starter:jar:3.14.5.redhat-00012:compile
[INFO] |     \- org.apache.camel:camel-xml-jaxp:jar:3.14.5.redhat-00009:compile
[INFO] |        \- org.apache.camel:camel-xml-io-util:jar:3.14.5.redhat-00009:compile
[INFO] +- org.apache.camel.springboot:camel-stream-starter:jar:3.14.5:compile
[INFO] |  \- org.apache.camel:camel-stream:jar:3.14.5:compile
[INFO] |     \- org.apache.camel:camel-support:jar:3.14.5:compile
[INFO] +- org.springframework.boot:spring-boot-starter-test:jar:2.7.4:test
[INFO] |  +- org.springframework.boot:spring-boot-test:jar:2.7.4:test
[INFO] |  +- org.springframework.boot:spring-boot-test-autoconfigure:jar:2.7.4:test
[INFO] |  +- com.jayway.jsonpath:json-path:jar:2.7.0:test
[INFO] |  |  +- net.minidev:json-smart:jar:2.4.8:test
[INFO] |  |  |  \- net.minidev:accessors-smart:jar:2.4.8:test
[INFO] |  |  |     \- org.ow2.asm:asm:jar:9.1:test
[INFO] |  |  \- org.slf4j:slf4j-api:jar:1.7.36:compile
[INFO] |  +- jakarta.xml.bind:jakarta.xml.bind-api:jar:2.3.3:compile
[INFO] |  |  \- jakarta.activation:jakarta.activation-api:jar:1.2.2:compile
[INFO] |  +- org.assertj:assertj-core:jar:3.22.0:test
[INFO] |  +- org.hamcrest:hamcrest:jar:2.2:test
[INFO] |  +- org.junit.jupiter:junit-jupiter:jar:5.8.2:test
[INFO] |  |  +- org.junit.jupiter:junit-jupiter-api:jar:5.8.2:test
[INFO] |  |  |  +- org.opentest4j:opentest4j:jar:1.2.0:test
[INFO] |  |  |  +- org.junit.platform:junit-platform-commons:jar:1.8.2:test
[INFO] |  |  |  \- org.apiguardian:apiguardian-api:jar:1.1.2:test
[INFO] |  |  +- org.junit.jupiter:junit-jupiter-params:jar:5.8.2:test
[INFO] |  |  \- org.junit.jupiter:junit-jupiter-engine:jar:5.8.2:test
[INFO] |  |     \- org.junit.platform:junit-platform-engine:jar:1.8.2:test
[INFO] |  +- org.mockito:mockito-core:jar:4.5.1:test
[INFO] |  |  +- net.bytebuddy:byte-buddy:jar:1.12.17:test
[INFO] |  |  +- net.bytebuddy:byte-buddy-agent:jar:1.12.17:test
[INFO] |  |  \- org.objenesis:objenesis:jar:3.2:test
[INFO] |  +- org.mockito:mockito-junit-jupiter:jar:4.5.1:test
[INFO] |  +- org.skyscreamer:jsonassert:jar:1.5.1:test
[INFO] |  |  \- com.vaadin.external.google:android-json:jar:0.0.20131108.vaadin1:test
[INFO] |  +- org.springframework:spring-core:jar:5.3.23:compile
[INFO] |  |  \- org.springframework:spring-jcl:jar:5.3.23:compile
[INFO] |  +- org.springframework:spring-test:jar:5.3.23:test
[INFO] |  \- org.xmlunit:xmlunit-core:jar:2.9.0:test
[INFO] \- org.apache.camel:camel-test-spring-junit5:jar:3.14.5:test
[INFO]    +- org.apache.camel:camel-test-junit5:jar:3.14.5:test
[INFO]    |  \- org.apache.camel:camel-core-languages:jar:3.14.5:compile
[INFO]    \- org.apache.camel:camel-spring-xml:jar:3.14.5:compile
[INFO]       +- org.apache.camel:camel-xml-jaxb:jar:3.14.5:compile
[INFO]       |  +- com.sun.xml.bind:jaxb-core:jar:2.3.0:compile
[INFO]       |  \- com.sun.xml.bind:jaxb-impl:jar:2.3.3:compile
[INFO]       |     \- com.sun.activation:jakarta.activation:jar:1.2.2:runtime
[INFO]       \- org.apache.camel:camel-core-xml:jar:3.14.5:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  2.434 s
[INFO] Finished at: 2025-01-06T11:18:35+09:00
[INFO] ------------------------------------------------------------------------

多くのシステムや製品ではOSSが使われており、動作にはOSSが必要になります。また、そのOSSは別のOSSが使われており、動作には別のOSSが必要になります。またまたその別のOSSにはさらに別のOSSが使われており・・・・ と芋づる式に依存ライブラリが増えていってしまっています。

予期しない依存ライブラリを狙った攻撃というのは毎年行われており、ライブラリ自体に脆弱性を埋め込もうとしたxz utilsの事例や脆弱性の含まれたライブラリに対する外部からの攻撃が行われたlog4shellの事例等があります。

本番環境でアプリケーションを動作させる前に検証環境などで動作確認しているから問題ないと考える人もいるかもしれませんが、業務の動作に関係ない時限式の罠が末端の依存ライブラリに含まれていない事の検証まで行われている方はどれくらいいるのでしょうか?

なお、他の言語でもパッケージマネージャーを使用して依存関係を管理している場合のほとんどで簡単に依存関係の一覧を出力することができます。 例えば、 JavaScript(npm)の場合はnpm ls -allで出力できます。 そのほかの言語についても必要な場合は確認してみてください。

みんな気にはなっている脅威

IPAは情報セキュリティ10大脅威として毎年、去年に発生した社会的に影響が大きかったと考えられる情報セキュリティにおける事案から、IPAが脅威候補を選出し、情報セキュリティ分野の研究者、企業の実務担当者など約200名のメンバーからなる「10大脅威選考会」が脅威候補に対して審議・投票を行い、決定したものを公開しています。それの2024年度版の組織向けの脅威によると、1位はランサムウェアによる被害で、2位はサプライチェーンの弱点を悪用した攻撃、3位は内部不正による情報漏えい等の被害でした。

情報セキュリティ10大脅威[組織] IPAより

www.ipa.go.jp

ランサムウェアはソフトウェアを勝手にインストールしたときに感染する場合もあります、また、開発環境だからと統制を行わずに好き勝手にPCを使わせていたら内部不正の温床になる可能性があります。サプライチェーンの弱点の中には依存ライブラリに起因する脆弱性が含まれます。

情報セキュリティ10大脅威のTOP3にはアプリケーション開発に関わるものが含まれています。当然、それ以外の物にもアプリケーション開発に関わるものが多く含まれています。

さて、どうしていくか

世の中にはこれらの課題を解決するためのソリューションが多数あります。しかし、本当にそれらのソリューションで解決できるのでしょうか?解決した気になっているだけではないでしょうか?

Red Hatは30年以上にわたりRed Hat Enterprise Linuxをセキュアに提供しています。その中でRed Hatでどうやって安全なアプリケーションをユーザーに提供してきたのかをノウハウとしてユーザーに提供できるようにしたのが、Red Hat Trusted Software Supply ChainおよびTrusted Application Pipelineです。

Red Hat Trusted Software Supply ChainはRed Hat OpenShift Plusに含まれるいくつかの製品とTrusted Application Pipelineを含んだソリューションの名前で単体では販売されていません。

ここから、開発プロセスを安全にするためにはどのようにしていけばよいのかと、Red Hat OpenShift PlusとTrusted Application Pipelineにどのような機能が含まれているのかについて説明していきます。

この記事では一般的なCI/CDパイプラインについての知識があることを前提としています。ご了承ください。

なお、これ以外にもかならずセキュリティパッチを当てる等一般的な事柄もありますが、割愛しています。

開発環境では誰が何をしたのかを判るようにする

Red HatではRed Hat build of KeyCloakというシングルサインオンを実現するための製品があります。そちらと各機能を連携させて、誰が何を行ったのかを確実にわかるようにします。

社内のIDは統合済みでしょうか?事務をされる方々等が使用するIDはMicrosoft Active Directory等を使用して統合されている場合がほとんどでしょうが、開発者が使用するシステムについてはユーザー数が少ないからという理由で統合されていない場合があります。それらをすべて統合する必要があります。

そのうえで適切に作業ログを取るようにしていきます。

Gitの設定を適切に行う

Gitのリポジトリには何を使っているでしょうか?GitHubですか?

実はGitHubではデフォルトでコミット履歴を改ざん(変更)することができます。方法はGitのマニュアルに記載されているとおりに実行するだけです。GitHub以外ではデフォルトでは改ざんできないようになっている場合もありますが、設定を変更することで改ざんができるようになります。

git-scm.com

また、Gitでは、コミットするユーザー名やメールアドレスは自由に入力できます。どのような値が入力されているかきちんと管理されているでしょうか?GitHubやGitLab等を使用している場合は、Gitとは別途に認証機能を使用して、正しいユーザー名、メールアドレスが使用されているか認証してくれる機能を持っている場合もあります。 Gitリポジトリのプロバイダ側でそういった仕組みを持っていない場合は、Trusted Application Pipeline に含まれるSigstore Gitsignを使用する事で、Gitに署名を行い、誰がコミットをしたのか、改ざんされていないことを担保することができます。

とにかく署名、ログを取る

開発中に作られたアプリケーションバイナリがその後改変されていないことを保証し、責任の所在を明確にするため、出来上がったものに署名を行います。Javaのjarファイルの場合はjarsignerを使用することができます。コンテナイメージなどの場合は汎用的な仕組みとしてSigstore Cosignを使用することができます。

これでアプリケーションに何かがあった場合にどこまで安全だったのかを確認することができます。コンテナイメージを使用していないRHEL(Linux)の場合は、Tripwire等を使用する事でその時点で何が入っていたのかのログを記録することができます。そうすることで改変されてないことを確認できるようになります。

開発者に手続きを守らせる

開発者全員が従順で、監督をしなくても決められたとおりに開発手順を守ってくれるのであればよいのですが、そういうわけにはいきません。特に優秀な開発者は手順を省略するのがうまく、効率化を旗印にどんどん手順を変更していきます。署名等を行うことは監査上重要なのですが、どうしても面倒くさくなって省略されがちです。

CI/CDビルドパイプラインの固定、標準化

ビルド、デプロイの自動化のためCI/CDパイプラインを使用するのが一般的になっています。しかし、現実的に多くのCI/CDパイプラインはそれぞれのプロジェクトで善意の開発者による維持、メンテナンスがされており、きちんとした管理ができているかわからない場合もあるのではないかと思います。

昨今のモダンと言われるCI/CDサーバーの多くはgitのリポジトリ上にCI/CDの設定ファイルを置くことでCI/CD中に何を行うのかの定義ができます。DevOpsの考え方の元、開発者が柔軟にビルドプロセスを変更することができるようになっています。しかしながら、それでは問題がある場合があります。

優秀な開発者は多くの場合、CI/CDに対する知見があり、柔軟にCI/CDを変更することで開発の効率化を行っていきます。CI/CD内で絶対に行わなくてはならないと決められていることを、開発者が勝手に削除してしまう場合もあり、問題になります。

先ほど、ビルドしたアプリケーションバイナリに署名をしようという話をしましたが、CI/CDパイプライン内で署名を自動的に行えるように設定していたとします。しかし、開発者がビルドパイプラインを勝手にいじれるようになっている場合は、その署名行為が必ず行われることを保証できません。

CI/CDパイプラインに関わる設定ファイルをgit内に保持する必要のあるCI/CDサーバーの場合、gitリポジトリのエイリアスを作る等で、設定ファイルを開発者から保護することもできますが、Trusted Application Pipelineに含まれるDeveloper Hub(backstage)を使用するとCI/CDパイプラインに関わる設定を開発者から分離した形でテンプレート(Golden Pathと呼ばれます)として保持することができ、OpenShift(Kubernetes)上に開発者が変更できない形でデプロイすることができます。

開発環境で標準化されたソフトウェアのみを使用する

開発環境に開発者が自由にソフトウェアをインストールすることができる場合、当然マルウェアが混入する可能性があります。そこを起点として本番稼働中のアプリケーションなどに影響が出ることがあります。そのため、開発者のPCには自由にソフトウェアを入れられないようにすることが望ましいです。この試み自体は昔から行われていて、簡単な方式であればMicrosoftのActive Directoryを使用してソフトウェアを配布します。それ以外にもシンクライアント端末という形で標準化されたソフトウェアのインストールされた環境をサーバー上に作り、開発者からはそこにアクセスさせ、クリーンな環境で開発をさせるという事が行われていました。現在はクラウドベンダーが同じような形で環境を提供しており、Amazon WorkSpacesAzure Virtual Desktopなどがあります。ただ、これらはいわゆるリモートデスクトップで接続する形なので、リッチなGUIが必要であり、サーバー側のリソースが潤沢に必要になるという問題があります。 最近では、Visual Studio Codeが言語を問わない開発のデファクトスタンダードの一つになっているということと、Visual Studio CodeがJavaScriptで開発されており、WebからアクセスできるようなフォークされたOSS(Eclipse Che等)が出てきたため、簡易なシンクライアント環境としてVisual Studio CodeをSaaSとして提供するようなGitHub Codespacesのようなサービスが登場しています。

Red HatでもEclipse CheをベースにしたRed Hat OpenShift Dev Spacesという製品があり、OpenShift上でVisual Studio Codeベースのシンクライアント開発環境を提供しています。Developer HubにはRed Hat OpenShift Dev Spacesのテンプレートを提供する機能もあり、開発者に統一された開発環境を提要できます。Javaで開発している場合は歴史的にEclipseやNetBeans、IntelliJといったパワフルなIDEがあり、それらに比べるとどうしても弱いところはあるのですが、コアチームを覗いた大多数の開発者向けとしては一考する余地があります。

署名の検証、正しいプロセスを踏んでいるかの確認

先ほど、アプリケーションバイナリに署名をしようという話をしましたが、正しく署名されているかについてはデプロイ前に確認する必要があります。デプロイするアプリケーションはただしいビルドプロセスを踏んでいるのかも確認したいです。そのためにTrusted Application Pipelineに含まれるEnterprise Contractの機能を使用することができます。

多くの製品では署名が行われており、インターネットからファイルをダウンロードする場合にはファイルのシグネチャ(CRC/SHA-1等)が提供されている場合もありますが、きちんと確認されているでしょうか?インターネットからダウンロードしたファイルが正しいものであるという証明をしているでしょうか?

Enterprise Contractではアプリケーションの署名の検証や、正しい手順で作られたアプリケーションであるかの確認などをすることができます。

Enterprise Contractではその他にも多数のチェックを行うことができます。詳細については以下のURLを参照してください。

enterprisecontract.dev

正しいサードパーティー製ライブラリを使用する

先に述べたとおりに、現在のソフトウェアは多くのサードパーティー製ライブラリに依存しています。それらに脅威が含まれていないことを確かにする必要があります。

信頼できるリポジトリを使用する

Javaで言えばMaven、JavaScriptで言えばnpm等のパッケージマネージャーを使用されていると思いますが、そのパッケージマネージャーはどこのリポジトリからライブラリを取得しているかご存知でしょうか?そのリポジトリは誰が運用して、いつまで運用される予定かを気にしたことはありますか?ライブラリがリポジトリにどのように公開され、どのように非公開となる可能性があるかを気にしたことはありますか? ライブラリがビルドできることを保証し続けるためにはそれらを確認する必要があります。また、ライブラリの取得先の永続性が保証されるかわからないので、JFrog ArtifactorySonatype Nexus Repository、Red Hat OpenShift Platform Plusに含まれるQuay等のリポジトリソフトウェアを使用して、リポジトリ自体を社内にコピーする必要があります。

どのライブラリを使用しているか明らかにする

アプリケーションが依存しているライブラリのすべてのソースコードをユーザー側が確認し、脅威が含まれていないことを確認するのは現実的ではありません。しかし、OSSである場合には第三者の評価機関がCVEとして驚異の情報を公開してくれています。プロプライエタリである場合は最低限信頼できる組織や人が作成した、もしくは信頼できる組織や人が検証したライブラリであること、OSSである場合は一般的な経路を通って、第三者機関がきちんと検査できる状態になっているもののみを使用する必要があります。最近SBOM(ソフトウェア部品構成表)というのが話題に上がっているのはご存知でしょうか。 経済産業省からSBOMを使用して依存ライブラリを管理するように手引きが発行されています。

www.meti.go.jp

SBOMは簡単に言えば、どのライブラリに依存しているのかをしっかり管理しようという標準規格のファイルです。 SBOMを作成するツールはたくさんありますが、Trusted Application Pipelineに含まれるsyftでSBOMを作成することができます。Syftでは各言語の仕組みをハックして情報を取得してくれます。

SBOMは言語に依存しない汎用的な形式ですが、JavaでMavenを使用している場合はpom.xmlファイルがそのまま部品表となります。どのライブラリに依存しているかは先に示した通りに以下のコマンドで表示できます。

mvn devendency:tree

さらに詳細な情報まで必要な場合は以下のコマンドで表示することができます。(HTMLが生成されます。)

mvn site

mvn site

使用しているライブラリに脅威が含まれていないかをモニタリングする

依存しているライブラリに脆弱性が含まれていないかを絶えずチェックする必要があります。また、大きな脅威が見つかった場合には過去にさかのぼって脅威が含まれていなかったかどうか、いつから含まれていたか等を確認する必要が出てきます。GitHubやGitLab等ではそのまま依存関係のバージョン管理からチェックまで行ってくれます。Trusted Application Pipelineに含まれるTrusted Profile Analyzerでもチェックを行うことができます。Trusted Profile AnalyzerではSBOMを履歴として保管しておくこともできるので、特に法令でSBOM対応が必要な場合にはちょうどよくなっています。GitHubやGitLab等を使用する場合は設定によってはカジュアルに履歴を改変できる可能性がある点についてはご注意ください。

なお、Trusted Profile Analyzerと同等の機能はRed Hat Dependency Analyticsという名前でプレビュー版がVSCodeのプラグインとして無償で公開されています。Maven等を使用している場合はそのままチェックができるので試してみてください。

marketplace.visualstudio.com

本番環境で怪しい振る舞いがないか確認をする

本番環境はユーザー、その他からアクセスされる環境なので、脅威が発覚しやすい環境です。怪しい挙動がないかを逐次確認することで、開発環境に素早くフィードバックすることができます。各種ベンダーが出しているアンチウィルスソフトを導入したり、Tripwire等のファイル変更検知ソフトウェアを使用したりします。Red Hatの場合はOpenShift Platform Plusに含まれるRed Hat Advanced Cluster Security for Kubernetesを使用する事で実行中のコンテナに含まれる脅威を検知することができます。また、OpenShiftではルートレスコンテナという仕組みを使用し、そもそも外部から混入した怪しいアプリケーションが実行しにくいようになっています。

まとめ

この記事では開発環境にどのような脅威が存在するか、それに対する一般的なソリューション及びRed Hat Trusted Software Supply Chain/Trusted Application Pipelineで何が行えるのかについて紹介しました。具体的にどう設定していくべきかについてはそれぞれの環境に合わせて検討していく必要があります。

個別のソリューションはあるもののRed Hat Trusted Software Supply Chain/Trusted Application Pipelineほどの網羅性があるものはあまりないのかなという印象があります。

Red Hat Trusted Software Supply Chain/Trusted Application Pipelineは既存のCI/CDパイプラインにも部分で気に導入できる柔軟性の高さが特徴です。すでに他の製品を導入している場合でも部分的に機能を選択して導入することができます。既存の社内ルールにあわせて柔軟に対応することもできます。

また、そもそも現在の開発環境のセキュリティがどうなっているかわからないから調査して改善の支援までしてほしい、トータルで支援してほしい等もRed Hatコンサルティングにより可能です。ぜひお問い合わせください。

誤字指摘thx! @henrich

* 各記事は著者の見解によるものでありその所属組織を代表する公式なものではありません。その内容については非公式見解を含みます。