【Rust】cargo-denyとは何なのか？使い方は？

こんばんは。きさらぎです。最近のマイブームは隅付き括弧を使って2ちゃんねるのまとめサイトのようなタイトルを持った記事を作成することです。
今回は`cargo-deny`という`cargo`のサブコマンドとして機能する実行可能ファイルの使い方をまとめました。

## cargo-denyとは？
[GitHubのレポジトリ][github]のdescriptionには次のような記載があります。

> Cargo plugin for linting your dependencies

これを邦訳するとこうなります。

> あなたの依存しているクレートをリントするCargoプラグイン

まだ「何をリント」するのかなどがわかりませんね。

### 具体的に何をするのか？
もう少し掘り下げるために[ドキュメンテーション][doc]を読むことにします。トップページには次のように、もう少し具体的な記載がありました。

> cargo-deny is a cargo plugin that lets you lint your project's dependency graph to ensure all your dependencies conform to your expectations and requirements.

これを邦訳するとこうなります。

> cargo-denyはあなたのプロジェクトの依存性グラフ上にある依存したクレートがあなたの期待と要求に沿っているかどうかを検査します。

やや具体的になりましたね。

さらに読み進めていくと、以下のことが[できる][doc-checks]ようです。

* [RustSecのadvisory][adv]に該当するかどうか検査する、`cargo deny check advisories`
* [特定のクレート](https://embarkstudios.github.io/cargo-deny/checks/bans/index.html#use-case---denying-specific-crates)や、依存グラフの中で起きた[特定のクレートのバージョンの違いを拒絶](https://embarkstudios.github.io/cargo-deny/checks/bans/index.html#use-case---duplicate-version-detection)する`cargo deny check bans`
* クレートのライセンスが期待したものに沿っているかどうか検査する`cargo deny check licenses`
* クレートが信頼しているソースからのみ来ているか検査する[`cargo deny check sources`](https://embarkstudios.github.io/cargo-deny/checks/sources/index.html)

## どうやって使うのか？
### 手元にインストール
ここでは一番馴染みが深い、手元のマシンに`cargo install`でインストールする方法を解説します。他の方法でインストールしたい方は[ドキュメンテーション](https://embarkstudios.github.io/cargo-deny/cli/index.html)を参照してください。

1. `cargo install cargo-deny`
2. `cargo deny help`でヘルプが出るかどうか確認

至ってシンプルな手順でした。

#### コンフィグの生成
ただし、インストールしただけだと`cargo deny check licenses`で`Apache-2.0`や`MIT`が弾かれるなど不都合があるため、コンフィグの初期化を行います。プロジェクトごとに以下の設定を行ってください。

1. `Cargo.toml`があるディレクトリに移動
1. `cargo deny init`

`cargo deny init`で生成される初期状態のコンフィグは[ドキュメント](https://embarkstudios.github.io/cargo-deny/cli/init.html#template)に記載があります。

#### コンフィグの設定
コンフィグを生成したら次にするのは設定です。

私は`[licenses]`を次のように設定します。

```toml
[licenses]
unlicensed = "deny"
allow = [
]
deny = [
]
# GPLに気づきたい。お好みでwarnに
copyleft = "deny"
allow-osi-fsf-free = "both"
default = "deny"
confidence-threshold = 0.8
exceptions = []
```

そして、`[bans]`を次のように変更します。

```toml
[bans]
multiple-versions = "warn"
# `*`で指定すると絶対にいつか壊れる
wildcards = "deny"
highlight = "all"
workspace-default-features = "allow"
external-default-features = "allow"
allow = [
]
deny = [
    # malicious
    # https://blog.rust-lang.org/2022/05/10/malicious-crate-rustdecimal.html
    { name = "rustdecimal" },
    # semi-malicious
    # https://security.snyk.io/vuln/SNYK-RUST-BETTERMACRO-1533595
    { name = "better-macro" },
    # unmaintained & crypto-fail
    # https://rustsec.org/advisories/RUSTSEC-2016-0005.html
    # https://rustsec.org/advisories/RUSTSEC-2022-0011.html
    { name = "rust-crypto" },
    { name = "lz4-sys", version = "<= 1.9.3" },
    { name = "juniper", version = "<= 0.15.9" },
    { name = "async-graphql", version = "<= 4.0.5" },
    # ReDoS
    { name = "regex", version = "<= 1.5.4" },
    { name = "flatbuffers", version = "<= 22.2.9" },
    { name = "openssl-src", version = "<= 111.16" },
]
```

これで最近のクリティカルな脆弱性を避け、ライセンスにある程度寛容なチェックを行うコンフィグができました。

#### コマンドの実行

お好みのコンフィグを設定したあと、[§具体的に何をするのか？](#具体的に何をするのか？)で解説したサブコマンドを打ってあなたのソフトウェアをより厳密にしましょう。

## おわりに
最近は脆弱性やライセンスに*気を遣う*ビジネス向けサービスが流行り始めていますが、FOSSの世界でもそういったことに気を遣うようになればいいなと思います。

お読みいただきありがとうございました。

[github]: https://github.com/EmbarkStudios/cargo-deny
[doc]: https://embarkstudios.github.io/cargo-deny/
[doc-checks]: https://embarkstudios.github.io/cargo-deny/checks/index.html
[adv]: https://github.com/RustSec/advisory-db