Colima(Lima + Docker)で開発をしてみている

ふとDocker Desktop for Mac以外の環境でDockerイメージを使った開発できるか試したくなったのでやってみています。

私が今選択しているのは Colima というツールです(このエントリ時点でv0.2.2です)。

github.com

Colimaは何をしているかというとLimaとDocker(や、必要に応じてcontainerdやKubernatesも)をいい感じに設定してくれるツールです*1

Lima

LimaはmacOS上でLinuxVMを起動して使えるようにしてくれるツールです。

github.com

READMEでは

Lima can be considered as a some sort of unofficial "macOS subsystem for Linux", or "containerd for Mac".

と書いてありますので、上記のようなイメージを持ってもらうと良さそうです。

Colima

Limaだけでも便利なのですが、Colimaはそこからさらに1コマンドで

  • Limaの設定ファイルを生成してLinux環境を作ってくれる
  • Linux on Limaの環境にDockerをインストールしてセットアップしてくれる
  • ホスト側(つまりmacOS側)のDocker CLIとDocker on Linux on Limaを透過的に接続できるような設定をホスト側にしてくれる

ということをしてくれます。

Colimaのはじめ方

1. Docker Desktop for Mac のアンインストール

まず、Docker Desktop for Macをアンインストールする必要があります。これが一番大きな障壁かもです。

FAQにも

Can it run alongside Docker for Mac?

No, except when started with Containerd runtime. Colima assumes to be the default Docker context and will conflict with Docker for Mac. You should run either, not both.

とあり、Colimaの「Docker CLIとDocker on Linux on Limaを透過的に接続できるような設定」が競合すると思われます。

ちなみに、全く保証はできませんが 私の環境では、Docker Desktop for Macをアンインストールしても、再インストールしたら使っていたDockerコンテナやDockerイメージは残っていました。「試しにColimaを使ってみる」もできそうです。 全く保証はできませんが

とりあえず、Docker Desktop for Macをアンインストールする必要があります。

私の場合はDocker Desktop for MacをHomebrew Caskでインストールしていたので、以下のコマンドを実行してアンインストールしました。

$ brew uninstall --casks docker

2. Colima(とLima)とDockerのインストール

Homebrewで以下をインストールします。

  • Colima(と依存しているLima)
  • ホスト側で docker コマンドと docker compose コマンドを使うためのDockerとdocker-compose
$ brew install colima docker docker-compose
$ ln -sfn $(brew --prefix docker-compose)/bin/docker-compose ~/.docker/cli-plugins/docker-compose # docker-composeを `docker compose` とサブコマンドとして実行できるようにするためにsymlink

3. colima start でDocker on Linux on Limaを起動

あとはColimaを通じてLima上のLinuxを起動して、その上でDockerデーモンを起動するだけです。

Colimaは起動時にVMで使用するコンピューティングリソースやマウントするホスト側のディレクトリを指定できます。指定した設定はLimaの設定ファイルに反映されます*2

私は以下のように実行しています。

$ colima start --cpu 8 --memory 8 --disk 128 --mount '~/src:w' --mount '~/tmp:w'

特に、私はソースコードghq~/src 以下に置いているので --mount ~/src:w というように :w を渡して書き込み可能にしています*3

あとは普通にホスト側から docker ps なり docker pull なりすれば良いです。

たったこれだけです。今までと同じようにDockerなのも良いと感じています。

Colima環境の現時点の課題

今2週間ほどColima環境を使っているのですが、ただ1つを除いて特に問題なくDockerを使った開発ができています*4

その1つの課題というのがホストからマウントしているファイルシステムに関するものです。

ホストとLima VM間はSSHで接続されています。 マウントはsshfsを使用していますし、Colima環境ではホストとDocker on Linux on Limaのdocker.sock の共有もSSHを経由して実行されています。 そのためホスト側のファイルシステムをLima VMを経由してマウントしているファイルを、Dockerコンテナ内からパーミッション変更などをすると失敗します。

以下のIssueが上記の問題に関係するものだと思います。

github.com

環境によっては厳しい条件かもしれません。私の場合は今のところはワークアラウンドは考えたり手元でそのワークアラウンドを適用したりできているので大丈夫です。ただ少し面倒ですね。

というわけで

Colimaの利用レポートでした。

*1:v0.1.xまではBashで書かれていたのですが、最近v0.2.xからGoでリライトされました。それくらいシンプルです

*2:デフォルトだと ~/.lima/colima/lima.yml になると思います

*3:前までは--mountオプションはなく、Limaの設定ファイルを書き換える必要があったのですが、https://github.com/abiosoft/colima/pull/17 を通じて機能要望をし、v0.2で導入してもらいました

*4:この間に更新しているOSSなDockerイメージなどは全部Colima環境です。 https://github.com/k1LoW?tab=packages

YAMLファイルの全ての値にos.Expandenv(os.Expand)を適用するgithub.com/k1LoW/expandを作った

私は作るツールの設定ファイルのフォーマットをYAMLにすることが多いです。

そして各値で環境変数を展開できるようにする機能を追加することがあります。

以下のような設定ファイルを読み込んだ際に、 ${COVERAGE_ACCEPTABLE}${COVERAGE_BADGE_PATH}環境変数から読み込んで変数展開してあげる機能を追加します。

coverage:
  acceptable: ${COVERAGE_ACCEPTABLE}
  badge:
    path: ${COVERAGE_BADGE_PATH}
comment:
  enable: ${COMMENT_ENABLE}

値が文字列であればYAMLファイルをエンコードしてから os.Expandenv を呼べばいいですし、今まではそのように作っていたのですが以下のような課題がありました。

数値や真偽値の変数展開の実装が面倒

${xxxxx} はどう見ても文字列なので、数値や真偽値の変数展開を実現するためにはUnmarshalする際に一工夫が必要になります。

そこまでの実装のモチベーションが持てず、大抵「環境変数展開対象外」にしていました。

os.Expandenv をひたすら書く必要がある

YAMLの文字列を構造体に変更した後に変数展開をする場合、os.Expandenvを各値に対してひたすら適用する必要があります*1。適用漏れもあったり。

そういったYAMLを設定ファイルに採用しているツールが手元に増えてきたので、YAMLファイルの全ての値に対してos.Expandenv(os.Expand)を適用する関数を作ってみました。

github.com

github.com/k1LoW/expand

使い方は簡単で、以下のように expand.Expand* を呼べば []byte や string なYAMLの各値にだけos.Expandenv(os.Expand)を適用します。

c := &Config{}
p := "config.yml"
buf, err := os.ReadFile(p)
if err != nil {
    return err
}
if err := yaml.Unmarshal(expand.ExpandenvYAMLBytes(buf), c); err != nil {
    return err
}

提供している関数は expand package - github.com/k1LoW/expand - pkg.go.dev をみてください。

実装は、ありがたいことに github.com/goccy/go-yaml が Lexer をpublicなAPIとして公開してくれているので、それを利用させてもらっています。 Lexer の活用事例として ycat があり、かなり参考にさせてもらいました*2

github.com

今後

せっかくYAMLのための関数を作ったので、他のフォーマットや構造体の関数も作ってみようかなとは思いました。思っただけです。

もし何かあればフィードバックもらえると嬉しいです。

*1:全ての値を走査するために「reflectを使って再帰的に」という手段もあるとは思います

*2:特に func (p *Printer) PrintTokens(tokens token.Tokens) string。ほぼそのままといってもいいです

メンテナンスが終了しているgithub.com/dgrijalva/jwt-goの脆弱性CVE-2020-26160に対応する

go.modでコミュニティメンテナンスバージョンの github.com/golang-jwt/jwt に replace すれば良さそうです。

replace github.com/dgrijalva/jwt-go => github.com/golang-jwt/jwt v3.2.2+incompatible

github.com/dgrijalva/jwt-goは様々なパッケージで利用されており、自分のアプリケーションで直接利用しているわけではなくても依存に含まれることがあります。 どうしようかなーと思っていたのですが、コミュニティでメンテナンスされていることを知ったのでreplaceしました。

全方位に感謝。

GitHub Actionsのサプライチェーンを構成しているDockerイメージやサードパーティActionのコード対して任意のコマンドを実行するツールを作ってみた

注意: 本エントリで紹介するツールは現時点でPoCな実装であり、効果や効率を保証するものではありません。


ちょっと前に社内でGitHub Actionsのサプライチェーン攻撃についての話題があがって、「なるほどー。今時は、リポジトリのコードだけの脆弱性や第三者コードの混入とかだけを気にしていても足りない時があるのか」いう感想でした。

いろいろな軽減策が提案されているので*1基本的にそれらを実践するが良いとする上で、「GitHub Actionsのサプライチェーンをたどって脆弱性スキャンとか危険なコード混入をチェックできたら意味あったりするかなあ」とふと思って、その「GitHub Actionsのサプライチェーンをたどる」というところに興味がでてきたのでツールとして作ってみました。

github.com

oshka

oshka*2の振る舞いは以下の通りです。

  1. 指定したディレクトリ( fs )や、リポジトリrepo )、アクション( action )、Dockerイメージ( image )をローカルのファイルシステムのテンポラリディレクトリに展開する。
  2. 1で展開したテンポラリディレクトリに対して指定のコマンド(デフォルトは trivy fs . --exit-code 1 )を実行する。
  3. 展開したディレクトリからGitHub Actionsのサプライチェーンを解析して( .github/workflows/*.yml とか action.yml とか、action.ymlで使っているDockerfileとか)、構成しているDockerイメージやサードパーティActionを特定する。
  4. 3で特定したDockerイメージやサードパーティActionをローカルのファイルシステムのテンポラリディレクトリに展開する。
  5. 4で展開したテンポラリディレクトリに対して指定のコマンド(デフォルトは trivy fs . --exit-code 1 )を実行する。
  6. 3-5を指定の深さ( --depth、デフォルトは1)繰り返す。
  7. 実行結果のサマリを出力する。

使い方

インストールは簡単でHomebrewだと

$ brew install k1LoW/tap/oshka

です。

デフォルトコマンドにTrivyを採用しているので合わせてTrivyのインストールもしてください。

実際に実行してみると面白くて「これがサプライチェーンかー」となります。

試しに oshka のリポジトリに対して実行してみます。

$ oshka run repo k1LoW/oshka

2021-09-02T07:26:34+09:00 [INFO] Create temporary directory for extracting supply chains: /var/folders/fp/hk95_wsj7s18mmc9drvrxdp1tt294n/T/
2021-09-02T07:26:34+09:00 [INFO] Extract repo github.com/k1LoW/oshka to /var/folders/fp/hk95_wsj7s18mmc9drvrxdp1tt294n/T/github.com/k1LoW/oshka
Enumerating objects: 131, done.
Counting objects: 100% (131/131), done.
Compressing objects: 100% (92/92), done.
Total 131 (delta 41), reused 85 (delta 14), pack-reused 0
2021-09-02T07:26:35+09:00 [INFO] Run `trivy fs --exit-code 1 .` on /var/folders/fp/hk95_wsj7s18mmc9drvrxdp1tt294n/T/github.com/k1LoW/oshka
2021-09-02T07:26:35.864+0900    INFO    Using your github token
2021-09-02T07:26:35.866+0900    INFO    Need to update DB
2021-09-02T07:26:35.866+0900    INFO    Downloading DB...
3.17 MiB / 23.43 MiB [------------------------>_______________________________________________________________________________________________________________________________________________________________] 13.55% ? p/s ?9.22 MiB / 23.43 MiB [------------------------------------------------------------------------>_______________________________________________________________________________________________________________] 39.36% ? p/s ?14.48 MiB / 23.43 MiB [----------------------------------------------------------------------------------------------------------------->_____________________________________________________________________] 61.80% ? p/s ?20.04 MiB / 23.43 MiB [------------------------------------------------------------------------------------------------------------------------------------------------->________________________] 85.53% 28.05 MiB p/s ETA 0s23.43 MiB / 23.43 MiB [-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------] 100.00% 33.59 MiB p/s 1s2021-09-02T07:26:37.914+0900    INFO    Number of language-specific files: 1
2021-09-02T07:26:37.914+0900    INFO    Detecting gomod vulnerabilities...

go.sum (gomod)
==============
Total: 18 (UNKNOWN: 3, LOW: 0, MEDIUM: 7, HIGH: 8, CRITICAL: 0)

+------------------------------------+------------------+----------+-----------------------------------+---------------------------------------+-----------------------------------------+
|              LIBRARY               | VULNERABILITY ID | SEVERITY |         INSTALLED VERSION         |             FIXED VERSION             |                  TITLE                  |
+------------------------------------+------------------+----------+-----------------------------------+---------------------------------------+-----------------------------------------+
| github.com/apache/thrift           | CVE-2019-0205    | HIGH     | 0.12.0                            | 0.13.0                                | thrift: Endless loop when               |
|                                    |                  |          |                                   |                                       | feed with specific input data           |
|                                    |                  |          |                                   |                                       | -->avd.aquasec.com/nvd/cve-2019-0205    |
+                                    +------------------+          +                                   +                                       +-----------------------------------------+
|                                    | CVE-2019-0210    |          |                                   |                                       | thrift: Out-of-bounds read              |
|                                    |                  |          |                                   |                                       | related to TJSONProtocol                |
|                                    |                  |          |                                   |                                       | or TSimpleJSONProtocol                  |
|                                    |                  |          |                                   |                                       | -->avd.aquasec.com/nvd/cve-2019-0210    |
+                                    +------------------+          +                                   +---------------------------------------+-----------------------------------------+
|                                    | CVE-2020-13949   |          |                                   | v0.14.0                               | libthrift: potential DoS when           |
|                                    |                  |          |                                   |                                       | processing untrusted payloads           |
|                                    |                  |          |                                   |                                       | -->avd.aquasec.com/nvd/cve-2020-13949   |
+------------------------------------+------------------+          +-----------------------------------+---------------------------------------+-----------------------------------------+
| github.com/buger/jsonparser        | CVE-2020-10675   |          | 0.0.0-20180808090653-f4dd9f5a6b44 | v0.0.0-20200321185410-91ac96899e49    | golang-github-buger-jsonparser:         |
|                                    |                  |          |                                   |                                       | infinite loop via a Delete call         |
|                                    |                  |          |                                   |                                       | -->avd.aquasec.com/nvd/cve-2020-10675   |
+                                    +------------------+          +                                   +---------------------------------------+-----------------------------------------+
|                                    | CVE-2020-35381   |          |                                   | v1.1.1                                | jsonparser: GET call can lead to        |
|                                    |                  |          |                                   |                                       | a slice bounds out of range...          |
|                                    |                  |          |                                   |                                       | -->avd.aquasec.com/nvd/cve-2020-35381   |
+------------------------------------+------------------+----------+-----------------------------------+---------------------------------------+-----------------------------------------+
| github.com/containerd/containerd   | CVE-2021-32760   | MEDIUM   | 1.5.3                             | v1.4.8, v1.5.4                        | containerd: pulling and                 |
|                                    |                  |          |                                   |                                       | extracting crafted container            |
|                                    |                  |          |                                   |                                       | image may result in Unix file...        |
|                                    |                  |          |                                   |                                       | -->avd.aquasec.com/nvd/cve-2021-32760   |
+------------------------------------+------------------+----------+-----------------------------------+---------------------------------------+-----------------------------------------+
| github.com/dgrijalva/jwt-go        | CVE-2020-26160   | HIGH     | 3.2.0+incompatible                |                                       | jwt-go: access restriction              |
|                                    |                  |          |                                   |                                       | bypass vulnerability                    |
|                                    |                  |          |                                   |                                       | -->avd.aquasec.com/nvd/cve-2020-26160   |
+------------------------------------+------------------+----------+-----------------------------------+---------------------------------------+-----------------------------------------+
| github.com/gorilla/handlers        | GO-2020-0020     | UNKNOWN  | 0.0.0-20150720190736-60c7bfde3e33 | v1.3.0                                |                                         |
+------------------------------------+------------------+----------+-----------------------------------+---------------------------------------+-----------------------------------------+
| github.com/miekg/dns               | CVE-2019-19794   | MEDIUM   | 1.0.14                            | v1.1.25-0.20191211073109-8ebf2e419df7 | golang-github-miekg-dns: predictable    |
|                                    |                  |          |                                   |                                       | TXID can lead to response forgeries     |
|                                    |                  |          |                                   |                                       | -->avd.aquasec.com/nvd/cve-2019-19794   |
+------------------------------------+------------------+----------+-----------------------------------+---------------------------------------+-----------------------------------------+
| github.com/sassoftware/go-rpmutils | CVE-2020-7667    | HIGH     | 0.0.0-20190420191620-a8f1baeba37b | v0.1.0                                | In package                              |
|                                    |                  |          |                                   |                                       | github.com/sassoftware/go-rpmutils/cpio |
|                                    |                  |          |                                   |                                       | before version 0.1.0, the               |
|                                    |                  |          |                                   |                                       | CPIO extraction functionality           |
|                                    |                  |          |                                   |                                       | doesn't sanitize...                     |
|                                    |                  |          |                                   |                                       | -->avd.aquasec.com/nvd/cve-2020-7667    |
+------------------------------------+------------------+----------+-----------------------------------+---------------------------------------+-----------------------------------------+
| github.com/satori/go.uuid          | GO-2020-0018     | UNKNOWN  | 1.2.0                             | v1.2.1-0.20181016170032-d91630c85102  |                                         |
+------------------------------------+------------------+----------+-----------------------------------+---------------------------------------+-----------------------------------------+
| github.com/ulikunitz/xz            | CVE-2021-29482   | HIGH     | 0.5.7                             | v0.5.8                                | ulikunitz/xz: Infinite                  |
|                                    |                  |          |                                   |                                       | loop in readUvarint allows              |
|                                    |                  |          |                                   |                                       | for denial of service                   |
|                                    |                  |          |                                   |                                       | -->avd.aquasec.com/nvd/cve-2021-29482   |
+                                    +------------------+----------+                                   +                                       +-----------------------------------------+
|                                    | GO-2020-0016     | UNKNOWN  |                                   |                                       |                                         |
+------------------------------------+------------------+----------+-----------------------------------+---------------------------------------+-----------------------------------------+
| k8s.io/kubernetes                  | CVE-2019-1002101 | MEDIUM   | 1.13.0                            | 1.11.9, 1.12.7, 1.13.5,               | kubernetes: Mishandling of              |
|                                    |                  |          |                                   | 1.14.1-beta.0                         | symlinks allows for arbitrary           |
|                                    |                  |          |                                   |                                       | file write via `kubectl cp`...          |
|                                    |                  |          |                                   |                                       | -->avd.aquasec.com/nvd/cve-2019-1002101 |
+                                    +------------------+          +                                   +---------------------------------------+-----------------------------------------+
|                                    | CVE-2019-11250   |          |                                   | v1.16.0-beta.1                        | kubernetes: Bearer tokens               |
|                                    |                  |          |                                   |                                       | written to logs at high                 |
|                                    |                  |          |                                   |                                       | verbosity levels (>= 7)...              |
|                                    |                  |          |                                   |                                       | -->avd.aquasec.com/nvd/cve-2019-11250   |
+                                    +------------------+          +                                   +---------------------------------------+-----------------------------------------+
|                                    | CVE-2020-8554    |          |                                   |                                       | kubernetes: MITM using                  |
|                                    |                  |          |                                   |                                       | LoadBalancer or ExternalIPs             |
|                                    |                  |          |                                   |                                       | -->avd.aquasec.com/nvd/cve-2020-8554    |
+                                    +------------------+          +                                   +---------------------------------------+-----------------------------------------+
|                                    | CVE-2020-8564    |          |                                   | v1.20.0-alpha.1                       | kubernetes: Docker config               |
|                                    |                  |          |                                   |                                       | secrets leaked when file is             |
|                                    |                  |          |                                   |                                       | malformed and loglevel >=...            |
|                                    |                  |          |                                   |                                       | -->avd.aquasec.com/nvd/cve-2020-8564    |
+                                    +------------------+          +                                   +---------------------------------------+-----------------------------------------+
|                                    | CVE-2020-8565    |          |                                   | v1.20.0-alpha.2                       | kubernetes: Incomplete fix              |
|                                    |                  |          |                                   |                                       | for CVE-2019-11250 allows for           |
|                                    |                  |          |                                   |                                       | token leak in logs when...              |
|                                    |                  |          |                                   |                                       | -->avd.aquasec.com/nvd/cve-2020-8565    |
+------------------------------------+------------------+----------+-----------------------------------+---------------------------------------+-----------------------------------------+
2021-09-02T07:26:37+09:00 [INFO] Detect action actions/setup-go@v2 from /var/folders/fp/hk95_wsj7s18mmc9drvrxdp1tt294n/T/github.com/k1LoW/oshka
2021-09-02T07:26:37+09:00 [INFO] Detect action actions/checkout@v2 from /var/folders/fp/hk95_wsj7s18mmc9drvrxdp1tt294n/T/github.com/k1LoW/oshka
2021-09-02T07:26:37+09:00 [INFO] Detect action golangci/golangci-lint-action@v2 from /var/folders/fp/hk95_wsj7s18mmc9drvrxdp1tt294n/T/github.com/k1LoW/oshka
2021-09-02T07:26:37+09:00 [INFO] Extract action actions/checkout@v2 to /var/folders/fp/hk95_wsj7s18mmc9drvrxdp1tt294n/T/actions/checkout@v2
Enumerating objects: 997, done.
Counting objects: 100% (27/27), done.
Compressing objects: 100% (20/20), done.
Total 997 (delta 10), reused 11 (delta 6), pack-reused 970
2021-09-02T07:26:39+09:00 [INFO] Run `trivy fs --exit-code 1 .` on /var/folders/fp/hk95_wsj7s18mmc9drvrxdp1tt294n/T/actions/checkout@v2
2021-09-02T07:26:39.114+0900    INFO    Using your github token
2021-09-02T07:26:39.177+0900    INFO    Number of language-specific files: 1
2021-09-02T07:26:39.177+0900    INFO    Detecting npm vulnerabilities...

package-lock.json (npm)
=======================
Total: 3 (UNKNOWN: 0, LOW: 0, MEDIUM: 2, HIGH: 1, CRITICAL: 0)

+---------------+------------------+----------+-------------------+---------------------+---------------------------------------+
|    LIBRARY    | VULNERABILITY ID | SEVERITY | INSTALLED VERSION |    FIXED VERSION    |                 TITLE                 |
+---------------+------------------+----------+-------------------+---------------------+---------------------------------------+
| @actions/core | CVE-2020-15228   | MEDIUM   | 1.1.3             | 1.2.6               | Environment Variable                  |
|               |                  |          |                   |                     | Injection in GitHub Actions           |
|               |                  |          |                   |                     | -->avd.aquasec.com/nvd/cve-2020-15228 |
+---------------+------------------+          +-------------------+---------------------+---------------------------------------+
| node-fetch    | CVE-2020-15168   |          | 2.6.0             | 3.0.0-beta.9, 2.6.1 | node-fetch: size of data after        |
|               |                  |          |                   |                     | fetch() JS thread leads to DoS        |
|               |                  |          |                   |                     | -->avd.aquasec.com/nvd/cve-2020-15168 |
+---------------+------------------+----------+-------------------+---------------------+---------------------------------------+
| underscore    | CVE-2021-23358   | HIGH     | 1.8.3             | 1.12.1              | nodejs-underscore: Arbitrary code     |
|               |                  |          |                   |                     | execution via the template function   |
|               |                  |          |                   |                     | -->avd.aquasec.com/nvd/cve-2021-23358 |
+---------------+------------------+----------+-------------------+---------------------+---------------------------------------+
2021-09-02T07:26:39+09:00 [INFO] Extract action golangci/golangci-lint-action@v2 to /var/folders/fp/hk95_wsj7s18mmc9drvrxdp1tt294n/T/golangci/golangci-lint-action@v2
Enumerating objects: 1342, done.
Counting objects: 100% (431/431), done.
Compressing objects: 100% (237/237), done.
Total 1342 (delta 329), reused 272 (delta 192), pack-reused 911
2021-09-02T07:26:40+09:00 [INFO] Run `trivy fs --exit-code 1 .` on /var/folders/fp/hk95_wsj7s18mmc9drvrxdp1tt294n/T/golangci/golangci-lint-action@v2
2021-09-02T07:26:40.707+0900    INFO    Using your github token
2021-09-02T07:26:40.764+0900    INFO    Number of language-specific files: 2
2021-09-02T07:26:40.764+0900    INFO    Detecting gomod vulnerabilities...
2021-09-02T07:26:40.765+0900    INFO    Detecting npm vulnerabilities...

package-lock.json (npm)
=======================
Total: 0 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 0)


sample-go-mod/go.sum (gomod)
============================
Total: 4 (UNKNOWN: 0, LOW: 0, MEDIUM: 1, HIGH: 3, CRITICAL: 0)

+-----------------------------+------------------+----------+-----------------------------------+---------------------------------------+---------------------------------------+
|           LIBRARY           | VULNERABILITY ID | SEVERITY |         INSTALLED VERSION         |             FIXED VERSION             |                 TITLE                 |
+-----------------------------+------------------+----------+-----------------------------------+---------------------------------------+---------------------------------------+
| github.com/dgrijalva/jwt-go | CVE-2020-26160   | HIGH     | 3.2.0+incompatible                |                                       | jwt-go: access restriction            |
|                             |                  |          |                                   |                                       | bypass vulnerability                  |
|                             |                  |          |                                   |                                       | -->avd.aquasec.com/nvd/cve-2020-26160 |
+-----------------------------+------------------+          +-----------------------------------+---------------------------------------+---------------------------------------+
| github.com/gogo/protobuf    | CVE-2021-3121    |          | 1.2.1                             | v1.3.2                                | gogo/protobuf:                        |
|                             |                  |          |                                   |                                       | plugin/unmarshal/unmarshal.go         |
|                             |                  |          |                                   |                                       | lacks certain index validation        |
|                             |                  |          |                                   |                                       | -->avd.aquasec.com/nvd/cve-2021-3121  |
+-----------------------------+------------------+----------+-----------------------------------+---------------------------------------+---------------------------------------+
| github.com/miekg/dns        | CVE-2019-19794   | MEDIUM   | 1.0.14                            | v1.1.25-0.20191211073109-8ebf2e419df7 | golang-github-miekg-dns: predictable  |
|                             |                  |          |                                   |                                       | TXID can lead to response forgeries   |
|                             |                  |          |                                   |                                       | -->avd.aquasec.com/nvd/cve-2019-19794 |
+-----------------------------+------------------+----------+-----------------------------------+---------------------------------------+---------------------------------------+
| golang.org/x/crypto         | CVE-2020-29652   | HIGH     | 0.0.0-20200622213623-75b288015ac9 | v0.0.0-20201216223049-8b5274cf687f    | golang: crypto/ssh: crafted           |
|                             |                  |          |                                   |                                       | authentication request can            |
|                             |                  |          |                                   |                                       | lead to nil pointer dereference       |
|                             |                  |          |                                   |                                       | -->avd.aquasec.com/nvd/cve-2020-29652 |
+-----------------------------+------------------+----------+-----------------------------------+---------------------------------------+---------------------------------------+
2021-09-02T07:26:40+09:00 [INFO] Extract action actions/setup-go@v2 to /var/folders/fp/hk95_wsj7s18mmc9drvrxdp1tt294n/T/actions/setup-go@v2
Enumerating objects: 1043, done.
Counting objects: 100% (39/39), done.
Compressing objects: 100% (31/31), done.
Total 1043 (delta 13), reused 19 (delta 3), pack-reused 1004
2021-09-02T07:26:41+09:00 [INFO] Run `trivy fs --exit-code 1 .` on /var/folders/fp/hk95_wsj7s18mmc9drvrxdp1tt294n/T/actions/setup-go@v2
2021-09-02T07:26:41.822+0900    INFO    Using your github token
2021-09-02T07:26:41.883+0900    INFO    Number of language-specific files: 1
2021-09-02T07:26:41.883+0900    INFO    Detecting npm vulnerabilities...

package-lock.json (npm)
=======================
Total: 0 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 0)

2021-09-02T07:26:41+09:00 [INFO] Cleanup temporary directory for extracting supply chains: /var/folders/fp/hk95_wsj7s18mmc9drvrxdp1tt294n/T/

Run results
===========
+----------------------------------+--------+--------------------------+-----------+-------+------------------------------------------+
|               NAME               |  TYPE  |         COMMAND          | EXIT CODE | DEPTH |                   HASH                   |
+----------------------------------+--------+--------------------------+-----------+-------+------------------------------------------+
| github.com/k1LoW/oshka           | repo   | trivy fs --exit-code 1 . | 1         | 0     | ca36be55f7fcfbc31cc7dc5e80b6fb7d01c53981 |
|                                  |        |                          |           |       | (commit hash)                            |
| actions/setup-go@v2              | action | trivy fs --exit-code 1 . | 0         | 1     | 331ce1d993939866bb63c32c6cbbfd48fa76fc57 |
|                                  |        |                          |           |       | (commit hash)                            |
| actions/checkout@v2              | action | trivy fs --exit-code 1 . | 1         | 1     | 5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f |
|                                  |        |                          |           |       | (commit hash)                            |
| golangci/golangci-lint-action@v2 | action | trivy fs --exit-code 1 . | 1         | 1     | 5c56cd6c9dc07901af25baab6f2b0d9f3b7c3018 |
|                                  |        |                          |           |       | (commit hash)                            |
+----------------------------------+--------+--------------------------+-----------+-------+------------------------------------------+
$

--depth 2 にすると、さらに深くサプライチェーンをたどります。

$ oshka run repo k1LoW/oshka --depth 2

[...]

Run results
===========
+----------------------------------+--------+--------------------------+-----------+-------+-------------------------------------------------------------------------+
|               NAME               |  TYPE  |         COMMAND          | EXIT CODE | DEPTH |                                  HASH                                   |
+----------------------------------+--------+--------------------------+-----------+-------+-------------------------------------------------------------------------+
| github.com/k1LoW/oshka           | repo   | trivy fs --exit-code 1 . | 1         | 0     | ca36be55f7fcfbc31cc7dc5e80b6fb7d01c53981                                |
|                                  |        |                          |           |       | (commit hash)                                                           |
| actions/setup-go@v2              | action | trivy fs --exit-code 1 . | 0         | 1     | 331ce1d993939866bb63c32c6cbbfd48fa76fc57                                |
|                                  |        |                          |           |       | (commit hash)                                                           |
| actions/checkout@v2              | action | trivy fs --exit-code 1 . | 1         | 1, 2  | 5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f                                |
|                                  |        |                          |           |       | (commit hash)                                                           |
| golangci/golangci-lint-action@v2 | action | trivy fs --exit-code 1 . | 1         | 1     | 5c56cd6c9dc07901af25baab6f2b0d9f3b7c3018                                |
|                                  |        |                          |           |       | (commit hash)                                                           |
| github/codeql-action/init@v1     | action | trivy fs --exit-code 1 . | 1         | 2     | 33f3438c1d59883f5e769fdf2b6adb6794d91d0f                                |
|                                  |        |                          |           |       | (commit hash)                                                           |
| github/codeql-action/analyze@v1  | action | trivy fs --exit-code 1 . | 1         | 2     | 33f3438c1d59883f5e769fdf2b6adb6794d91d0f                                |
|                                  |        |                          |           |       | (commit hash)                                                           |
| actions/publish-action@v0.1.0    | action | trivy fs --exit-code 1 . | 0         | 2     | 63abd0d521e21329399edb30e8f577a7ab85443c                                |
|                                  |        |                          |           |       | (commit hash)                                                           |
| actions/setup-node@v1            | action | trivy fs --exit-code 1 . | 1         | 2     | f1f314fca9dfce2769ece7d933488f076716723e                                |
|                                  |        |                          |           |       | (commit hash)                                                           |
| alpine/git:latest                | image  | trivy fs --exit-code 1 . | 1         | 2     | sha256:70f7b70d9324314642b324ac79655862656255dd71b4d18357e5a22f76215ade |
|                                  |        |                          |           |       | (digest)                                                                |
| datadog/squid:latest             | image  | trivy fs --exit-code 1 . | 1         | 2     | sha256:f7d19d5e3f4163771291d91de393ce667f2327a3e080c39b9b7ea9e19f91488f |
|                                  |        |                          |           |       | (digest)                                                                |
+----------------------------------+--------+--------------------------+-----------+-------+-------------------------------------------------------------------------+

デフォルトコマンドは trivy fs --exit-code 1 . ですが、全てローカルのファイルシステムのテンポラリディレクトリに展開する実装になっているので、ローカルにインストールされているコマンドならなんでも実行できるはずです。複数コマンドも以下のように指定可能です。

$ oshka run repo k1LoW/tbls -c 'command1' -c 'command2' -c ...

起点とできるのはリポジトリrepo )以外にも、ディレクトリ( fs )やアクション( action )、Dockerイメージ( image )が指定可能です。コマンドの作りはTrivyを参考にしています。

$ oshka run fs .
$ oshka run action actions/cache@v2
$ oshka run image nginx:alpine

というわけで

GitHub Actionsのサプライチェーンをたどって任意のコマンドを実行できるツール oshka を作ってみたというお話でした。

感想としては、

  • これがサプライチェーン
  • Trivyすごい。いろいろスキャンしてくれる。
  • ついでにサードパーティアクションがcommit SHAでピン留めされているか確認する機能を追加すると良さそう
  • ついでにサードパーティアクションでリポジトリリダイレクト*3が発生しているか確認すする機能を追加すると良さそう
  • こういうサプライチェーン攻撃に対する何かしらの機能にニーズがあるならどこかのセキュリティツールが実装してくれたらいいなあ

という感じです。

以上、夏休みの自由研究発表でした。

参考

*1:「参考」の項を参照

*2:oʊʃkə

*3:「参考」の項を参照

Pull Requestベースでgit revertできる pr-revert / pr-revert-action を作った

記事タイトルをみて「え?それもうあるじゃん」と思った方、半分正解で半分不正解かもしれません(私が知らないだけかもしれません)。

マージしたPull Requestをリバート(して新たなPull Requestを作成)する機能はあります。

f:id:k1LoW:20210802231024p:plain

マージ済みのPull Requestのページの上記画像でいうと赤枠の部分にあります。

リバート機能はあります。ただし、Web UI上にだけです。

マージ済みPull Requestを指定してリバートする機能は、実は公式のghコマンドにもGitHub APIにもないのです*1

ところで、開発の現場では必ずPull Requestでレビューを実施したあとマージ、そしてリリースという流れになっていることが多いです。

Pull Requestは何かしらの意味をもったコード差分の塊になっているため、「マージ済みPull Request単位でのリバート」は何かあった場合の有効な選択肢の1つとなります。

というわけで、様々な自動化のための1つのパーツとして「マージ済みPull Request単位でのリバート」を実現する pr-revert を作成しました。

github.com

pr-revert

pr-revertのデフォルトの振る舞いとしては以下の通りです。

  1. 対象のリポジトリ(リモートリポジトリ)を一時的なディレクトリにclone。
  2. リバートコミットを積むブランチ(リバートブランチ)を作成。
  3. Pull Requestをリバート。
  4. リバートブランチをリモートリポジトリにPush。
  5. リバートブランチでPull Requestを作成。
  6. 一時的なディレクトリを削除。

また、事項には以下の環境変数の設定が必要です( GITHUB_TOKEN 以外はGitHub Actions上では自動で設定される値です)。

環境変数 説明 デフォルト値
GITHUB_TOKEN リポジトリのアクセストーク -
GITHUB_REPOSITORY 対象リポジトリ ( owner/repo ) -
GITHUB_SERVER_URL GitHubのWeb UIのURL https://github.com
GITHUB_API_URL GitHub APIのURL https://api.github.com
GITHUB_GRAPHQL_URL GitHub GraphQL APIのURL https://api.github.com/graphql
$ export GITHUB_TOKEN=XXXxxxxxxXXXXxXXXXXXXX
$ export GITHUB_REPOSITORY=owner/repo

あとは、pr-revertコマンドを用途に合わせたオプションをつけて実行するだけです。

マージ済みPull Requestを指定してリバートする

(実装が間違っていなければ)Web UIとほぼ同じ機能になります。

$ pr-revert --number 3

マージされた最新5件のマージ済みPull Requestをまとめてリバートする

複数のマージ済みPull RequestをまとめてリバートするPull Requestを作ることが可能です。

$ pr-revert --latest 5

2時間前までにマージされたPull Requstをまとめてリバートする

期間指定も可能です。

$ pr-revert --until '2 hours'

新しいリバートPull Requestを作らずにブランチのPushだけをする

デフォルトの振る舞いの5番を実施しません。

$ pr-revert --latest 3 --no-pull-request

一時ディレクトリ を削除しない

デフォルトの振る舞いの6番を実施しません。

$ pr-revert --latest 3 --no-cleanup

ブランチを作成せずに直接デフォルトブランチにリバートする

デフォルトの振る舞いの2番を実施しません。

$ pr-revert --latest 3 --no-branch

pr-revert-action

pr-revertは最終的に自動化の一部として使われることを想定しています。GitHub Actionsによる自動化のためにactionも作成しています。

github.com

pr-revertに渡すオプションは全て環境変数で受け取れるようになっているので、例えば workflow_dispatch を作成する場合などは以下のようなワークフローを作成できます。

# .github/workflows/revert.yml
name: Revert

on:
  workflow_dispatch:
    inputs:
      latest:
        description: '--latest: マージ済みPull Requestを何件リバートするか指定してください'
        required: false
      until:
        description: '--until: マージ済みPull Requestをどれくらいの期間リバートするか指定してください'
        required: false
      number:
        description: '--number: マージ済みPull Requestの番号を指定してください'
        required: false

jobs:
  revert:
    runs-on: ubuntu-latest
    steps:
      -
        uses: k1LoW/pr-revert-action@v0
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          PR_REVERT_LATEST: ${{ github.event.inputs.latest }}
          PR_REVERT_UNTIL: ${{ github.event.inputs.until }}
          PR_REVERT_NUMBER: ${{ github.event.inputs.number }}

というわけで

とりあえずパーツを作っただけですが、これからこれをうまく組み込んで、いろいろ作ってみたいと思っています(まだ)。

もし使ってみた方が現れましたらフィードバックお待ちしています。

*1:2021年7月時点で少なくとも私が探した限りは見つかりませんでした。

第8回Web System Architecture研究会に参加して「システムの変化に追従可能でかつ理解し易いドキュメントシステムのモデル化」について発表した #wsa研

wsa.connpass.com

オンライン開催に参加してきました。

予稿

github.com

発表資料

システムの変化に追従可能でかつ理解し易いドキュメントシステム

発表内容はドキュメントシステム(ドキュメンテーションツール)についてです。

私は、システムを理解するためにかかる時間(いわゆる「オンボーディングまでのコスト」。私は「開発開始までのオーバーヘッド」と呼んでいます)をいかに継続的に削減できるかに興味をもっています。

それはなぜかというと「私がシステムの理解のセンスがないからそれをなんとか技術で解決したい」という個人的欲求に他ならないのですが、「まあオンボーディングのコストが小さくなればそれはエンジニア全員にも良いことだろうな」と勝手に思い込んでいろいろ作ったりしています。

実は今回の発表にいたるまでには過程があって、July Tech Festa 2021 winter ではDocumentation as Codeというキーワードで継続的なドキュメント運用の実現方法について主張しPHPerKaigi 2021ではその主張をさらに進めて発表しました

www.youtube.com

そして今回のWSA研では、集合を使って「継続的なドキュメント運用」「理解しやすいドキュメント」についてモデル化し、有効性を主張してみました。まだまだ前提などが甘々ですが、やはりWSA研、有用なフィードバックを多くいただきました。ありがとうございました。

実装としてのndiag

さて、上記の発表の主張に沿って実装しているのが ndiag です。

github.com

嘘です。

実際には逆で、いかに継続的にドキュメントを運用できるかウンウン考えて試行錯誤しながらndiagを開発し、その設計思想を整理したのが上記の発表です。

ndiagがどのようなドキュメンテーションツールなのか?については割愛します。公式チュートリアルや、実際に使ってみたエントリを書いてくださっている方もいらっしゃるので(本当にありがとうございます!!)そちらをご覧ください。

zenn.dev

「システムが頻繁に更新されるならシステム自体を観測してそこからドキュメントを作成すればいい」というアイデアは、真新しいものではありません(PHPerKaigi 2021の資料にその例が掲載されていて、わかりやすいと思います)。私自身も tbls という自身で作成したデータベースドキュメンテーションツールの開発で効果を実感しています。

github.com

ndiagで実現したいと思っていることは、まだまだ全ては実装できていません。それは、主に私の技術力や、開発に確保できる時間、ついつい発散してしまうモチベーションなどが原因です。

ただ、システムの継続的なドキュメンテーションを実現するのに有用そうな技術もどんどん生まれてきているので、もう1、2歩進めることができるんじゃないかなあと思っています。

とりあえず今の主張は以下です。

まとめ

今回もWSA研は楽しかったです。いつも受け入れていただいてありがたいです。

特に @YutaroHayakawaさん の発表と、懇親会でのいろいろなお話が「頑張らないとな」と思うことが多々あり「頑張らないとな」という気持ちです。

みなさんお疲れ様でした!!

任意のPull Requestの内容を複数のリポジトリに対して一括コピーするツールpr-bulletを作った

GitHub Actions便利ですよね。

ペパボではGitHub Enterprise Server(以下、GHES)が運用されており、GHESでもGitHub Actionsが利用できます。

uses: だけで利用できるリポジトリを横断で再利用可能なActionの存在はかなり生産性を上げていると思います。

そういった便利なワークフローを複数のリポジトリに対して適用していきたいことが時々あります。

一気に複数のリポジトリに同じワークフローを適用したいこともあれば、「あ、このリポジトリにはあのリポジトリのワークフローをいれたほうがいいな」となることもあります。

その時、それぞれのリポジトリに対して「突然のデフォルトブランチへのpush」はあまりにも乱暴なのでPull Requestを作成していくことになります。

ただ、適用したいレポジトリが2桁あったとき、Pull Requestを作成するのも心が折れそうになります。

そこで、任意のPull Requestの内容を他の複数のリポジトリに対して「コピーPull Request」として一括作成するツールpr-bulletを作ってみました。

github.com

pr-bullet

ちなみに、同様の、pr-bulletよりも高機能なツールとして NerdWalletOSS/shepherd があります。

それなのに、なぜわざわざ作ったかというと

  • 単機能で迷わない
  • 設定ファイルが必要ない
  • 全てオンメモリで完結

を実現したかったからです。

pr-bulletの使い方は簡単で、

  1. どこか適当なリポジトリでオリジナルとなるPull Requestを作成
  2. pr-bulletを実行して指定のリポジトリへPull Requestをコピー

で終わりです。

実行している様子は以下のような感じです。

$ pr-bullet https://github.com/k1LoW/my-bullets/pull/3 k1LoW/tbls k1LoW/ndiag
Original pull request:
  Title ... Add allow-auto-merge label action using ghdag
  URL   ... https://github.com/k1LoW/my-bullets/pull/3
  Files ... 34
Target repositories:
  k1LoW/tbls, k1LoW/ndiag
Do you want to create pull requests? (y/n) [y]: y

Copying k1LoW/my-bullets pull request #3 to k1LoW/tbls ... https://github.com/k1LoW/tbls/pull/999 as draft
Copying k1LoW/my-bullets pull request #3 to k1LoW/ndiag ... https://github.com/k1LoW/ndiag/pull/333 as draft
$

実際は

  • 追加もしくは修正したファイルのみサポート(削除やリネームは未対応)
  • ファイルのパーミッションは一律 100644 v0.3.0 で修正しました
  • オリジナルPull Requestのコミットは強制で1つにまとめられる
  • ラベルやAssigneesはコピーされない

といった感じで本当の意味での「コピー」ではないのですが、それでも毎回Pull Requestタイトルや文章をコピペしなくて良いだけだいぶ楽です。

とりあえず社内のGHESに k1low/my-bullets リポジトリを作成して、Pull Request発射基地としてみました。

1コマンドでPull Requestがコピーできてしまうので、ついつい濫用しそうですが気をつけていこうと思います。