AWS CodeArtifactを利用してソフトウェアサプライチェーンのセキュリティを確保しよう 〜実践編〜
こんにちは。
このあいだAWSパートナー同士のフットサル大会があったのですが、準備運動不足により前腿が軽い肉離れになってしまいました、かめでございます。
今回は、前回ブログにて紹介させて頂いたCodeArtifactの実践的な利用についてご紹介させて頂こうと思います!
AWS CodeArtifactを利用した依存関係かく乱攻撃への対策
前回のブログ、AWS CodeArtifactを利用してソフトウェアサプライチェーンのセキュリティを確保しよう で紹介させて頂いたとおり、CodeArtifactの利用は、ソフトウェアサプラーチェーン攻撃に対して有効なサービスです。
例えばCodeArtifactを利用することで、依存関係かく乱攻撃を防ぐための構成を行うことができます。CodeArtifactは、依存関係のパッケージを安全に管理することができるフルマネージド型のソフトウェアアーティファクトリポジトリサービスです。このサービスを使うことで、悪意のあるパッケージが混入することを防ぎ、組織内部で使われているプライベートな依存関係を守ることができます。
今回は、CodeArtifactを利用して、より実践的な「依存関係かく乱攻撃」の対策についてご紹介していきたいと思います!
依存関係かく乱攻撃について
依存関係かく乱攻撃(Dependency Confusion Attack)は、悪意ある第三者が、企業内部で使われているプライベートな依存関係と外部の公共パッケージとの間にある名前の競合を利用するセキュリティ攻撃です。この攻撃の目的は、組織が誤って悪意のあるコードを含むパッケージをダウンロードして実行することを引き起こすことにあります。
図を用いて具体的に説明します。
ある開発組織では、組織内部で利用する内部プライベートレポジトリを持っており、ここで内部パッケージ(ここの例では @dws/my-package
と言う名前のパッケージ)を管理しています。ここで、攻撃者は悪意のあるコードを含んだ同名のパッケージをパブリックレポジトリへと事前に公開しておきます。開発組織にて、アプリケーションを開発する上で、この@dws/my-package
を利用するために内部プライベートレポジトリを参照すべきところを、誤ってパブリックレポジトリを参照してしまうことで、悪意のあるコードが開発者の持つ開発環境やビルド環境にて実行されることにより、攻撃が成立します。
CodeArtifact 新機能:パッケージグループについて
2024年3月に、CodeArtifactの新しい機能である、パッケージグループが設定出来るようになりました。このパッケージグループでは、パッケージの名前空間をターゲットとして、CodeArtifactレポジトリの上流レポジトリからの取り込みを制御できるようになる(オリジン制御)ため、今回はこのパッケージグループを利用して、依存関係かく乱攻撃に対する対策を行って見ることにします。
CodeArtifactを用いた依存関係かく乱攻撃への対策
今回は、サンプルの環境をご用意しました。
ソースコードはこちらに公開してあります。
こちらのサンプルコードで作成できる全体的な構成は以下の図の通りとなっています。
サンプルコードでは、Node.jsアプリケーションのビルドを行う内容になっています。Node.jsアプリケーションは、ビルド前に npm install
コマンドを実行することにより、通常であればパブリックのnpmレポジトリに対して依存するパッケージを取得することになりますが、このサンプルでは、CodeArtifactレポジトリから依存するパッケージを取得するようにしています。
このCodeArtifactレポジトリは2段構成となっており、それぞれ図では npm-staging
、 my-repo
という名前が付いており、それぞれ以下のような用途を想定しています。
npm-staging
: パブリックnpmレポジトリを上流とし、ここでパッケージの事前検証を行う。my-repo
: アプリケーションの構築時に参照されるレポジトリ。
ビルドパイプラインについて説明します。 ソースコードはCodeCommitに保存され、それをソースとして、まずは npm install
を実行するCodeBuild Actionが実行されます。こちらのCodeBuild Actionは、専用のVPCが用意され、VPC Interface Endpoint経由でCodeArtifactレポジトリにアクセス可能となっています。またプライベートサブネットに配置されることによって、npmのパブリックレポジトリを参照出来ないようになっています。
2つめのCodeBuild Actionは、前段のCodeBuild Actionで実施した npm install
後のアーティファクトを元に、コンテナイメージビルドを実施します。ビルドした結果はECRへとPushされます。
CodeArtifactレポジトリまわりについて詳しく説明します。
CodeArtifactレポジトリはnpm-staging
、 my-repo
の以下の2段構成となっています。
npm-staging
: パブリックnpmレポジトリを上流とし、ここでパッケージの事前検証を行う。my-repo
: アプリケーションの構築時に参照されるレポジトリ。
前提として、この開発組織は、内部npmパッケージにおいて @dws
という名前空間を使用している物とします。
この構成では、前述のパッケージグループの設定にて @dws/*
の名前空間パターンに対して、上流からの取得を禁止するように設定しています。この設定により、CodeArtifactレポジトリに対して、内部プライベートレポジトリにしか存在しない想定の @dws
名前空間を持つパッケージの取得が禁止する事が出来ます。
さらに、CI/CDパイプラインとして設定してある、 npm install
コマンドを実行するCodeBuild Actionをプライベートサブネットにて実行することで、インターネット上にあるnpmパブリックレポジトリに対するアクセスが出来ないようになります。
この2つの合わせ技により、CI/CDパイプラインにおける依存関係かく乱攻撃への対策が出来ることになります。
サンプルコードの実行
ソースコードの取得
以下のコマンドでCloneしてください。
git clone https://github.com/tak-kam/codeartifact-cdk-sample
cd codeartifact-cdk-sample
インフラストラクチャーのデプロイ
デプロイ
次にインフラストラクチャーをAWSにデプロイするために、以下のコマンドを実行してください。(AWS認証情報の設定は事前に設定お願いします。)
# モジュールのインストール
npm install
# インフラストラクチャーのデプロイ
npm run deploy:repo
npm run deploy
CodeArtifactへの内部パッケージ公開
次に、CodeArtifactへ内部パッケージである @dws/sample-package
を公開します。
そのために、まずはnpmクライアントをCodeArtifactに対してログインさせる必要があります。
CodeArtifactの画面からリポジトリ「my-repo」を開き「接続手順の表示」ボタンを押した後、自分の環境にあわせたオペレーティングシステムを選択、パッケージマネージャのクライアントはnpmを選択し、ダイアログ下部にあるコピーボタンを押し、ターミナルにて実行してください。
CodeArtifactへのログインが済んだら、以下のコマンドを実行してCodeArtifactレポジトリへ内部パッケージを公開しましょう。
cd sample-package
npm publish
cd -
公開が成功したら、AWSコンソールでも my-repo レポジトリにて sample-package が公開されていることが確認出来るかと思います。
ビルドパイプラインの実行
実際にビルドパイプラインを実行し、CodeBuild ActionにてCodeArtifactレポジトリを利用できているかどうかを確認してみましょう。
ビルドパイプラインを実行するためには、デプロイされているCodeCommitレポジトリへソースコードをPushすることが必要になります。
CodeCommitを利用するためには、git-remote-codecommit を利用すると認証情報の管理が楽になるのでお勧めです。利用する場合は以下のコマンドを実行してください。
# git-remote-codecommit のインストール
pip install git-remote-codecommit
次に、サンプルアプリケーションをCodeCommitにもPushしましょう。
AWSコンソールより、デプロイされたCodeCommitレポジトリ「MyGitRepository」を開き、画面右上あたりにある「URLのクローン」ボタンにより、GitのURLをコピーします。
git-remote-commit を利用する場合は、 「HTTPSのクローン(GRC)」を選択してください。
URLがコピーされたら、以下のコマンドで git remote を追加し、CodeCommitへとソースコードをPushしてください。
# git remote の追加
git remote add codecommit {コピーされたURLをここに貼り付け}
# 以下は git-remote-commit を利用した場合の例
# git remote add codecommit codecommit::ap-northeast-1://MyGitRepository
# CodeCommitへソースコードのPush
git push codecommit
CodeCommitへのPushが終わると、それをトリガとしてCodePipelineが動作し、ビルドが始まります。AWSコンソールのCodePipeline「MyPipeline」を開き、画面にてパイプラインが動作していることを確認してください。
パイプラインの実行が終了したら、「NpmInstallAction」の「詳細を表示」ボタンを押してログを確認してみましょう。
ログ上でも、CodeArtifactへログイン&npm install が成功していることが確認出来ました!
まとめと考察
以上、CodeArtifactを利用して依存関係かく乱攻撃への対策をご紹介しました!
CodeArtifactでは、あとはタイポスクワッティングへの対策が出来ればと言うところですが、こちらはホワイトリスト形式でのパッケージ許可管理などを行わないといけないため、難しいところでしょうか・・・。こういう領域こそ、AIでの判定が生きてくるのかもしれませんね。今後の機能拡張に期待したいところです。
以上、有り難うございました!