GitHub Actionsで実装した湯婆婆にマスクをつける

**注**:[元ネタ様](https://qiita.com/Nemesis/items/c7192a7c510788d2cba2)以上にネタバレ要素満載ですので、ご注意ください。

このご時世ですので、[前回GitHub Actionsで実装した湯婆婆](https://qiita.com/nogic1008/items/7ed9f77ce32dec6f5ef0)にマスクをつけてもらいます。

## はじめに

~~湯婆婆様は重症化しやすい高齢者ですので~~
前回の実装では、**契約書に書いた名前がログに残ってしまいます。**契約者のプライバシーにも関わりますし、何よりも**奪った名前が後から参照できてしまう**という「湯婆婆の労働搾取システム」に対する重大なインシデントが発生します。

今回は、入力された名前をログから隠すことを目指します。

## add-mask

GitHub Actionsのログから、指定した値を`****`にマスクします。
なお、[`secrets`コンテキストから持ってきた値](https://docs.github.com/ja/actions/reference/encrypted-secrets#%E6%9A%97%E5%8F%B7%E5%8C%96%E3%81%95%E3%82%8C%E3%81%9F%E3%82%B7%E3%83%BC%E3%82%AF%E3%83%AC%E3%83%83%E3%83%88%E3%81%AE%E3%83%AF%E3%83%BC%E3%82%AF%E3%83%95%E3%83%AD%E3%83%BC%E5%86%85%E3%81%A7%E3%81%AE%E5%88%A9%E7%94%A8)は、最初からマスクされています。

```sh
# "secret_value"という文字列を****にマスクする
echo "::add-mask::secret_value"
# 環境変数nameとその値を****にマスクする
echo "::add-mask::$name"
```

### 注意点

#### add-mask評価前のログには効果がない

以下の部分などに該当文字列が利用された場合、ログに表示されてしまうことがあります。

- job名
- Actionのコマンドに直接埋め込んだ変数
- `workflow_dispatch`で渡された`inputs` ([GitHubのissue](https://github.com/actions/runner/issues/643))

本番利用前に、**必ずマスクされているかテストしてください。**

今回は以下のように対応することで、ログに入力した名前が表示されることを防いでいます。

- job名の名前部分を固定で「****」にする
- webhookのイベントペイロードから入力値を取得するよう変更 ([上記issueのコメントより](https://github.com/actions/runner/issues/643#issuecomment-708228940))

#### マスクされるのはログ表示だけ

あくまでも「GitHub Actionsのログ表示がマスクされる」だけですので、ファイルへのリダイレクトや、各actionからは**普通に見えてしまいます**。
「定義されている環境変数・シークレットのすべてを外部のHTTPサーバーに送信する」ような**悪意のあるaction**をworkflowに含めないよう、細心の注意を払ってください。[^1]

[^1]: GitHub公式は、信頼できないactionの場合、バージョン指定をバージョンタグ(`v1`, `v1.0.1`など)ではなく[コミットSHAで指定すること](https://docs.github.com/ja/actions/learn-github-actions/security-hardening-for-github-actions#%E3%82%B5%E3%83%BC%E3%83%89%E3%83%91%E3%83%BC%E3%83%86%E3%82%A3%E3%82%A2%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B)を推奨しています。

## upload-artifact

このままだと、千尋が元の名前を思い出すことができなくなってしまうため、別口で名前を保存しておきます。
ビルド成果などをGitHub Actionsの実行結果画面にアップロードできる[actions/upload-artifact](https://github.com/actions/upload-artifact)を使用します。

```yml
# ファイルを作成
- run: echo "ありがとう 千尋。僕の名前は「$name」" > hidden_name.txt
# 作成したファイルをアップロード
- uses: actions/upload-artifact@v2.2.0
  with:
    name: hidden_name # artifactに表示される名前(任意)
    path: hidden_name.txt # アップロードするファイル/フォルダのパス
```

### 有効期間

保存されたartifactの有効期間は、`retention-days`オプションで指定した日数になります。
この日数を過ぎた場合、永遠に元の世界には帰れなくなります。

未指定あるいは`0`を指定した場合は、リポジトリのログ保持期間と同じになります。
ログ保持期間はリポジトリの「Settings」→「Actions」→「Artifact and log retention」で確認できます。(デフォルトは90日)
~~この期間を過ぎれば、契約したログ自体が消えるので踏み倒せます~~

## 完成形

```yml:yubaba-mask.yml
name: 湯婆婆(マスク)

on:
  workflow_dispatch:
    inputs:
      name:
        description: '契約書だよ。そこに名前を書きな。'
        required: false

jobs:
  keiyaku:
    runs-on: ubuntu-latest
    steps:
      - name: フン。****というのかい。贅沢な名だねぇ。
        id: rnd
        run: |
          set -eu
          name=$(jq -r '.inputs.name' $GITHUB_EVENT_PATH)
          echo "::add-mask::$name"
          random=$[RANDOM % ${#name}]
          echo ::set-output name=new_name::${name:random:1}
          echo "ありがとう 千尋。僕の名前は「$name」" > hidden_name.txt
      - name: 今からお前の名前は${{ steps.rnd.outputs.new_name }}だ。いいかい、${{ steps.rnd.outputs.new_name }}だよ。分かったら返事をするんだ、${{ steps.rnd.outputs.new_name }}!!
        uses: actions/upload-artifact@v2.2.0
        with:
          name: hidden_name
          path: hidden_name.txt
          retention-days: 30
```

## おわり

今回の実装は「認証トークンを外部から注入する」ようなワークフローに使えそうですが、そのような用途の場合、素直に[Secrets](https://docs.github.com/ja/actions/reference/encrypted-secrets)を使ったほうが良いです。