概要
本記事はQualiArts Advent Calendar 2024の6日目の記事です。
株式会社QualiArtsでバックエンドエンジニアをやっている末吉と申します。今回はGitHub Actionsの運用方法ついて書いていこうと思います。
GitHub Actionsを使用するとCI/CDが簡単に実装できる反面、攻撃されてしまうと自社の資産に対して重要な被害をもたらす可能性があります。
(ここでいう資産とはコードや、Secretsで登録しているクレデンシャル、Dockerイメージなどの成果物を指しています)
そこで今回はGitHub Actionsでセキュリティに役立つテクニックをいくつか紹介させていただきます。
尚、本記事ではGitHub Actionsの基本は割愛させていただきます。
①Permissionsをワークフローの中で明示的に指定する
突然ですが、ここで質問です。
下記のコードにおけるtestジョブはコードの読み取りまで可能なのか、書き込みまで可能なのかだとどちらでしょうか?
尚、privateなリポジトリに置かれているものとします。
name: Test
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Test
run: echo "hoge"
正解は「リポジトリのデフォルト権限による」です。
実は、GITHUB_TOKENのデフォルトの権限はリポジトリの出来上がった時期によってバラバラです。
Settings > Actions > Generalにて、Workflow Permissionsが
- Read and write permissionsなら全てのパーミッションで読み書きOK
- Read repository contents and packages permissionsならコードとパッケージ読みOK
となっています。セキュアなのは後者のRead repository contents and packages permissionsです。
当然ここのデフォルトの設定を変えた方が良いのは間違いないのですが、そもそも明示的にワークフローの中でPermissionsを書いておくことでデフォルトの挙動に左右されず、チーム内で権限を意識した運用をすることができます。
先ほどのワークフローだと、checkoutが出来れば良いのでコードの読み取りだけ許可すればOKです。
name: Test
jobs:
test:
runs-on: ubuntu-latest
permissions:
contents: read ← これを追加
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Test
run: echo "hoge"
また、最小権限の法則からjobごとに書くのをオススメします。
下記のようにworkflowレベルで書くと、本来コードの読み取りが必要ないJobに対しても権限を付与してしまうからです。
name: Test
permission:
contents: read ← workflowレベルで書くのは良くない
jobs:
②サードパーティーアクションをコミットハッシュで固定する
name: Test
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Test
run: echo "hoge"
上記のactions/checkout@v4はGitタグを参照しています。
これ自体はよくあるのですが、忘れてはいけないのがGitタグは可変であるということです。
対象のリポジトリに悪意あるコードを忍び込ませた上でv4.0.0などをpushすることができます。
そのため、同じコードを使用できるという保証がありません。
そこで有効なのが、コミットハッシュで固定してしまうことです。
GitHubのハッシュアルゴリズムにはSHA-1を使用されているので、値がぶつかる可能性は限りなく低いからです。
name: Test
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Test
run: echo "hoge"
③こまめにアップデートを行う
最後はありきたりなことを書いてしまいましたが、こまめにアップデートを行うことが大切です。
ソフトウェアでは脆弱性が見つかると対応のパッチバージョンがリリースされると思うのですが、あまりにも古いマイナー、メジャーバージョンは対象外になっていることがあります。
その時にverがかけ離れているのを取り戻すのは工数も大きく、こまめにアップデートしている状態より格段に時間がかかります。作業に時間がかかってしまうと、その間に脆弱性を突かれて攻撃されてしまう可能性があります。
定期的にアップデートを行うことで、脆弱性が見つかった時にすぐに対応できるようになるでしょう。
とはいえ開発の合間に並行してアップデート作業を行うのも大変だとは思うので、Dependabotのauto mergeなどを活用するのをオススメします。
終わりに
本記事では3つほどテクニックを紹介しました。
運用のお役に立てたら幸いです。