AWS CDK issue 21197 - OIDCProvider L2 の再構成についてメモ
issue: https://github.com/aws/aws-cdk/issues/21197
概要
CDK の OpenIdConnectProvider
は CustomResource を使っている。
AWS::IAM::OIDCProvider
を使った L2 に再構築したい。
議論
過去に PR を送った人がいたが、Feature flag に対応していなかったのでクローズされた。
L2 レベルの変更なので RFC が出ている
今提供している OIDCProvider L2 は、証明書のダウンロードと thumbprint の取得・検証を行っていて、そこが引き続き提供したい部分になる。
今 CustomResource でやっているのは CreateOpenIDConnectProvider
API によるリソース作成と、証明書のダウンロード
本来の AWS::IAM::OIDCProvider
を使う場合、後者の証明書 (というより thumbprint) 関係だけが残るので、それを CustomResource として残し、OIDCProvider は AWS::IAM::OpenIdConnectProvider
にする方針が良い、と言っている。
OIDCProvider L2 Construct
CustomResource impl
やんなきゃいけないことは;
Thumbprint
カスタムリソースの実装。
証明書のダウンロード部分だけ切り出して Construct にする必要がある。
関係しているのは、
packages/aws-cdk-lib/aws-iam/lib/oidc-provider/external.ts
の downloadThumbprint
のみ。
従来の L2 (CustomResource) では onCreate, onUpdate で呼び出しが入っている。
onCreate, onUpdate のどちらも、thumbprint の引数がない場合のデフォルト挙動としてこれが入っている。
OIDCProvider リソースとしての return は以下
AWS User Guide - CustomResource によれば $.Data
以下の key-value は Fn::GetAtt
によって取得可能とのこと
一方、ネイティブリソースでは GetAtt できるものは異なる様子。 Arn しか返せない。
ここは今は(重要度が相対的に小さく見えるので)考えないようにする。
Thumbprint を Construct で構成する場合、なにが必要になるか??
実質的に downloadThumbprint
の結果を引っ張ってくることだけなので、ダウンロードしてその戻り値を CsutomResource の戻り値として返す実装があれば良い、といえそう
RFC では Thumbprint を L2 に切り出す、と言っているが考えること増えててあんまり良くないんじゃない?
...と思っている。普通に Construct を作成するタイミングで作るのではダメなのか。
AWS API を叩くようなものではないので、問題があるとすれば synth, deploy する際の実行環境がインターネットに出られることを要求することくらい。とはいえすでに外部通信を要求する話はあるので大きな問題ではないように見える。
いったん、Thumbprint 用の Construct は切らない方針で実装してみようと思う
「なんで Thumbprint をわざわざ Construct にするのか、OIDCProvider L2 で直接呼べばいいじゃないか」
と思っていたんだけど、これすると非同期が必須になる。このへんが jsii の制約か何かに引っかかるのではないか?という仮説を立てた。
このへん流し読みしてみる。
あるいは、Intro から参照のある Author Guide あたりにありそう
テーマ: jsii だと Construct に非同期は使えない制約がある?
まずは jsii の概要を調べる
トップページ に、
jsii allows code in any language to naturally interact with JavaScript classes. It is the technology that enables the AWS Cloud Development Kit to deliver polyglot libraries from a single codebase!
と書いてあった。てっきりトランスパイルするものだと思っていたけど、実際には他の言語から JavaScript への FFI 的なものっぽい?
Runtime Architecture の図を見ると実際そうっぽい。CDK TypeScript が各種対応言語向けの binding を生成していて、実際の機能は jsii Runtime によって JavaScript 側にある機能の実体と通信することで提供されている様子がわかる
┌─────────────────────────┐ ┌────────────┬────┬────┬────┐
│ │ │ │ │ │ │
│ Host Application │ │@jsii/kernel│LibA│LibB│... │
│ │ │ │ │ │ │
│ ┌──────────────────┤ ├────────────┴────┴────┴────┤
│ │ │ │ │
│ │Generated Bindings│ │ @jsii/runtime │
│ │ │ │ │
│ ├──────────────────┤ Requests ├──────┬────────────────────┤
│ │ ├───────────────▶STDIN │ │
│ │Host jsii Runtime │ Responses ├──────┤ │
│ │ Library ◀───────────────┤STDOUT│ │
│ │ │ Console ├──────┤ node │
│ │ ◀───────────────┤STDERR│ │
├──────┴──────────────────┤ ├──────┘ │
│ Host Runtime │ │ (Child Process) │
│ (JVM, .NET Core, ...) │ │ │
│ │ │ │
├─────────────────────────┴───────────────┴───────────────────────────┤
│ │
│ Operating System │
│ │
└─────────────────────────────────────────────────────────────────────┘
jsii の制約はTypeScript Restrictions に書いてある
クラスのプロパティには、PascalCased なクラス名と同名のものを宣言できない
// 例
export class Foo {
public foo: string;
}
interface は2種類の用法が許されている
kind | description | Naming |
---|---|---|
Behavioral | メソッド、プロパティを持てる |
I で始まる名前 |
Struct | イミュータブルなデータエンティティ。readonly プロパティしか宣言できない |
I で始まらない名前 |
Struct の場合は、同じ Struct タイプの interface を extend することができる
オーバーライドされたメンバーは元のメンバーと同じ可視性を持つ
index signatures が使えない
export interface WithIndexSignature {
public readonly name: string;
// 💥 Index signatures are not supported
public [key: string]: unknown;
}
(これ index signature ていうのか...)
ジェネリック使った型は宣言できない
// 💥 Parameterized types cannot be introduced
export interface Parameterized<T> {
readonly value: T;
}
export interface IAsyncFooMaker {
// ✅ Asynchronous methods must return promises
makeFoo(): Promise<Foo>;
// ✅ Arrays are supported
makeFoos(count: number): Array<Promise<Foo>>;
}
非同期メソッドは Promise の戻り値なら使える。Array も OK
Type alias は TypeScript の中でだけ使える。使えはする。
// 👻 Only visible in TypeScript
export type FooOrBar = Foo | Bar;
export interface Props {
// ⚠️ Effectively `readonly fooOrBar: Foo | Bar;` in non-TypeScript
readonly fooOrBar: FooOrBar;
}
他の言語の予約語に被る
jsii が警告を出す
Primise なら非同期も行けそう。
同僚氏が最近書いた PR が割といい感じなのでこれを見ながら変更すべき場所にアタリを付けていく
Thumbprint Construct のテストどう書くか作戦
とりあえず2種類のテストを書かなくちゃならない
(1) Construct 単体のテスト
packages/aws-cdk-lib/aws-iam/test/oidc-provider.test.ts
が既存のやつ。
Feature Flag 有効化した場合の挙動を足す必要がある
(2) Integ Test
packages/@aws-cdk-testing/framework-integ/test/aws-iam/test/integ.oidc-provider.ts
が既存のやつ。
Slack 見てみると、OIDC Provider について会話している履歴があった。
急がないと先を越されそう。
If I'm working on contributing a change to https://github.com/aws/aws-cdk/, is there a way I can rebuild only the subsets of aws-cdk-lib that I've changed? For example, if I change
aws-cdk/packages/aws-cdk-lib/aws-iam/lib/oidc-provider.ts
, is there a command I can run other thanyarn build
fromaws-cdk-lib/
, that will be faster?
回答がこれ。デフォルトでいけるっぽい
Yes. I think that's the default. Don't remember the exact command, but it only builds that package and its dependencies.
because the yarn build works in that context onl
最近持ち込まれた feature flag が参考になりそうなのでこれのソース追いかけてみると良さそう?
AUTOSCALING_GENERATE_LAUNCH_TEMPLATE