tech.guitarrapc.cóm

Technical updates

OSSライセンスを正しく理解するための本 を読んだ

OSSライセンス はむずかしい、のと同時にどんどん変わっていっているので学び続けないといけないというのがあります。

自分自身がOSSライブラリを公開しているので、ライセンスは何をつかうか、なぜというのをアップデートしていく必要があります。 一方で、仕事も同様かそれ以上に必要な情報を、誤解なく伝えられるようにありたいとも思います。(難しい)

ということで、OSSライセンスを正しく理解するための本 が気になったのでKindle版を購入して読みました。

www.amazon.co.jp

あんまり本のレビューはしないのですが、たまには書きます。そして本を読んで改めて、自分のライブラリは今後も MIT をベースにすると思います。

tl;dr;

OSSライセンス、これからもしっかり管理していこうという気持ちになったので、本の目標は達成できてそうです。

どう読み進めたのか

この本はコードが出てこない一方、自分の考えをフラットにしつつまとめる必要があるので、Notion を使って読み進めつつメモを取る形式で進めました。

Kindle で読んでたのですが、文章をカーソル選択もマークもできないのでこれは厳しい。電子本なのになにもできない悲しさ。語句の検索もできないのはつらいですね。(ことさら Notion にメモを書く必要があった)

大体6時間ぐらいかかったので、文量に対して時間かけて考えながら読んだようです。

気づき

OSSライセンスが各国の著作権法に根差しているというのは、そういえばと思いつつおぼろげだったことでした。(著作権といいつつどこの? というスタートラインが曖昧だったといえる)

OSSライブラリを「使用する」と「利用する」を基点として、明確に言語化されて例が示されているのは整理されます。(例えば、クラインアントとしてのバイナリ提供は? サーバーとしての提供は? 社内向けサービスは? デバッグで使うツールは? 負荷試験で使うツールは? などのよくあるものも含めて) よく考えてみても、利用と使用を明確に区別しているのは、説明するにあたって大事だけど意識していなかった。意識しなくても大きく解釈ずれることがないけど、伝えやすいと思います。

AGPLに関して著作権法上利用といえるか疑問(P113)、という著者の意見が素直に書かれていて、実際これってどうなんですかね? 私も疑問です。

日本における利用、使用の裏付けは、著作権審議会マルチメディア小委員会 ワーキング・グループ中間まとめ (平成10年2月 文化庁) に依るんですね。これはOSSライセンスで調べていても、たびたび出てくる出典ですが、ほかに出てこないのはそんなもの? もう少し裏付けないのかしらと思わなくもない。平成10年って。

www.cric.or.jp

分類がいわゆる「コピーレフト型、準コピーレフト型、非コピーレフト型」ではなく「BSDタイプ、GPLタイプ、LGPLタイプ、MPLタイプ」になっているのはなるほどでした。言ってることに大きな違いはないんだけど、これもわかりにくいと思う部分があり微妙ですね。 permissive かどうかに焦点を当てた視線も同じ本で触れられているといいんじゃないかなぁと思いつつ、発散して難しそう。 分類いろいろあるけど、個人的には Public Domain などの著作権放棄に触れた本が読みたい気持ちがわきました。

リバースエンジニアリングに関して、利用規約として改変の目的のためのリバースエンジニアリングは許可しつつ、機能分析のためのリバースエンジニアリングは禁止することができるというのは新鮮でした。目的別に指定するという発想がなかった。

ライセンス管理の例として、ライセンス以外にライセンスタイプを書くことで対処しやすくするというのは良いと思いました。このライセンスだから XXXではなく、ライセンスのタイプだから XXX とするのは運用しやすい。

バージョンによってライセンスが変わるは、ここ最近もちょいちょいあるので結構難しいですね。アップデートしたらライセンス変わりますからね。調べないと気づけないのはまぁいいとして、変わったら強制的に気づく仕組みが欲しい。こういうのは人間のやることじゃないので仕組みで何とかしたいところです。Dependabot も脆弱性に応じて更新できてもライセンス変更をあれで気づくのは無理だしなぁ。ふと思ったけど、licensed 使ってないんですがどうなんでしょう。

github.com

気になったこと

フラットな立場1で書かれた本ではないと感じました。それは自由なのでよいのですが、フラットな文章が読みたいと思った時には手に取りにくい本です。

著者の主張が強く、不満に思っていることを本の中で文面にちょいちょい出されているので、うっと敬遠する気持ちが増します。主語が大きく、強い言い回しが多いので、軽く読みすすめようと思って結果疲れました。私はこういうの苦手なので、人にすすめることは難しいです。

静的リンクと動的リンクによる違いに触れてないので、ちょっとこれだけだと片手落ちな感想というかあまりよくない気配。 コンパイルとしての例があるので、静的リンクとしてはいいのだけどリンクの違いに触れてないので、この本だけで察するのはできなさそうです。

一部の主張は、10行前と矛盾していることを言っているように思ったので気になります。

出典不明なケースが数例あったのと、出典を示しつつ和訳のみがあるものがあり、解釈あってるかの再考証がむずかしいと思いました。出典がURL抜きで不明なものはちょっと困ります。

時々例示が古く、今それを例にするのかと思い残念です。(プリンタドライバーの例とか)

併せて読みたい

IoT 時代におけるOSS の利用と法的諸問題Q&A 集

future-architect.github.io


  1. 個人の好みはおいて、あるいはどのOSSライセンスがいいなどといった信条から距離をおいた立場

東プレ REALFORCE R3HC12 にメインキーボードを変更した

Realforce R3 が発売されました。

これまで Realfoce が抱えていた不満がほぼすべて解消されたモデルに見えるので、メインキーボードに据えてみました。

前回の R2TLS-JP4 から約4年での新モデル、実際どうなのか見てみます。

tech.guitarrapc.com

tl;dr;

R2 を有線で使って満足しているなら、R3 を買う動機は薄いと思います。 ただ、Realforce を 無線で使いたいならオススメです。 Realforce ConnectによるAPCやキーマップ設定も使ってみるとよいものです。

よく比較に挙げられていたNIZ と比較して足りないものはほぼなくなったので、正しく進化した感触です。 価格が高いのがネックですが、キーボードは職業柄一番使う道具なので更新していきたいところです。

余談ですが、キースペーサー2mm を入れると、キーボード入力が気持ち浅くなる以上に、入力音が低減されてよかったです。

簡易まとめ

  • R3 はベゼルは太い。
  • スコスコは強くなった。(違和感ある人もいそう)
  • 静音はR2 より気持ち劣ってるかもしれない。
  • Bluetooth で使って、キータップで自動復旧させるなら モード4 一択。
  • Bluetooth なのに 1.3 kg あるのは、Realforce はそういうものといえばそうだけどちょっとちぐはぐになっていくかもしれませんね。
  • キースペーサー2mm と APC 1.5mm で、メンブレンタイプも試せるように矯正したりもできる。

外見と特徴

ホームページから見てみましょう。

www.realforce.co.jp

f:id:guitarrapc_tech:20211108014952p:plain

特徴的なのが、上部のボタンとインジケーターランプです。

見た目は R2 から初代に戻っており、サイズとベゼルが残念です。

R2 に比べてベゼルが太く、角がの丸っこいため初代に近く感じます。

サイズを見てみましょう。

モデル サイズ
R2 142mm x 369mm x 30mm
R3 163mm × 379mm × 30mm

キーピッチ、キー入力の配置感覚はは変わらないので、単純にベゼルが増えた分だけ上下左右に長くなっています。

  • 横方向は、キーピッチの配置で合わせると左右に微妙に伸びただけで案外違いは分かりません。
  • 上方向は、1cmあまりの差がはっきりわかります。ボタンとインジケータで増えたにしては大きかった。

f:id:guitarrapc_tech:20211108015134p:plain
上 R2、下R3 で横合わせ

f:id:guitarrapc_tech:20211108020042p:plain
上 R3、下R2でキーピッチ合わせ

スペースはR2より少し短くなり、初代ぐらいになっています。

そのほか

R3 は R2 と違い、モデルによらずキー印刷はレーザー印刷です。

今回購入したのは、Bluetooth 5.0 & USB 有線のハイブリッド接続なので、USB C - USB A ケーブルがつけ外し可能になっています。(Realforce 側が Type-C)

Bluetooth は、バスパワーか単三電池x2 で動作します。

キープラーや替えのキートップは同梱されませんので注意です。 キートップは別売りでさまざまな色が売られるようなので、面白そうですね。黒 + 黄 などもよさそうです。

www.realforce.co.jp

操作

電源ボタンが追加されました。1秒長押しするとつながります。

Fn キーと一緒に、キートップ側面に書かれたキーを押すと各種操作ができます。

よく使うものをあげてみると

  • Fn + P で、Bluetooth のペアリングができます。
  • Fn + 1~4 で Bluetooth 接続先を4つキーボードが記録でき、 Fn + 5 でUSB 接続に切り替えることができます。
  • Fn +F9 でバッテリー状態を確認できます。
  • Fn +F11 で、Bluetooth のエコモードを切り替えられます。

取説にも説明がありますが、側面を見るとすぐにわかるのは便利ですね。

Bluetooth 接続時の復旧

Bluetooth キーボードやマウスは、電池節約のために自動的に切れるのが一般的です。 R3 も例外にもれず、Bluetooth 接続時はエコモードが働きます。

エコモードは全部で4モードあり、デフォルトはモード 1です。

f:id:guitarrapc_tech:20211108021400p:plain
取説のエコモード

取説の時間放置後の復旧を試したのですが、モードごとの違いは次の通りです。

  1. 10分でキーボードがスリープ。キータップでは復帰せず、電源ボタン1秒長押しでキーボードの電源onが必要
  2. 10分でキーボードがスリープ。キータップでは復帰せず、電源ボタン1秒長押しでキーボードの電源onが必要
  3. 30分でキーボードがスリープ。キータップでは復帰せず、電源ボタン1秒長押しでキーボードの電源onが必要
  4. 30分でキーボードが切断。キータップで自動的に再接続して、2キー入力から使える。

私は時間が経ってキーボードとPCがつながらくなっても、何かしらのキーをタップしたら復旧してほしいと考えています。 この要件にあるのは「エコモード4」だけでした。 1~3 の電源長押しが必須なのはちょっと受け入れがたいです。

気になるのが、4の切断でスリープとちがうということはスリープしないんですかね。 とりあえず単三電池で使っていますが、どうなるのか今後が気になります。(3か月も持てば十分ですが)

キータッチの違い

R2 と比べて、R3 は、スコスコ感が増したようです。 良くも悪くもスコスコ、好みはあるかもしれませんがすぐに慣れて R2 を忘れたので私にはその程度でした。

ただ、R2と同じ静音ですが、少しキーボードがうるさい気がします。

キースペーサーを2mm を試してみるので、静音やタッチ感覚がどうなるか楽しみです。

www.realforce.co.jp

Realforce Connect

Realforce のだめといわれた最大のゆえんは、お高いわりに調整がしょぼいことです。

R3 ではRealforce Connect をインストールして、USB でつなぐとAPCやキーマップの入れ替えが可能におなっています。

例えば、APCモデルならデフォルト2.2mm から「キーボード全部」や「キー個別」に浅くしたり深くしたりが可能なのはうれしいところです。

キーマップの入れ替えも、Windows レジストリや機能を使うことなくキーボードで完結できます。今回は、Caps lock を Ctrl にしました。

f:id:guitarrapc_tech:20211109224658p:plain
変更後のキーマップ。Caps Lock を L-Ctrl に切り替えている

面白いところでは、今のキーストロークの深さがわかる機能もあって、普段自分がどれぐらいの深さで入力しているのかがわかります。

f:id:guitarrapc_tech:20211109223903p:plain
Realforce Connectでキーストロークの深さが可視化される

惜しむらくは、USB接続していないと接続を検知してくれないことでしょう。 普段 Bluetooth 接続なので、気になったときにUSBにつなぐのは面倒ですね。

Windows の Japanese IME 設定

スペースの左右にある無変換、変換をそれぞれ IME-off / IME-on に割り当てています。これは、macOS は英字、日本語になっているので合わせているのですが、日本語キーボードで頻繁に日本語、英字の切り替えをするので便利です。

f:id:guitarrapc_tech:20211108023307p:plain
日本語 IME > キー & タッチ

キースペーサー2mm を入れてみる。

2021/11/9 2mm のキースペーサーをつけてみました。

f:id:guitarrapc_tech:20211109224828p:plain
キースペーサーをつける前

f:id:guitarrapc_tech:20211109224857p:plain
キースペーサーをつけた後

Realforce Connect で見ると、キーストロークはFull に近いようですが、APC 1.5mm にしてより軽くタイプできるようにもしてみました。

期待した効果ですが、装着前と比べて次の違いがあります。

  • キーストロークの深さが、気にするとわかる程度に浅くなった。
  • キーボードのカタカタ音から高音が減ったことで静かになったように感じる。

耳の位置あたりで録音したものを聞くと、普段の Realfoce R3 は結構うるさく感じますね。静音とはいえ、録音するとそういうものなのかもしれません。

Cascadia Mono の検討

プログラミング用のフォントは、前回は DevaVu Sans Mono Bront が今一番好みとしました。

しばらく、パッと思うのがなかったのですが、Windows Terminal に入った Cascadia Mono (合字ありは Cascadia Code) がいいという噂を聞いて、実際採用するか検討してみます。

tech.guitarrapc.com

tl;dr;

  • Cascadia Mono のほうが Consolas よりいい感じのバランスだった。
  • 少しBold で Consolas 気味にしたいなら、Cascadia Mono、合字が欲しいなら Cascadia Code がよさそう。
  • 今のところ普段使いは DejaVuSansMono-Bront のままだけど、Cascadia Mono はWindows 11 標準で提供される + Bold 気味にしたいときによさそうなので切り替える対象として有用。

結果

今回も、個人の感覚でスコアを点けてみました。 Cascadia Mono、DejaVuSansMono-Bront と並んで気に入っているようです。

f:id:guitarrapc_tech:20211107181454p:plain
Score

基準は

Target Border(:eyes:) Bad(-1) Good (+1)
oO08 distinct each 0 has dot inside 0 has slash
iIlL1 distinct each l and 1 are almost same l and 1 are completely different
g9qCGQ distinct each g is Slab serif g is not Slab serif, Q is serif font
~-+=> no ligature not center or any unbalance n/a
Left and right side padding too narrow TODO: measure
Top and bottom side padding too wide TODO: measure
Size too small 2/3 or 3/4 height of small letters
Balance Letter Paddings and Boldness

Fonts-lab/SCORE.md at master · guitarrapc/Fonts-lab · GitHub

Requirements

  • モノスペースフォント(等幅フォント)必須。プロポーショナルフォントは絶対だめ
  • 文字幅が少しあるほうがいい
  • 行が少し詰まっているほうが全体を見れてうれしい
  • 0 は スラッシュいれてほしい
  • 小文字L と 1 の区別は大事
  • 小文字 g がグねってしていると q と区別つきやすくて最高
  • Ligature はいらない
  • もともとプログラム内で日本語はかかないので入っていなくてもok
  • 横は狭いより広くてok
  • 縦が広いのはダメ
  • フォントは大き目がよい

Compare

Cascadia Code (Mono) を Consolas と DevaVu Sans Mono Bront と比べてみます。

https://app.programmingfonts.org

f:id:guitarrapc_tech:20211107171212p:plain
Bront Dejavu Sans Mono

f:id:guitarrapc_tech:20211107171127p:plain
Cascadia Code

f:id:guitarrapc_tech:20211107172218p:plain
Cascadia Code と Consolas

f:id:guitarrapc_tech:20211107172231p:plain
Cascadia Code と DejaVu Sans Mono - Bront

Selection

DejaVu Sans Mono - Bront と Cascadia Mono の選択

フォント自体がべつもの。Cascadia Mono は セリフが少し強め。

Cascadia Mono は、Bold 気味で文字が詰まって見えるのと、小文字の縦のサイズが 1/2 で 2/3 や 3/4 ぐらいが好きなのでそこだけ惜しい感じ。

Dejavu Sans Mono は 少しBold 気味で読みたい時に代替がなかったので、Cascadia Mono はそこを埋めてくれそうです。

Consolas と Cascadia Mono の選択

フォント自体は似ている。

文字一つ一つが Cascacia Mono はより大きく、Bold も強めなので視認性が良い印象です。

g が、Cascacia Monoでは 丸くなっていないのが残念。

文字の詰まり具合が、Cascacia MonoのほうがConsolas より改善していて好ましい感じです。

GitHub Actions で configure-aws-credentials を使った OIDCではまったこと

GitHub Actions の OpenID Connector と AWS の OIDC Provider を使うことで、IAM Role を Assume できるというのは前回書きました。

tech.guitarrapc.com

構築中によく出るエラーに関しても書いたのですが、いざ実際に使おうとしたら別のエラーではまったので忘れないようにメモしておきます。

tl;dr;

  • OpenID Connect で認証すると、AWS OIDC Provider の認証の上限に引っ掛かりやすい。
  • Composite Action の中で、 configure-aws-credentials を呼び出すときは注意。

GitHub Actions で並列実行すると時々失敗する。

エラーメッセージ Error: Couldn't retrieve verification key from your identity provider, please reference AssumeRoleWithWebIdentity documentation for requirements

対策: configure-aws-credentials で OIDC 認証を頻繁に呼び出す場合は、キャッシュかリトライしましょう。

並列でジョブを実行するなど、短時間に頻繁に認証を取得ようとすると、時々認証に失敗します。 IAM Userを使っていると当然でないのですが、OIDC Providerで認証をかけようとするとぐさっと刺さります。

これを回避するには、リトライかキャッシュ作戦をとる必要があります。

github.com

workflow で一回だけ認証ととって、キャッシュを使いまわす場合次のような workflow になります。

gist.github.com

ただ、GitHub Actions の cache は 「パブリックリポジトリのキャッシュには、センシティブな情報を保存しないことをおすすめします。」とある通り取扱いには注意だと思います。トークン自体 は 900sec (min) か 1 hour (default) で切れますが、時間の問題ではないという。

Warning: We recommend that you don't store any sensitive information in the cache of public repositories. For example, sensitive information can include access tokens or login credentials stored in a file in the cache path. Also, command line interface (CLI) programs like docker login can save access credentials in a configuration file. Anyone with read access can create a pull request on a repository and access the contents of the cache. Forks of a repository can also create pull requests on the base branch and access caches on the base branch. https://docs.github.com/en/actions/advanced-guides/caching-dependencies-to-speed-up-workflows

configure-aws-credentials を1 jobで複数回呼び出したときに初回の認証を上書きできない

対策: configure-aws-credentials の呼び出しは一回の composite action で行うか、workflow で呼び出しましょう。

通常 configure-aws-credentials は、呼び出しのたびに job 内の認証を後勝ちで上書きします。 ただし、composite action の中で、configure-aws-credentials を呼び出すと、意図しない結果になるパターンがあります。

configure-aws-credentials を呼び出す処理を composite action に書いて、1 job内で 別の IAM Role の Assume を呼びだすと 2 回目の configure-aws-credentials で上書きできないので避けましょう。

github.com

正常動作例1

次のように workflow 上で連続でconfigure-aws-credentialsを呼び出すと、2回目の configure-aws-credentials で myrole_Bに上書きできていることが確認できます。

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
     # 1st
      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@master
        with:
          aws-region: ap-northeast-1
          role-to-assume: arn:aws:iam::123456789012:role/myrole_A
          role-session-name: GitHubActions-${{ github.run_id }}
      - name: get-caller-identity shows myrole_A as expected
        run: aws sts get-caller-identity
      # 2nd
      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@master
        with:
          aws-region: ap-northeast-1
          role-to-assume: arn:aws:iam::123456789012:role/myrole_B
          role-session-name: GitHubActions-${{ github.run_id }}
      - name: get-caller-identity shows myrole_B as expected
        run: aws sts get-caller-identity

1回目のget-caller-identity は myrole_A です。

{
    "UserId": "AROASJXUOK5UM7XZKRYTB:GitHubActions-1426675663",
    "Account": "***",
    "Arn": "arn:aws:sts::***:assumed-role/myrole_A/GitHubActions-1426675663"
}

2回目のget-caller-identity は myrole_B です。

{
    "UserId": "AROASJXUOK5UM7XZKRYTB:GitHubActions-1426675663",
    "Account": "***",
    "Arn": "arn:aws:sts::***:assumed-role/myrole_B/GitHubActions-1426675663"
}

意図通りの挙動です。

正常動作例2

Composite Action の中で configure-aws-credentials をまとめて2回呼び出すと、2回目の呼び出しで myrole_B に上書きできていることが確認できます。

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Configure AWS Credentials
        uses: ./.github/actions/aws_oidc_auth_all

aws_oidc_auth_all はこうなっています。

# ./.github/actions/aws_oidc_auth_all/action.yaml
name: aws oidc auth
description: |
  Get aws oidc auth.
runs:
  using: "composite"
  steps:
    # 1st
    - name: Configure AWS Credentials (Role A)
      uses: aws-actions/configure-aws-credentials@master
      with:
        aws-region: ap-northeast-1
        role-to-assume: arn:aws:iam::123456789012:role/myrole_A
        role-session-name: GitHubActions-${{ github.run_id }}
    - name: get-caller-identity shows myrole_A as expected
      run: aws sts get-caller-identity
      shell: bash
    # 2nd
    - name: Configure AWS Credentials (Role B)
      uses: aws-actions/configure-aws-credentials@master
      with:
        aws-region: ap-northeast-1
        role-to-assume: arn:aws:iam::123456789012:role/myrole_B
        role-session-name: GitHubActions-${{ github.run_id }}
    - name: get-caller-identity shows myrole_B as expected
      run: aws sts get-caller-identity
      shell: bash

1回目のget-caller-identity は myrole_A です。

{
    "UserId": "AROASJXUOK5UM7XZKRYTB:GitHubActions-1426687022",
    "Account": "***",
    "Arn": "arn:aws:sts::***:assumed-role/myrole_A/GitHubActions-1426687022"
}

2回目のget-caller-identity は myrole_B です。

{
    "UserId": "AROASJXUOK5UHN4XWD3XF:GitHubActions-1426687022",
    "Account": "***",
    "Arn": "arn:aws:sts::***:assumed-role/myrole_B/GitHubActions-1426687022"
}

意図通りの挙動です。

問題の動作

Composite Action の中で configure-aws-credentials を それぞれのIAM Role について呼び出すと、2回目の呼び出しが myrole_A のままで myrole_B で上書きできていないことが確認できます。

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      # 1st <- Shows myrole_A, expected.
      - name: Configure AWS Credentials (Role A)
        uses: ./.github/actions/aws_oidc_auth_single
        with:
[https://docs.github.com/en/actions/creating-actions/creating-a-composite-action:embed:cite]


          role-to-assume: arn:aws:iam::123456789012:role/myrole_A
      # 2nd <- Shows myrole_A, unexpected!!
      - name: Configure AWS Credentials (Role B)
        uses: ./.github/actions/aws_oidc_auth_single
        with:
          role-to-assume: arn:aws:iam::123456789012:role/myrole_B

aws_oidc_auth_single はこうなっています。

# ./.github/actions/aws_oidc_auth_single/action.yaml
name: aws oidc auth
description: |
  Get aws oidc auth.
inputs:
  role-to-assume:
    description: "AWS IAM Role to assume 1"
    required: true
runs:
  using: "composite" # this is key point
  steps:
    - name: Configure AWS Credentials
      uses: aws-actions/configure-aws-credentials@master
      with:
        aws-region: ap-northeast-1
        role-to-assume: ${{ inputs.role-to-assume }}
        role-session-name: GitHubActions-${{ github.run_id }}
    - name:  get-caller-identity shows myrole_A on both 1st and 2nd run. (2nd run must be myrole_B but incorrect result.)
      run: aws sts get-caller-identity
      shell: bash

1回目のget-caller-identity は myrole_A です。

{
    "UserId": "AROASJXUOK5UM7XZKRYTB:GitHubActions-1426687028",
    "Account": "***",
    "Arn": "arn:aws:sts::***:assumed-role/myrole_A/GitHubActions-1426687028"
}

2回目のget-caller-identity も myrole_A です。myrole_B に上書きできていません。

{
    "UserId": "AROASJXUOK5UHN4XWD3XF:GitHubActions-1426687028",
    "Account": "***",
    "Arn": "arn:aws:sts::***:assumed-role/myrole_A/GitHubActions-1426687028"
}

aws-actions/configure-aws-credentials の中身を見ても、composite action 特有の処理は当然存在しません。 composite action の仕様かと思いつつ、そういった記述もないので謎です。

仕方ないので、正常動作例1,2 のいずれかを用いることになるでしょう。

あるいは、両方の権限をもつ単一Roleでやるのも手でしょう。

GitHub Actions が OpenId Connect に対応したので AWS OIDC Provider と連携する

前々から言われていた GitHub Actions で OpenID Connect 経由で、各種Cloud Provider の認証を得るのが GA しました。 めでたい。

github.blog

これにより、aws-actions/configure-aws-credentials のみで認証が組めるようになったので見てみましょう。

github.com

tl;dr;

  • GitHub Actions でAWS操作をするために、IAM User が不要になるので神。
  • セルフホストな GitHub Actions を EC2 で動かしているなら、素直に Instance Role を使うので十分というのもある。(何か事情があれば OpenId Connector でもいい)
  • AWS アカウントで OpenId Connect Provider は 一意です。1 AWSアカウントで複数環境を持っている & 環境ごとに IAM Role を持っている場合は、環境ごとに OpenId Conect Provider を作ろうとして失敗しないように。
  • 並列度高く認証を取得しようとすると失敗することが多いので注意

動作例

設定がただしければ、必要な IAM Role Arn を role-to-assume に指定するだけで、その Role 権限で 操作ができるようになります。

これで

      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@master
        with:
          aws-region: ap-northeast-1
          role-to-assume: "作ったIAM Role の Arn を入れる"
          role-session-name: "適当な名前"

こうなる。

f:id:guitarrapc_tech:20211105022035p:plain
GitHub OpenId Conector と AWS OIDC Provider でAWS の操作ができる

基本

GitHubから公式にドキュメントが公開されたのでこれに従いましょう。先日までuses: aws-actions/configure-aws-credentials@v1 になってたせいでドキュメントが嘘つきでしたが @master に修正されています。

docs.github.com

なお、https://github.com/aws-actions/configure-aws-credentials は、uses: aws-actions/configure-aws-credentials@v1 になっているので動きません。uses: aws-actions/configure-aws-credentials@master に読み替えましょう。

Terraform で AWSを用意する。

用意する必要があるのは、OIDC Provider と IAM Role です。

  • OIDC Provider は、GitHub OIDC と信頼関係を結ぶのに必要です。
  • IAM Role は OIDC Provider 経由で GitHub OIDC でリクエストされたときに、リクエスト元のリポジトリオーナー/リポジトリ名:ブランチ名 を検証し条件にマッチしたらそのRoleを Assume して利用できるようにします。つまり、このRoleに、リポジトリの制約と必要な IAM Policyを振ればok。

全体を示します。

gist.github.com

OIDC Provider を用意する

値はすべて固定なので単純です。terraform ならこうなります。

// oidc provider
resource "aws_iam_openid_connect_provider" "main" {
  url             = "https://token.actions.githubusercontent.com"
  client_id_list  = ["sts.amazonaws.com"]
  thumbprint_list = ["a031c46782e6e6c662c2c87c76da9aa62ccabd8e"]
}

client_id_list がGA前と後で変わっています。古いバージョンではここで、リクエスト元のリポジトリURL を指定していましたが、今は sts.amazonaws.com といつものになりました。標準に沿ってくれてよかった。

GitHub の Endpoint が確認できますね。

https://token.actions.githubusercontent.com/.well-known/openid-configuration

{"issuer":"https://token.actions.githubusercontent.com","jwks_uri":"https://token.actions.githubusercontent.com/.well-known/jwks","subject_types_supported":["public","pairwise"],"response_types_supported":["id_token"],"claims_supported":["sub","aud","exp","iat","iss","jti","nbf","ref","repository","repository_owner","run_id","run_number","run_attempt","actor","workflow","head_ref","base_ref","event_name","ref_type","environment","job_workflow_ref"],"id_token_signing_alg_values_supported":["RS256"],"scopes_supported":["openid"]}

IAM Role を用意する

順番に解説します。

重要なのは、Assume Role です。 Assume Role で OIDC Provider からのリクエストを検証しています。

  • principal は、認証を委譲されて受けるので type: "Federated" + 先ほど作った OIDC Provider の arn を指定 します。
  • condition で、リクエスト元が repo:<GitHubOwner>/<Repositry>:Branch の条件とマッチするか検証します。

OIDC 経由で、許可した「リポジトリ、かつブランチ」だった場合に IAM Role をsts:AssumeRoleWithWebIdentity としてAssume できるようにします。

さて、複数のリポジトリで同じロールを使いたいケースはどうすればいいでしょうか?

IAM Policy の condition は、ワイルドカード一致するかを StringLike で検証できますが、これは value が1要素 (=単一リポジトリ) のときにしか機能しません。 value が複数要素(=複数リポジトリ)でもワイルドカードで一致するかを見る場合は、ForAnyValue: + StringLike を用います。

今回は 分岐させましたが、別に ForAnyValue で初めから書いてもいいでしょう。

data "aws_iam_policy_document" "github_oid_assume_role_policy" {
  statement {
    effect  = "Allow"
    actions = ["sts:AssumeRoleWithWebIdentity"]
    principals {
      type        = "Federated"
      identifiers = [aws_iam_openid_connect_provider.main.arn]
    }
    # aud があるとはじかれてるので、aud の値がおかしいっぽい。 aws-actions/configure-aws-credentials の仕組みからすると、sts.amazonaws.com が来るはず。 <- github.com/aws-actions/configure-aws-credentials ではなしになってる :(
    # condition {
    #   test     = "StringEquals"
    #   variable = "token.actions.githubusercontent.com:aud"
    #   values   = ["https://github.com/${var.github_owner}"]
    # }
    condition {
      test     = length(var.github_oidc_repo_names) == 1 ? "StringLike" : "ForAnyValue:StringLike"
      variable = "token.actions.githubusercontent.com:sub"
      values   = [for item in var.github_oidc_repo_names : "repo:${var.github_owner}/${item}:*"]
    }
  }
}

AssumeRole ができてしまえば IAM Roleを作るだけです。今回は、aws sts get-caller-identity を実行できるようにしてみましょう。

特にいうことはないですね。終わり。

data "aws_iam_policy_document" "github_actions" {
  // allow running `aws sts get-caller-identity`
  statement {
    effect    = "Allow"
    actions   = ["sts:GetCallerIdentity"]
    resources = ["*"]
  }
}

resource "aws_iam_policy" "github_actions" {
  name        = "githubactions_policy"
  path        = "/"
  description = "Policy for GitHubActions"
  policy      = data.aws_iam_policy_document.github_actions.json
}
resource "aws_iam_role" "test_role" {
  name               = "githubactions-oidc-role"
  path               = "/"
  assume_role_policy = data.aws_iam_policy_document.github_oid_assume_role_policy.json
  policy_arns = [
    aws_iam_policy.github_actions.arn
  ]
}

リソースを作成

さて、これで AWS にリソースを作るとこんな感じになります。

今回は私は、guitarrapc/githubactions-lab と guitarrapc/infrastructure の 2リポジトリから GitHub Actions 経由で認証を受けられるようにしました。 IAM Role の Trust relationships > Conditions で2リポジトリが ForAnyValue:StringLike で指定されているのがわかりますね。

f:id:guitarrapc_tech:20211105021103p:plain
IAM > Identity providers > token.actions.githubusercontent.com

f:id:guitarrapc_tech:20211105021210p:plain
IAM > Roles > githubactions-oidc-role

ここまでのどれかにミスがあると Assume Role されません。 うまくいかない場合は何度も見直すことになるでしょう。

GitHub Actions の構成

Workflow を用意します。 キーポイントは3つです。

  • permissions で、id-token: write で書き込み権限が必要です。 permissions: write-all でもいいのですが、現状では permissions を指定しないとうごかないので注意です。
  • role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}secrets.AWS_ROLE_TO_ASSUME は、GitHub Secret に AWS_ROLE_TO_ASSUME という名前で先ほど作った IAM Role の Arn を仕込んであります。Arnのフォーマットは、今回の例なら arn:aws:iam::xxxxxxxxxxxxx:role/githubactions-oidc-role というフォーマットになります。
  • role-session-name で、CloudTrail イベントにユーザー名が出るのでいい感じの名前にしましょう。
  • uses: aws-actions/configure-aws-credentials@master を指定します。 uses: aws-actions/configure-aws-credentials@v1 でないので注意してください。

github.com

name: aws oidc credential

on:
  workflow_dispatch:
  push:
    branches: ["main"]

# allow use id-token
permissions:
  id-token: write # required!
  contents: read

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Configure AWS Credentials
        # must use "master", not "v1". v1 is not yet released to use latest role-to-assume.
        # Error: Credentials could not be loaded, please check your action inputs: Could not load credentials from any providers
        uses: aws-actions/configure-aws-credentials@master
        with:
          aws-region: ap-northeast-1
          role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
          role-session-name: GitHubActions-${{ github.run_id }}
          role-duration-seconds: 900 # minimum: 900sec, maximum: iam role session duration
      - name: get-caller-identity is allowed to run on role.
        run: aws sts get-caller-identity

実行してみると、冒頭のスクショのように成功するはずです。

$ aws sts get-caller-identity
{
    "UserId": "AROASJXUOK5UM7XZKRYTB:GitHubActions-1420393244",
    "Account": "***",
    "Arn": "arn:aws:sts::***:assumed-role/githubactions-oidc-role/GitHubActions-1420393244"
}

うまくできましたか? おめでとうございます!

ダメでした? 私も失敗を繰り返したので、経験したエラーと対処をFAQに載せておきます。

FAQ

GitHub Actionsで実行してみたら動作しない。

エラーメッセージ Credentials could not be loaded, please check your action inputs: Could not load credentials from any providers

この場合、AWS OIDC Provider の設定がおかしい or GitHub Actions の permissions が抜けています。

  • (AWSの設定ミス) OIDC Provider の client_id_list に "sts.amazonaws.com" ではなく、リポジトリのURL を指定している。(古いブログが記事がそうなっている)
  • (GitHub Actions Workflowの設定ミス) Workflow で、permissions がない。デフォルトの GitHub Actionsは write-all のはずですが、まだ id-tokens は含まれていないようです。明示的に permissions: write-all を指定するか、id-token: write を指定しましょう。

GitHub Actionsで実行してみたら動作しない。

エラーメッセージ Not authorized to perform sts:AssumeRoleWithWebIdentity

このケースは、OIDC Provider は問題なく、AssumeRole の設定にミスがあります。

  • (AWSの設定ミス) AssumeRole の Action が "Action": "sts:AssumeRoleWithWebIdentity" になっていない。
  • (AWSの設定ミス) 複数リポジトリなのに ForAnyValue:StringLike ではなく StringLike で判定している。
  • (AWSの設定ミス) AWS の IAM Role の Assume Policy が設定しようとしている GitHub Owner/Repository:ブランチ と内容と一致していない。

過去にある類似記事との差分

GA前の内容で、結構ずれています。GA前の記事の内容でやると失敗するので注意です。(aws-actions/configure-aws-credentials が v1 で OIDC 変更を反映すればいける)

dev.classmethod.jp

zenn.dev

github.com