
kviklet v0.9.0
データベースクエリに対するプルリクエスト形式のレビュー/承認フロー。コンプライアンスを確保しつつ、エンジニアがスムーズに本番環境へアクセスできるようにします。
Kviklet
Kviklet.dev | リリースノート | Discord
開発者の生産性を損なうことなく、本番環境への安全なアクセスを実現します。

Kviklet(クイックレットと発音)は、本番データベースアクセスに四眼原則を適用し、個々のSQL文または時間制限付きデータベースセッションに対して、プルリクエストのようなレビューと承認のワークフローを提供します。エンジニアは、すべてのクエリをDBAや運用チーム経由にすることなく、互いのリクエストをレビューして承認できます。
Kvikletはセルフホスト型で、アプリケーション状態用のPostgreSQLデータベースを備えたDockerコンテナとして動作します。Webインターフェースからリクエストの送信、レビュー、実行が可能です。オプションのエンタープライズライセンスにより、SAML認証、ロールベースのレビュー要件、ロール同期、APIキーが利用可能になります。エンタープライズライセンスはkviklet.devでお申し込みください。
対応データベースはPostgres、MySQL、MariaDB、MS SQL Server、MongoDBです。
アクセスモデル
Kvikletを既存のIDプロバイダーに接続することを推奨します。KvikletはOIDC(Google、Keycloakなど)またはSAML(エンタープライズ限定)によるSSO、およびLDAP認証(Active Directoryなど)をサポートしています。
ユーザーは特定のデータベースユーザーにマッピングされた接続に対してリクエストを作成します。これらのリクエストは以下のいずれかです:
- 単一クエリ: レビューのために送信された特定のSQL文。
- 一時アクセス: 複数の文を実行できる時間制限付きセッション。
設定に応じて、Kvikletが実行を許可する前に、リクエストは他のユーザーによってレビューおよび承認されます。
Kvikletはユーザーに代わってデータベースに接続します。接続のデータベースパスワードがユーザーに表示されることはありません。
管理者は、どのロールがどの接続にアクセスできるか、および実行に必要なレビューゲートを設定できます。データベースレベルのアクセスは、基盤となるデータベースのRBACメカニズムを介して管理されます。例えば、読み取り専用接続用に読み取り専用ロールを作成し、書き込み接続よりも少ないレビュー要件を割り当てることが可能です。
Kvikletは実行された文を記録し、ユーザーとアクセスリクエストに関連付けます。手動によるデータベースアクセスを完全にカバーするには、直接接続を制限し、すべての手動アクセスをKviklet経由でルーティングしてください。エンジニアは基盤となるデータベース認証情報を受け取ったり共有したりする必要がありません。
追加のエンタープライズ機能には以下が含まれます:
- SAML: SAML認証のサポート。
- プロキシ(Postgres、MariaDB、MySQL):一時パスワードを使用した承認済みの一時アクセスセッションを通じて、お好みのデータベースクライアントを使用できます。実行された文はKvikletの監査ログに記録されます。
- ロールベースのレビューゲート: 実行前に特定のロールからの承認を要求します。
- ロール同期: IDプロバイダーのグループからユーザーロールを自動的に同期します。
- APIキー: Kviklet APIへのプログラムによるアクセス。
その他のスクリーンショット
リクエスト
すべてのデータリクエストが一箇所に集約されます。本番データベースのオープンPRのように:

ライブセッション
承認された一時アクセスリクエストは、ブラウザ上で直接ライブSQLセッションを開きます:

監査ログ
実行されたすべての文が記録されます — レビュー済みの単一クエリとして実行されたか、ライブセッション内で実行されたか、データベースプロキシ経由で実行されたかに関わらず:

データベース/接続タイプ別の機能
ほとんどの機能はすべてのデータベースで利用可能です(SSO、LDAP、RBAC、レビュー/承認フロー、監査ログなど)。ただし、一部の機能は制限されています。単にまだ実装されていないか、その特定の目的に対して意味をなさないかのいずれかです。以下の表は、どの機能がどのデータベースタイプで利用可能かを示しています:
| Database | Statement Review | Temporary Access | Proxy(Beta) | Explain Plan |
|---|---|---|---|---|
| Postgres | ✓ | ✓ | ✓ | ✓ |
| MySQL | ✓ | ✓ | ✓ | ✓ |
| MariaDB | ✓ | ✓ | ✓ | ✓ |
| SQL Server | ✓ | ✓ | ✗ | ✓ |
| MongoDB | ✓ | ✓ | ✗ | ✗ |
| Kubernetes | ✓ | ✗ | ✗ | ✗ |
セットアップ
KvikletはシンプルなDockerコンテナとして提供されます。
利用可能なバージョンはReleasesで確認できます。新機能を継続的に開発しているため、使用しているバージョンを定期的に更新することを推奨します。
現在の最新版はghcr.io/kviklet/kviklet:0.8.0です。:mainも使用できますが、時折バグのあるものが誤ってマージされる可能性があります。ただし、それは避けるよう努めています。
クイックスタート
どのように動作するか試してみたいだけの場合:
-
以下は最小限のdocker-compose.yamlです:
クリックしてcomposeの内容を展開
``` services: postgres: image: postgres:16 restart: always environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_DB: postgres ports: - "5432:5432" volumes: - ./postgres-data:/var/lib/postgresql/data # - ./sample_data.sql:/docker-entrypoint-initdb.d/init.sqlkviklet-postgres: image: postgres:16 restart: always environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_DB: kviklet ports: - "5433:5432" volumes: - ./kviklet-postgres-data:/var/lib/postgresql/data
kviklet: image: ghcr.io/kviklet/kviklet:main ports: - "80:8080" environment: - SPRING_DATASOURCE_URL=jdbc:postgresql://kviklet-postgres:5432/kviklet - SPRING_DATASOURCE_USERNAME=postgres - SPRING_DATASOURCE_PASSWORD=postgres - INITIAL_USER_EMAIL=[email protected] - INITIAL_USER_PASSWORD=admin depends_on: - kviklet-postgres
-
docker-compose up -dでdocker-compose.ymlを実行します。Kviklet はポート 80 で起動するので、localhostにアクセスして試してみてください。管理者ログインは [email protected]、パスワードはadminです。 -
docker-compose には、Kviklet で接続を設定できる追加の postgres データベースが含まれています。このデータベースにデータを入れるには、次の行のコメントを解除してください: ``` - ./sample_data.sql:/docker-entrypoint-initdb.d/init.sql
そして、sample_data.sql ファイルを作成します:
クリックして sample_data.sql の内容を展開
```sql CREATE TABLE Locations ( Name VARCHAR(100) NOT NULL, Address VARCHAR(255) NOT NULL, City VARCHAR(100) NOT NULL, Country VARCHAR(100) NOT NULL, PostalCode VARCHAR(20) NOT NULL );alter table public.Locations owner to postgres;
INSERT INTO public.Locations (Name, Address, City, Country, PostalCode) VALUES ('Central Park', '59th to 110th St', 'New York', 'USA', '10022'), ('Eiffel Tower', 'Champ de Mars, 5 Avenue Anatole', 'Paris', 'France', '75007'), ('Colosseum', 'Piazza del Colosseo, 1', 'Rome', 'Italy', '00184'), ('Sydney Opera House', 'Bennelong Point', 'Sydney', 'Australia', '2000'), ('Great Wall of China', 'Huairou District', 'Beijing', 'China', '101405');
</details>
### DB セットアップ
Kviklet はクエリ、接続、承認などに関するメタデータを保存するために、独自の postgres データベース(または少なくともスキーマ)を必要とします。
公式イメージはこちらにあります: https://hub.docker.com/_/postgres、またはお好みのクラウドプロバイダーが提供するクラウドホスト版を利用することもできます。
kviklet コンテナを起動する際には、次の 3 つの環境変数を適切に設定する必要があります:```
SPRING_DATASOURCE_PASSWORD = password
SPRING_DATASOURCE_USERNAME = username
SPRING_DATASOURCE_URL = jdbc:postgresql://[host]:[port]/[database]?currentSchema=[schema]
代替認証方法
- IAM 認証:
データベース接続に AWS IAM 認証を使用することが可能です。その場合はパスワードを省略し、ユーザー名のみを設定します。
また、以下の環境変数を設定する必要があります: ```
SPRING_DATASOURCE_IAMAUTH=true
Kvikletは通常の場所(環境変数、インスタンスロールなど)から認証情報を読み込み、接続用のトークンを生成します。
- 証明書: DB接続に証明書を使用することもできます。例についてはこちらを参照してください。
初期ユーザー
設定のために初期管理者ユーザーが必要です。そのためには、2つの環境変数INITIAL_USER_EMAILとINITIAL_USER_PASSWORDを設定して、Webインターフェースにログインできるようにします。パスワードは後でUIから変更できます。
例:```
INITIAL_USER_EMAIL=[email protected]
INITIAL_USER_PASSWORD=someverysecurepassword
私たちは現在、コンテナを GitHub packages に公開しているので、これらをすべて設定した上で `ghcr.io/kviklet/kviklet:main` を実行できます。Kviklet が起動するデフォルトポートである `8080` のマッピングを忘れないでください。
docker run の例は次のようになります:```
docker run \
-e SPRING_DATASOURCE_PASSWORD=postgres \
-e SPRING_DATASOURCE_USERNAME=postgres \
-e SPRING_DATASOURCE_URL=jdbc:postgresql://localhost:5432/Kviklet \
-e [email protected] \
-e INITIAL_USER_PASSWORD=someverysecurepassword \
--network host \
ghcr.io/kviklet/kviklet:main
OIDC / OAuth2 による SSO
Kviklet インスタンスに SSO を設定したい場合(そうしないとパスワードを再度管理する必要があるため、設定することを強くお勧めします)。 以下の 3 つの環境変数を設定する必要があります:``` KVIKLET_IDENTITYPROVIDER_CLIENTID KVIKLET_IDENTITYPROVIDER_CLIENTSECRET KVIKLET_IDENTITYPROVIDER_TYPE=google
google client id と secret は、以下の google の手順に従うことで簡単に取得できます:
https://developers.google.com/identity/gsi/web/guides/get-google-api-clientid
有効なリダイレクト URI には、以下を設定する必要があります:https://[kviklet_host]/api/login/oauth2/code/google
許可されたオリジンには、単にあなたのホストされた kviklet URL を設定します。
これらの環境変数を設定した後、組織内の全員が「Sign in with Google」ボタンでログインできるようになります。ただし、デフォルトでは誰も権限を持っていないため、一度ログインした後にロールを割り当てる必要があります。
#### Keycloak
代わりに Keycloak で SSO をセットアップしたい場合は、以下の 4 つの環境変数を設定する必要があります:```
KVIKLET_IDENTITYPROVIDER_CLIENTID
KVIKLET_IDENTITYPROVIDER_CLIENTSECRET
KVIKLET_IDENTITYPROVIDER_TYPE=keycloak
KVIKLET_IDENTITYPROVIDER_ISSUERURI=http://[host]:[port]/realms/[realm]
Keycloak でアプリケーションを作成すると、クライアント ID とシークレットを取得できます。 有効なリダイレクト URI には、以下を設定する必要があります: https://[kviklet_host]/api/login/oauth2/code/keycloak 許可されたオリジンには、単にホストされている kviklet の URL を設定します。
これらの環境変数を設定すると、ログインページに Keycloak でログインボタンが表示され、お使いの Keycloak インスタンスにリダイレクトされます。エンタープライズエディションでは、ロール同期を有効にして、Keycloak インスタンスから kviklet へロールを自動的に同期できます。詳細については、ロール同期セクションを参照してください。
GitHub (ベータ)
ベータ: GitHub 認証は新機能であり、まだロール同期をサポートしていません — すべての新規ユーザーはデフォルトロールで登録され、手動でロールを割り当てる必要があります。
GitHub は OIDC 準拠ではありません(純粋な OAuth 2.0 です)ので、Kviklet では専用のサポートを提供しています。以下の環境変数を設定してください:``` KVIKLET_IDENTITYPROVIDER_CLIENTID KVIKLET_IDENTITYPROVIDER_CLIENTSECRET KVIKLET_IDENTITYPROVIDER_TYPE=github KVIKLET_IDENTITYPROVIDER_GITHUB_ALLOWEDORGS=your-org,another-org
https://github.com/settings/developers で GitHub OAuth App を作成し、以下を設定します:
- Authorization callback URL: `https://[kviklet_host]/api/login/oauth2/code/github`
- Homepage URL: ホストしている Kviklet の URL
`KVIKLET_IDENTITYPROVIDER_GITHUB_ALLOWEDORGS` は**必須**です(これがないと Kviklet は起動を拒否します)。GitHub OAuth App は OAuth フローを完了できるユーザーを制限できないため、Kviklet は認証後に `/user/orgs` を呼び出し、許可リストに登録された組織の少なくとも1つに所属していないユーザーを拒否します(大文字小文字を区別せず、最初の100組織をチェック)。
組織チェックでユーザーのメンバーシップを確認するには、ユーザーが OAuth 同意画面で許可リストに登録された各組織の横にある **Grant**(または **Request**)をクリックする必要があります。組織で「Restrict third-party OAuth applications」が有効になっている場合、メンバーのメンバーシップが表示されるようになる前に、組織のオーナーが一度 OAuth アプリを承認する必要もあります。
Kviklet は `read:user`、`user:email`、`read:org` スコープを要求します。メールアドレスは常に `/user/emails` から読み取られ、`primary && verified` のエントリのみが受け入れられるため、メールアドレスを非公開にしているユーザーでも正常にログインできます。
#### その他の OIDC プロバイダー
その他の OIDC 準拠プロバイダー(GitLab、Auth0、Okta など)も Keycloak と同様に動作するはずです。選択したタイプによって `redirect URI` が変わることに注意してください。例えば `gitlab` を選択した場合、`https://[kviklet_host]/api/login/oauth2/code/gitlab` になります。
問題が発生した場合は、お気軽に issue を作成してください。私たちは(まだ)世の中のすべての OIDC プロバイダーを試したわけではなく、Kviklet 側での更新が必要となる実装上の微妙な違いがあるかもしれません。
### LDAP
Kviklet は LDAP 認証をサポートしています。LDAP を有効化および設定するには、以下の環境変数を上書きします:```
LDAP_ENABLED=true
LDAP_URL=ldap://your-ldap-server:389
LDAP_BASE=dc=your,dc=domain,dc=com
LDAP_PRINCIPAL=cn=admin,dc=your,dc=domain,dc=com
LDAP_PASSWORD=your-admin-password
LDAP_UNIQUE_IDENTIFIER_ATTRIBUTE=uid
LDAP_EMAIL_ATTRIBUTE=mail
LDAP_FULL_NAME_ATTRIBUTE=cn
LDAP_USER_OU=people
LDAP_SEARCH_BASE=ou=people
各設定の意味は次のとおりです:
LDAP_ENABLED: LDAP 認証を有効にするにはtrueに設定します。LDAP_URL: LDAP サーバーの URL。LDAP_BASE: LDAP 検索のベース DN。LDAP_PRINCIPAL: LDAP サーバーへのバインドに使用する管理者ユーザーの DN。LDAP_PASSWORD: 管理者ユーザーのパスワード。LDAP_UNIQUE_IDENTIFIER_ATTRIBUTE: ユーザーの一意の識別子として使用される LDAP 属性(デフォルト: "uid")。LDAP_EMAIL_ATTRIBUTE: ユーザーのメールアドレスを含む LDAP 属性(デフォルト: "mail")。LDAP_FULL_NAME_ATTRIBUTE: ユーザーのフルネームを含む LDAP 属性(デフォルト: "cn")。LDAP_USER_OU: ユーザーアカウントが保存される組織単位(OU)(デフォルト: "people")。LDAP_SEARCH_BASE: ユーザー検索のベース DN を上書きできます(デフォルト: "ou=people")。FreeIPA を使用している場合は、例えばcn=usersに設定する必要があるかもしれません。設定した場合、LDAP_USER_OU は無視されます。
これらの属性は、LDAP スキーマに合わせてカスタマイズできます。LDAP を設定すると、ユーザーは LDAP 認証情報を使用してログインできるようになります。LDAP ユーザーが初めてログインすると、デフォルトの権限を持つ対応するユーザーアカウントが Kviklet に作成されます。管理者は、これらのユーザーの初回ログイン後に適切なロールを割り当てる必要があります。
SAML(エンタープライズのみ)
Kviklet は SAML 2.0 認証をサポートしています。SAML を有効にするには、次の環境変数を設定します:``` SAML_ENABLED=true SAML_ENTITYID=https://your-identity-provider.com SAML_SSOSERVICELOCATION=https://your-identity-provider.com/sso SAML_VERIFICATIONCERTIFICATE=-----BEGIN CERTIFICATE-----\nMIICmzCCAYMCBgF4...\n-----END CERTIFICATE-----
設定の詳細:
- `SAML_ENABLED`: SAML 認証を有効にするには `true` に設定します
- `SAML_ENTITYID`: SAML ID プロバイダーのエンティティ ID
- `SAML_SSOSERVICELOCATION`: ID プロバイダーの SSO サービス URL
- `SAML_VERIFICATIONCERTIFICATE`: SAML レスポンスの検証に使用する X.509 証明書(BEGIN/END CERTIFICATE 行を含めてください)
オプションで SAML 属性マッピングをカスタマイズできます:```
SAML_USERATTRIBUTES_EMAILATTRIBUTE=email
SAML_USERATTRIBUTES_NAMEATTRIBUTE=name
SAML_USERATTRIBUTES_IDATTRIBUTE=nameID
ID プロバイダーは次のように設定する必要があります:
- Entity ID:
https://[kviklet_host]/api/saml2/service-provider-metadata/saml - Redirect Uri:
https://[kviklet_host]/api/login/saml2/sso/saml
SAML を設定すると、ユーザーは ID プロバイダー経由でログインできるようになります。初回ログイン時に、デフォルトの権限を持つユーザーアカウントが作成されます。
IDP に正しくリダイレクトされたものの CORS エラーが発生する場合は、Kviklet で許可されたオリジンに IDP のホストを追加できます:``` CORS_ALLOWEDORIGINS=https://[idp_host]
## 設定
### 接続
Kviklet を起動したら、まずデータベース接続を設定する必要があります。Settings -> Databases -> Add Connection に移動してください。


ここでは、各接続のレビュー要件と実行制限を設定できます。詳細は[レビューゲート](#review-gates)を参照してください。
#### AWS IAM AUTH
Kviklet は Postgres、MySQL、MariaDB のデータベース接続で IAM Auth の使用をサポートしています。これを使用するには、新しい接続を作成する際に IAM Auth を選択してください。


これによりパスワードを設定するオプションが削除され、代わりに AWS 認証情報を使用してデータベースに接続します。
Kviklet は AWS の `DefaultCredentialsProvider` を使用して認証情報を検索し、接続用のトークンを生成します。つまり、通常の場所(環境変数や関連付けられたインスタンスロール)はすべて機能するはずです。正確な順序はこちらに記載されています: https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/auth/credentials/DefaultCredentialsProvider.html
さらに、Kviklet が引き受ける AWS ロール ARN を指定し、その認証情報を使用して一時的な DB トークンを作成することもできます。これは、Kviklet とは異なる AWS アカウントにあるデータベースに接続する場合に特に便利です。この機能を使用するには、IAM Auth 接続の作成または編集時に、指定されたフィールドにロール ARN を入力するだけです。フィールドを空のままにすると、デフォルトの認証情報プロバイダーが使用されます(ロールの引き受けは行われません)。
トークン生成時に使用する AWS リージョンは接続 URL から推測されるため、設定するオプションはありません。
データベースの IAM Auth を設定する方法については、公式の AWS ドキュメントに従ってください: https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.html
主なポイントは次の 2 つです:
- IAM auth オプションと正しい権限を持つ DB ユーザーを作成する
- AWS エンティティがこのユーザーのトークンを生成できるようにする IAM ポリシーを作成する
### レビューゲート
デフォルトでは、Kviklet はシンプルなレビュー数の設定を許可します。特定の接続に対するリクエストが実行される前に必要な承認数を設定できます。
リクエストの承認ステータスは、各レビュアーの最新のアクションに基づいて計算されます。レビュアーが承認した後に変更をリクエストした場合、変更リクエストのみがカウントされ、以前の承認は削除されます。リクエストを編集すると、常に以前のすべての承認がリセットされ、変更が最初にレビューされずに実行されないことが保証されます。同様に、実行が失敗した場合(例: SQL 構文エラーによるもの)、承認がリセットされるため、新しいリクエストを作成することなく、リクエストを修正して再承認できます。
接続ごとに **最大実行回数** 制限を設定して、承認された 1 つのリクエストを実行できる頻度を制御することもできます。デフォルトは 1 です。これを 0 に設定すると無制限に実行できます。失敗した実行はこの制限にカウントされません。
#### ロールベースのレビュー要件(エンタープライズ)
Kviklet Enterprise ライセンスでは、特定のロールを持つユーザーからの承認を必要とするように個々の接続を設定できます。これにより、例えば特定のデータベースを保守するチームからの承認を要求したり、機密性の高い接続を DBA や管理者の承認でゲートしたりできます。
**仕組み:**
各接続には **必要な総レビュー数**(`numTotalRequired`)があり、これは下限として機能します。つまり、ロールに関係なく必要な異なる承認の最小数です。さらにその上に、特定のロールを持つユーザーからの承認数を指定する **ロール要件** を追加できます(例: 「DBA から 1 件、Security から 1 件」)。
リクエストは、**両方** の条件が満たされた場合にのみ承認されます:
- 異なる承認の総数が `numTotalRequired` を満たしている
- 各ロール要件が個別に満たされている
ユーザーが複数のロールに属している場合、そのユーザーからの 1 回の承認は、一致するすべてのロール要件にカウントされます。ただし、総数に対しては 1 つの承認としてのみカウントされます。
**例:** ある接続が、DBA から 1 件と Security から 1 件を含む合計 3 件の承認を必要としています。DBA と Security の両方のロールを持つユーザーが承認すると、これは両方のロール要件を満たしますが、必要な合計 3 件の承認のうち 1 件としてのみカウントされます。任意のユーザーからのさらに 2 件の承認が依然として必要です。
エンタープライズライセンスが期限切れになると、既存のロールベースのレビュー要件は引き続き適用されますが、変更できなくなります。シンプルな総レビュー数設定に戻すには、それらを削除することしかできません。
### ロール
Kviklet には Default、Admins、Developers の 3 つのロールが付属しています。
- デフォルトロールは、すべての接続とリクエストへの読み取りアクセスを提供します。このロールはすべてのユーザーに割り当てられ、削除できません。ただし、このロールの権限は自由に変更できます。
- Admins は、接続の作成と編集、および新しいユーザーの追加と権限の設定を行う権限を持っています。
- Developers は、リクエストの作成、およびそれらの承認とコメント、そしてもちろん実際のステートメントの実行ができます。
ロールをカスタマイズして、例えば特定の接続または DB 接続のグループへのアクセスのみをロールに付与できます。
これは、例えば異なるデータベースを持つ異なるチームがあり、それらへのアクセスをより細かく制御したい場合に便利です。
#### 新しいロールの作成
新しいロールの作成は次のように行います。Settings -> Roles -> Add Role に移動してください。


デフォルト設定はほとんどのロールにとって重要ではないため、User Read と RoleView アクセスを付与してそのままにしておくことができます。
より興味深いのは、接続に対する個別の権限の追加です。ここでは、まず特定の接続を選択するためのセレクターを追加します。これは特定の id にするか、`*` を使用したワイルドカードで複数の接続に一致させることができます。例えば、すべての dev データベースへのアクセスを持つロールを作りたい場合(kviklet でそれらへのアクセスも管理している場合)、`dev-*` のようなセレクターを使用し、接続の id が正しく設定されていることを確認します。
もちろん、組織内の異なるチーム用に使用する独自のシステムを考案することもできます。
### ロール同期(エンタープライズ)
アイデンティティプロバイダーのグループからユーザーロールを自動的に同期します。この機能にはエンタープライズライセンスが必要です。
**設定** は Settings > Role Sync で行います:
- **Enable Role Sync**: 同期のオン/オフ
- **Sync Mode**:
- **Full Sync** - ユーザーロールが IdP グループマッピングと正確に一致します(デフォルトロールに加えて)
- **Additive** - IdP グループがロールを追加しますが、既存のロールは削除しません
- **First Login Only** - ロールは初回ログイン時のみ同期され、その後の手動変更は保持されます
- **Groups Attribute**: グループメンバーシップを含む IdP 属性(デフォルト: `groups`)
- **Role Mappings**: IdP グループ名(例: `engineering`)を Kviklet ロールにマッピングします
#### OIDC セットアップ
OIDC プロバイダーを設定して、ID トークンに `groups` クレームを含めるようにします:
- **Keycloak**:
Keycloak はデフォルトでトークンにグループを含めないため、クライアントにマッパーを追加する必要があります。
1. 左メニューの **Clients** に移動します
2. Kviklet クライアントを選択します
3. **Client scopes** タブに移動します
4. 専用スコープ(例: `kviklet-dedicated`)をクリックします
5. **Mappers** タブに移動します
6. **Add mapper** → **By configuration** をクリックします
7. **Group Membership** を選択します
8. マッパーを設定します:
| Setting | Value |
| ------------------- | -------- |
| Name | `groups` |
| Token Claim Name | `groups` |
| Full group path | **OFF** |
| Add to ID token | **ON** |
| Add to access token | **ON** |
| Add to userinfo | **ON** |
9. **Save** をクリックします
> **重要:** 「Token Claim Name」は、Kviklet の Role Sync 設定で構成された「Groups Attribute」と一致する必要があります(デフォルト: `groups`)。
- **その他の OIDC プロバイダー**: ID トークンにユーザーのグループメンバーシップを含める groups マッパー/クレームを追加します。これは通常、プロバイダーの管理 UI で行います。
問題が発生した場合は、お気軽に issue を作成してください。私たちは(まだ)世の中のすべての OIDC プロバイダーを試したわけではなく、Kviklet 側での更新が必要となる実装の微妙な違いがあるかもしれません。
#### LDAP セットアップ
LDAP ロール同期は `memberOf` 属性を使用します:
1. LDAP サーバーで `memberOf` オーバーレイが有効になっていることを確認します
2. Kviklet で **Groups Attribute** を `memberOf` に設定します
3. グループ名は、ユーザー属性の `memberOf` 属性から抽出されます。
#### SAML セットアップ
SAML IdP を設定して、アサーションにグループを含めるようにします:
1. ユーザーのグループメンバーシップをマッピングする属性ステートメントを追加します
2. Kviklet の **Groups Attribute** を SAML 属性名に一致するように設定します
3. グループ名は、ユーザー属性の SAML 属性から抽出されます。
### 通知
Kviklet を設定して、Slack または Teams のチャンネルに通知を送信できます。これは、レビューが必要な新しいリクエストについてチームに通知するのに便利です。これは Settings -> General -> Notification Settings で設定できます。
#### Slack
Slack 通知を設定するには、Slack App を作成し、そのための webhook を有効にする必要があります。こちらの手順に従ってください: https://api.slack.com/messaging/webhooks
#### Teams
Teams 通知は Power Automate の **Workflow** webhook を使用します。Kviklet は Adaptive Card を送信し、webhook テンプレートがそれをチャンネルに投稿します。
**推奨: ワークフローテンプレートを使用する**
1. Teams で、通知を受け取りたいチャンネルを開き、チャンネル名の横にある **...** をクリックして **Workflows** を選択します(または **Workflows** アプリを追加します)。
2. **「Send webhook alerts to a channel」** テンプレートを検索して作成します。
3. プロンプトが表示されたらサインインし、対象の Team と Channel を選択してワークフローを作成します。
4. トリガーステップを開き、生成された **HTTP POST URL** をコピーします。
5. URL を Kviklet の Settings -> General -> Notification Settings に貼り付けて、保存をクリックします。
**代替案: ワークフローを手動で構築する**
自分でフローを構築したい場合(またはテンプレートが利用できない場合):
1. チャンネルの **...** -> **Workflows** -> トリガー **「When a Teams webhook request is received」** でフローを作成します。
2. アクション **Microsoft Teams -> 「Post card in a chat or channel」** を追加します。
3. アクションの **Adaptive Card** フィールドを式 `string(triggerBody())` に設定して、Kviklet が送信するカードを投稿するようにします。
4. 対象の Team と Channel を選択し、**Save** してから、トリガーステップから **HTTP POST URL** をコピーします。
現在、以下の通知があります:
- 承認が必要な新しいリクエスト
- リクエストへの新しい承認
#### ベース URL の設定
リバースプロキシまたは Kubernetes Ingress の背後で Kviklet を実行している場合、通知リンクがパブリックドメインではなく内部 IP アドレスを使用することがあります。Kviklet は受信リクエストを調べて正しい URL を追跡しようとしますが、一部のリバースプロキシは Forwarded ヘッダーを正しく設定しません。これを修正するには、ベース URL を明示的に設定します:```
KVIKLET_BASE_URL=https://kviklet.example.com
これにより、すべての通知リンクが正しい公開 URL を指すようになります。
テレメトリ
Kviklet は、どの機能が使用されているか、どこでエラーが発生しているかを把握するために、匿名の使用統計を報告します。無効にするには、次を設定します:``` KVIKLET_TELEMETRY_ENABLED=false
Kvikletは起動時にテレメトリが有効かどうかを示す1行をログに出力します。
**送信されるもの。** すべてのイベントには、ランダムなインスタンスID(一度生成され、Kvikletのデータベースに保存されます)、Kvikletにアクセスする際のベースURL(上記参照。多くの場合、内部ホスト名です)、およびKvikletのバージョンが含まれます。ユーザーはインスタンスにスコープされた不透明なIDによってのみ識別されるため、一意のユーザーをカウントできますが、メールアドレスや名前が送信されることは一切ありません。正確なイベントとそのプロパティは `backend/src/main/kotlin/dev/kviklet/kviklet/telemetry/TelemetryEvent.kt` で定義されています。
**送信されないもの。** クエリ、ステートメント、結果、コマンド出力、エラーメッセージ、接続名、ホスト名、認証情報、リクエストのタイトルや説明、コメント、およびユーザー名やロール名。
### ログ
デフォルトでは、Kvikletは人間が読める(整形された)ログをstdoutに書き込みます。これは、直接または `docker logs` を介してログを読む際に便利です。
ログを中央システム(Elasticsearch、Loki、Datadog、CloudWatchなど)に転送する場合は、代わりに構造化された**JSONログ**に切り替えることができます。こちらはインデックス作成やクエリが容易です。フォーマットは環境変数で設定します:```
# One of: ecs (Elastic Common Schema), logstash, gelf (Graylog)
LOGGING_STRUCTURED_FORMAT_CONSOLE=ecs
暗号化
認証情報をDBに平文で保存したくない場合は、Kvikletのpostgres DB自体でデータベース暗号化を有効にすることをお勧めします。ほとんどのホスティングプロバイダーでは、これはクリックするだけの簡単なチェックボックスです。 それでも、Kvikletデータベースが何らかの形で侵害された場合、これは重大なセキュリティリスクとなります。潜在的にすべての本番データストアのデータベース認証情報が含まれているためです。そのため、保存時の認証情報の暗号化を有効にすることができます。
これを行うには、2つの環境変数を設定するだけです。``` ENCRYPTION_ENABLED=true ENCRYPTION_KEY_CURRENT=some-secret
Kvikletは起動時に既存のすべての認証情報を暗号化し、今後作成する接続にはそのシークレットを使用します。
### キーローテーション
キーをローテーションしたい場合は、以前のキー用の変数をもう1つ追加し、現在のキーを変更するだけです:```
ENCRYPTION_KEY_PREVIOUS=some-secret
ENCRYPTION_KEY_CURRENT=another-secret
Kvikletは起動時にすべての接続を再暗号化するため、その後、以前のキーを削除した状態でコンテナを再起動できます。
APIキー
KvikletはシステムへのプログラムによるアクセスのためのAPIキーをサポートしています。これはエンタープライズ限定の機能であり、有効なライセンスが必要です。APIキーは設定 -> APIキーセクションで作成できます。

次のように使用します:```bash
curl --location '[kviklet_host]/api/connections/'
--header 'Authorization: Bearer your-api-key'
APIキーは、それを作成したユーザーの権限を継承します。現在、APIキーを管理できるのは管理者のみであり、APIキーを使用して実行されたすべての操作は、そのキーを作成したユーザーに帰属します。
基本的なAPIドキュメントは `[kviklet_host]/api/swagger-ui/index.html` にあります。ただし、これは作業中のものであり、将来のバージョンでAPIが変更される可能性があることにご注意ください。
最終的にはコードが真実ですので、APIがどのように定義されているかを確認するには、いつでもコントローラーを参照できます。ご質問があれば、お気軽にissueを作成してください。
## 実験的機能
現在、2つの実験的機能があります。これらは主にコミュニティからのフィードバックに基づいて構築されました。ぜひお試しいただき、ご意見をお聞かせください。今後さらに開発を進め、コアの承認フローとうまく連携できるようにしていきたいと考えています。
### Kubernetes Exec
Kubernetes Exec機能を使用するには、別途Kubernetes接続を作成する必要があります。Kvikletは、デプロイされたPodのユーザーを使用してコマンドを実行します。そのため、アクセスしたいPod上でコマンドを実行するために必要な権限がそのユーザーにあることを確認してください。
また、Kvikletはコマンドの実行に /bin/sh を使用するため、Podにシェルがあるか、少なくとも /bin/sh へのシンボリックリンクがあることを確認する必要があります。これが問題になる場合は、お気軽にissueを作成してください。設定可能にするか、別の解決策を見つけることができるかもしれません。
Kubernetesコマンドは出力を5秒間だけ待機します。コマンドがそれより長くかかる場合、Kvikletはコマンドをタイムアウトするまで最大1時間待機します。これは暫定的な解決策であり、websocketsを検討して、より応答性を高め、将来的にはターミナルセッションを可能にすることを目指しています。
### プロキシ - Postgres、MariaDB、MySQL (エンタープライズ)
一時アクセスのリクエストを作成する場合、Webインターフェースを使用する代わりに、kvikletが管理するプロキシを通じてクエリを実行し、お好みのDBクライアントを使用できます。
プロキシはエンタープライズ機能です。有効なライセンスが必要で、さらに管理者が Settings -> General -> Database Proxy で有効にする必要があります。
このため、コンテナは固定ポート(デフォルトでは5432と3306、`kviklet.proxy.postgres.port` と `kviklet.proxy.mysql.port` で設定可能)でリッスンするので、これらのポートを公開する必要があります。
ユーザーは一時アクセスリクエストを作成し、承認されたら「Start Proxy」をクリックできます。各リクエストには一時的なユーザー名とパスワードが割り当てられ、Kvikletはユーザー名によって各接続をそのリクエストにルーティングします。これらを使用してデータベースに接続できます。Kvikletは一時ユーザーとパスワードを検証し、すべてのリクエストをデータベース上の基盤となるユーザーにプロキシします。実行されたステートメントは、Webインターフェース経由で実行された場合と同様に監査ログに記録されます。
注: プロキシは現在、結果の追跡をサポートしていません。そのため、実行されたステートメントはログに記録されますが、結果やステートメントが成功したか失敗したかは記録されません。


#### プロキシ - TLS
KvikletはデータベースへのTLS接続を終端します。つまり、デフォルトではプロキシ自体との間のトラフィックは暗号化されません。
kvikletにトラフィックを再暗号化させたい場合は、以下の環境変数を設定して、プロキシ用のTLS証明書とキーをKvikletに提供できます:```
PROXY_TLS_CERTIFICATE_SOURCE=env
PROXY_TLS_CERTIFICATE_CERT=your-certificate
PROXY_TLS_CERTIFICATE_KEY=your-key
または、ファイルを使用することもできます:``` PROXY_TLS_CERTIFICATE_SOURCE=file PROXY_TLS_CERTIFICATE_CERT_FILE=path/to/cert.pem PROXY_TLS_CERTIFICATE_KEY_FILE=path/to/key.pem
いずれの場合も、証明書と鍵は [pem 形式](https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail) で保存する必要があります。
## 質問はありますか?コントリビューションは?
ご質問、フィードバックの提供、セットアップに関するサポートが必要な場合は、[Discord コミュニティ](https://discord.gg/7SmPJfeP6e) にご参加ください。バグ報告や機能リクエストには [GitHub issue](https://github.com/kviklet/kviklet/issues) を作成することもできます。
コントリビューションをご希望の場合は、些細なことであれば自由にフォークして PR を作成してください。より大きな機能を計画している場合は、GitHub issue または Discord で事前にいくつか議論していただけると助かります。
[email protected] までご連絡いただくこともできます。