返回更新列表
新发布Sep 22, 2026

kviklet v0.9.0

类似 Pull Request 的数据库查询审批/批准流程,用于合规但顺畅的工程人员访问生产环境。

分享

Kviklet

Kviklet.dev | 发布说明 | Discord

在不影响开发者生产力的情况下安全访问生产环境。

Kviklet Kviklet

Kviklet(发音为 Quick-let)将四眼原则应用于生产数据库访问,为单条 SQL 语句或限时数据库会话提供类似拉取请求的审查和批准工作流。工程师可以相互审查和批准彼此的请求,而无需将每个查询都通过 DBA 或运维团队。

Kviklet 是自托管的,作为 Docker 容器运行,并使用 PostgreSQL 数据库存储应用程序状态。其 Web 界面允许你提交、审查和执行请求。可选的企业许可证可解锁 SAML 身份验证、基于角色的审查要求、角色同步和 API 密钥。请在 kviklet.dev 申请企业许可证。

支持的数据库包括 PostgresMySQLMariaDBMS SQL ServerMongoDB

访问模型

我们建议将 Kviklet 连接到您现有的身份提供商。Kviklet 支持通过 OIDC(Google、Keycloak 等)或 SAML(仅限企业版)进行 SSO,以及 LDAP 身份验证(Active Directory 等)。 用户随后为映射到特定数据库用户的连接创建请求。这些请求可以是:

  • 单条查询:提交审查的特定 SQL 语句。
  • 临时访问:限时会话,您可以在其中运行多条语句。

根据配置,请求在 Kviklet 允许执行之前会由其他用户审查和批准。

Kviklet 代表用户连接到数据库。连接的数据库密码永远不会向用户显示。

管理员可以配置哪个角色有权访问哪个连接,以及执行需要哪些审查关卡。数据库级别的访问通过底层数据库的 RBAC 机制进行管理。例如,可以为只读连接创建只读角色,并为其分配比写入连接更少的审查要求。

Kviklet 记录已执行的语句,并将其与用户和访问请求关联。为了全面覆盖手动数据库访问,请限制直接连接,并将任何手动访问都通过 Kviklet 进行路由。工程师无需接收或共享底层数据库凭据。

额外的企业版功能包括:

  • SAML:支持 SAML 身份验证。
  • 代理(Postgres、MariaDB、MySQL):通过已批准的临时访问会话,使用临时密码,使用您首选的数据库客户端。已执行的语句会记录在 Kviklet 的审计日志中。
  • 基于角色的审查关卡:要求在执行前获得特定角色的批准。
  • 角色同步:自动从您的身份提供商组同步用户角色。
  • API 密钥:以编程方式访问 Kviklet API。
更多截图

请求

所有数据请求都集中在一个地方。就像您生产数据库的开放 PR:

Requests Requests

实时会话

已批准的临时访问请求会直接在浏览器中打开一个实时 SQL 会话:

Live Session Live Session

审计日志

每条已执行的语句都会被记录——无论是作为已审查的单条查询运行、在实时会话中运行,还是通过数据库代理运行:

audit log audit log

按数据库/连接类型划分的功能

大多数功能适用于所有数据库(SSO、LDAP、RBAC、审查/批准流程、审计日志等)。但某些功能受到限制,要么是因为尚未构建,要么是因为对该特定用途没有意义。下表显示了哪些功能适用于哪种数据库类型:

DatabaseStatement ReviewTemporary AccessProxy(Beta)Explain Plan
Postgres
MySQL
MariaDB
SQL Server
MongoDB
Kubernetes

设置

Kviklet 以简单的 docker 容器形式发布。 您可以在 Releases 下找到可用版本。我们建议定期更新您使用的版本,因为我们会继续构建新功能。 目前最新版本是 ghcr.io/kviklet/kviklet:0.8.0,您也可以使用 :main,但偶尔可能会发生我们意外合并了有问题的内容。不过我们会尽量避免这种情况。

快速开始

如果您只是想尝试一下它的工作方式:

  1. 以下是一个最小的 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.sql

    kviklet-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

  1. 通过 docker-compose up -d 运行 docker-compose.yml。Kviklet 将在 80 端口启动,访问 localhost 即可试用。管理员登录账号为 [email protected],密码为 admin

  2. docker-compose 中包含一个额外的 postgres 数据库,你可以在 Kviklet 中为其设置连接。要让该数据库包含一些数据,请取消注释以下行: ``` - ./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>

### 数据库设置

Kviklet 需要自己的 postgres 数据库(或至少是 schema)来保存关于查询、连接、审批等的元数据。
你可以在这里找到官方镜像:https://hub.docker.com/_/postgres,或使用你所选云服务商提供的云端托管版本。

启动 kviklet 容器时,你需要相应地设置以下三个环境变量:```
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 将从常见位置(环境变量、实例角色等)加载凭据,并为连接生成令牌。

  • 证书: 你也可以使用证书进行数据库连接,示例见此处

初始用户

你需要一个初始管理员用户来进行配置。为此,请设置两个环境变量: INITIAL_USER_EMAILINITIAL_USER_PASSWORD,以便你可以登录 Web 界面。之后你可以通过 UI 更改密码。
示例:``` INITIAL_USER_EMAIL=[email protected] INITIAL_USER_PASSWORD=someverysecurepassword

我们目前将容器发布到 GitHub packages,因此完成所有设置后,你可以运行 `ghcr.io/kviklet/kviklet:main`,别忘了映射端口 `8080`,这是 Kviklet 默认启动的端口。

一个 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

Google

如果你想为你的 Kviklet 实例设置 SSO(这非常合理,否则你又得管理密码了)。 你需要设置这 3 个环境变量:``` KVIKLET_IDENTITYPROVIDER_CLIENTID KVIKLET_IDENTITYPROVIDER_CLIENTSECRET KVIKLET_IDENTITYPROVIDER_TYPE=google

你可以按照 Google 的说明轻松获取 google client id 和 secret:
https://developers.google.com/identity/gsi/web/guides/get-google-api-clientid

对于有效的重定向 URI,你应该配置:https://[kviklet_host]/api/login/oauth2/code/google
对于允许的来源,只需填写你托管的 kviklet url。

设置这些环境变量后,你组织中的每个人都可以通过“使用 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。有关更多详细信息,请参阅 Role Sync 部分。

GitHub(Beta)

Beta: 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`,并拒绝不属于至少一个允许列表组织的用户(不区分大小写,仅检查前 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:设置为 true 以启用 LDAP 身份验证。
  • 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`:设置为 `true` 以启用 SAML 身份验证
- `SAML_ENTITYID`:您的 SAML 身份提供者的实体 ID
- `SAML_SSOSERVICELOCATION`:您的身份提供者的 SSO 服务 URL
- `SAML_VERIFICATIONCERTIFICATE`:用于验证 SAML 响应的 X.509 证书(包含 BEGIN/END CERTIFICATE 行)

您可以选择性地自定义 SAML 属性映射:```
SAML_USERATTRIBUTES_EMAILATTRIBUTE=email
SAML_USERATTRIBUTES_NAMEATTRIBUTE=name
SAML_USERATTRIBUTES_IDATTRIBUTE=nameID

你的身份提供者应配置为:

  • Entity ID:https://[kviklet_host]/api/saml2/service-provider-metadata/saml
  • Redirect Uri:https://[kviklet_host]/api/login/saml2/sso/saml

配置 SAML 后,用户可以通过身份提供者登录。首次登录时,会创建一个具有默认权限的用户账户。

如果你被正确重定向到 IDP,但随后遇到 cors 错误,你可以通过以下方式将你的 IDP 主机添加到 Kviklet 的允许来源中:``` CORS_ALLOWEDORIGINS=https://[idp_host]

## 配置

### 连接

启动 Kviklet 后,你首先需要配置一个数据库连接。前往 设置 -> 数据库 -> 添加连接。

![添加连接](https://assets.kitploit.com/production/public/readmes/7140/3ded2a0b23e5d2f02feb21a854263c91dedea25a789fb75ab8342384c4e39b52.png)
![添加连接](https://assets.kitploit.com/production/public/readmes/7140/585238c9eddad8ed4e2440096ce0616445a6696e1042f58676a1d0b038edde7f.png)

在这里,你可以为每个连接配置审核要求和执行限制。详情请参阅[审核门](#review-gates)。

#### AWS IAM 认证

Kviklet 支持为 Postgres、MySQL 和 MariaDB 数据库连接使用 IAM 认证,为此在创建新连接时选择 IAM 认证。

![IAM 认证](https://assets.kitploit.com/production/public/readmes/7140/14ed42bd639eb9b0ba81b22850e277703f2da9495dd101f68066f95fc51f291c.png)
![IAM 认证](https://assets.kitploit.com/production/public/readmes/7140/5a60a3a9ae527e11679f3c33c787caba4c80b379ddc463db1f871288408517e1.png)

这将移除设置密码的选项,转而使用 AWS 凭证连接到数据库。

Kviklet 使用 AWS 的 `DefaultCredentialsProvider` 来查找凭证并为连接生成令牌。这意味着所有常见的位置都应该可用(环境变量或关联的实例角色),确切的顺序在此处有文档说明:https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/auth/credentials/DefaultCredentialsProvider.html

此外,你可以提供一个 AWS 角色 ARN,Kviklet 将代入该角色,并使用这些凭证来创建临时的数据库令牌。这对于连接到与 Kviklet 不在同一 AWS 账户中的数据库特别有用。要使用此功能,只需在创建或编辑 IAM 认证连接时,在指定字段中输入角色 ARN。将该字段留空将使用默认凭证提供程序(不代入角色)。

令牌生成期间使用的 AWS 区域是从你的连接 URL 推断出来的,因此没有设置它的选项。

要了解如何为你的数据库设置 IAM 认证,请遵循 AWS 官方文档:https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.html
主要的两点是:

- 创建一个启用了 IAM 认证选项并具有正确权限的数据库用户
- 创建一个 IAM 策略,允许 AWS 实体为该用户生成令牌

### 审核门

默认情况下,Kviklet 允许简单的审核数量配置。你可以配置特定连接上的请求在执行之前需要多少个批准。

请求的批准状态是根据每个审核者的最新操作计算的。如果审核者批准后又请求更改,则只有更改请求计入——其先前的批准被移除。编辑请求总是会重置所有先前的批准,确保任何更改都必须先经过审核才能执行。同样,如果执行失败(例如由于 SQL 语法错误),批准会被重置,以便请求可以被更正并重新批准,而无需创建一个新的请求。

你还可以为每个连接配置**最大执行次数**限制,以控制单个已批准的请求可以执行的频率。默认值为 1。将其设置为 0 允许无限次执行。失败的执行不计入此限制。

#### 基于角色的审核要求(企业版)

拥有 Kviklet 企业版许可证,你可以配置单个连接要求来自具有特定角色的用户的批准。这允许你例如要求来自维护给定数据库的团队的批准,或将敏感连接置于 DBA 或管理层批准的门槛之后。

**工作原理:**

每个连接都有一个**所需审核总数**计数(`numTotalRequired`),它作为一个下限——无论角色如何,所需的不同批准的最小数量。在此基础上,你可以添加**角色要求**,指定必须有多少个批准来自具有特定角色的用户(例如,“1 个来自 DBA,1 个来自安全团队”)。

只有当**两个**条件都满足时,请求才会被批准:

- 不同批准的总数达到 `numTotalRequired`
- 每个角色要求都单独满足

如果用户属于多个角色,来自该用户的单个批准会计入所有匹配的角色要求。但是,它仍然只计为总数中的一个批准。

**示例:** 一个连接需要 3 个总批准,其中包括 1 个来自 DBA 和 1 个来自安全团队。一个同时拥有 DBA 和安全团队角色的用户批准了——这满足了两个角色要求,但只计为所需的 3 个总批准中的 1 个。仍然需要来自任何用户的另外两个批准。

如果你的企业版许可证过期,现有的基于角色的审核要求仍然会被强制执行,但无法再修改。你只能移除它们,以回退到简单的总审核数配置。

### 角色

Kviklet 附带 3 个角色:默认、管理员和开发者。

- 默认角色提供对所有连接和请求的读取访问权限。此角色分配给每个用户且无法移除。但是,你可以随意更改此角色的权限。
- 管理员有权创建和编辑连接,以及添加新用户并设置其权限。
- 开发者可以创建请求,以及批准和评论请求,当然还可以执行实际的语句。

你可以自定义角色,例如,让某个角色只能访问特定连接或一组数据库连接。
这很有用,例如,如果你有不同的团队使用不同的数据库,并希望更细粒度地控制对这些数据库的访问。

#### 创建新角色

创建新角色的操作如下。前往 设置 -> 角色 -> 添加角色。

![添加角色](https://assets.kitploit.com/production/public/readmes/7140/a91b79287c0b3130b83bdde1c059f49b89c5d43a1c0deae33b211ea427956f8e.png)
![添加角色](https://assets.kitploit.com/production/public/readmes/7140/c535ac152759bb21bea04a0968ce43fa7bf946c7699feca23c71f9eaba41ceaf.png)

默认设置对大多数角色来说并不重要,你可以直接给用户读取和角色查看访问权限,然后就这样。
更有趣的是为连接添加单独的权限。在这里,你首先添加一个选择器来选择特定的连接。这可以是一个特定的 id,或者你使用 `*` 通配符来匹配多个连接。例如,如果你想要一个可以访问所有开发数据库的角色(以防你也用 kviklet 管理对这些数据库的访问),你可以使用像 `dev-*` 这样的选择器,并确保连接的 id 设置正确。

当然,你也可以为组织内的不同团队制定一套自己的系统。

### 角色同步(企业版)

自动从你的身份提供程序组同步用户角色。此功能需要企业版许可证。

**配置**在 设置 > 角色同步 中完成:

- **启用角色同步**:打开/关闭同步
- **同步模式**:
  - **完全同步** - 用户角色与其 IdP 组映射完全匹配(加上默认角色)
  - **增量** - IdP 组添加角色但不移除现有角色
  - **仅首次登录** - 角色仅在首次登录时同步,之后保留手动更改
- **组属性**:包含组成员身份的 IdP 属性(默认:`groups`)
- **角色映射**:将 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. 配置映射器:

  | 设置             | 值    |
  | ------------------- | -------- |
  | 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 角色同步设置中配置的“组属性”匹配(默认:`groups`)。

- **其他 OIDC 提供程序**:添加一个组映射器/声明,在 ID 令牌中包含用户的组成员身份。这通常在提供程序的管理界面中完成。

  如果你遇到问题,请随时创建一个 issue,我们还没有尝试过所有的 OIDC 提供程序(目前),并且实现上可能存在细微差异,可能需要 Kviklet 这边进行更新。

#### LDAP 设置

LDAP 角色同步使用 `memberOf` 属性:

1. 确保你的 LDAP 服务器启用了 `memberOf` overlay
2. 在 Kviklet 中将**组属性**设置为 `memberOf`
3. 然后从用户属性中的 `memberOf` 属性提取组名称。

#### SAML 设置

配置你的 SAML IdP,在断言中包含组:

1. 添加一个映射用户组成员身份的属性语句
2. 在 Kviklet 中设置**组属性**以匹配你的 SAML 属性名称
3. 然后从用户属性中的 SAML 属性提取组名称。

### 通知

你可以配置 Kviklet 向 Slack 或 Teams 中的频道发送通知。这对于通知你的团队有需要审核的新请求很有用。你可以在 设置 -> 常规 -> 通知设置 中配置。

#### Slack

要配置 Slack 通知,你需要创建一个 Slack 应用并为其启用 webhooks。你可以按照此处的说明操作:https://api.slack.com/messaging/webhooks

#### Teams

Teams 通知使用 Power Automate **工作流** webhook。Kviklet 发送一个自适应卡片,webhook 模板将其发布到你的频道。

**推荐:使用工作流模板**

1. 在 Teams 中,打开你想要接收通知的频道,点击频道名称旁边的 **...**,然后选择 **工作流**(或添加 **工作流** 应用)。
2. 搜索并创建 **“向频道发送 webhook 警报”** 模板。
3. 在提示时登录,然后选择目标团队和频道并创建工作流。
4. 打开触发器步骤并复制生成的 **HTTP POST URL**。
5. 将 URL 粘贴到 Kviklet 的 设置 -> 常规 -> 通知设置 中,然后点击保存。

**替代方案:手动构建工作流**

如果你更喜欢自己构建流程(或者模板不可用):

1. 频道 **...** -> **工作流** -> 创建一个触发器为 **“收到 Teams webhook 请求时”** 的流程。
2. 添加操作 **Microsoft Teams -> “在聊天或频道中发布卡片”**。
3. 将该操作的 **自适应卡片** 字段设置为表达式 `string(triggerBody())`,以便它发布 Kviklet 发送的卡片。
4. 选择目标团队和频道,**保存**,然后从触发器步骤复制 **HTTP POST URL**。

目前有以下通知:

- 需要批准的新请求
- 请求上的新批准

#### 基础 URL 配置

当 Kviklet 在反向代理或 Kubernetes Ingress 后面运行时,通知链接可能会使用内部 IP 地址而不是你的公共域名。Kviklet 尝试通过查看传入请求来跟踪正确的 URL,但一些反向代理没有正确设置 Forwarded 头。要解决此问题,请显式设置基础 URL:```
KVIKLET_BASE_URL=https://kviklet.example.com

这确保所有通知链接都指向正确的公共 URL。

遥测

Kviklet 会报告匿名使用统计数据,以帮助我们了解哪些功能被使用以及错误发生在何处。要关闭此功能,请设置:``` KVIKLET_TELEMETRY_ENABLED=false

Kviklet 在启动时会记录一行日志,说明遥测是否开启。

**发送的内容。** 每个事件都携带一个随机实例 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

加密

如果你不希望凭据以明文形式存储在数据库中,建议在 Kviklet postgres 数据库本身上启用数据库加密。对于大多数托管服务提供商来说,这只是一个简单的勾选框。 尽管如此,如果 Kviklet 数据库以某种方式被攻破,这将是一个巨大的安全风险。因为它包含可能你所有生产数据存储的数据库凭据。因此,你可以启用凭据的静态加密。

要做到这一点,只需设置这两个环境变量。``` ENCRYPTION_ENABLED=true ENCRYPTION_KEY_CURRENT=some-secret

Kviklet 会在启动时加密您所有现有的凭据,并将该密钥用于您之后创建的未来连接。

### 密钥轮换

如果您想轮换密钥,只需为旧密钥添加另一个变量并更改当前密钥即可:```
ENCRYPTION_KEY_PREVIOUS=some-secret
ENCRYPTION_KEY_CURRENT=another-secret

Kviklet 将在启动时重新加密所有连接,这样您之后就可以在移除先前密钥的情况下重启容器。

API 密钥

Kviklet 支持使用 API 密钥进行程序化访问。这是一项仅限企业版的功能,需要有效的许可证。您可以在 设置 -> API 密钥 部分创建 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 可能会在未来版本中发生变化。

最终,真相在代码中,所以你随时可以查看 controller 来了解 API 是如何定义的。如果你有任何问题,欢迎提交 issue。

## 实验性功能

目前有两个实验性功能。它们主要基于社区反馈构建。欢迎试用这些功能并留下你的任何意见。我们希望在未来进一步发展这些功能,并使其与核心审批流程良好配合。

### Kubernetes Exec

如果你想使用 Kubernetes Exec 功能,你需要创建一个单独的 kubernetes 连接。Kviklet 将使用部署 pod 的用户来执行命令。因此请确保该用户具有在你想访问的 pod 上执行命令所需的权限。

Kviklet 还使用 /bin/sh 来执行命令,因此你需要确保你的 pod 有一个 shell,或者至少在 /bin/sh 中有一个符号链接。如果这让你感到困扰,欢迎提交 issue,我们可能会将其设为可配置,或者找到其他解决方案。

Kubernetes 命令只等待 5 秒的输出,如果命令耗时超过这个时间,Kviklet 将等待最多一小时,然后命令超时。这是一个临时解决方案,我们正在研究使用 websockets 来使其响应更快,并有可能启用终端会话。

### 代理 - Postgres、MariaDB、MySQL(企业版)

如果你为临时访问创建请求,你可以——而不是使用 Web 界面——通过 kviklet 管理的代理运行你的查询,并使用你选择的数据库客户端。
代理是一个企业版功能:它需要有效的许可证,并且管理员还需要在 设置 -> 通用 -> 数据库代理 下将其打开。
为此,容器监听稳定的端口(默认是 5432 和 3306,可通过 `kviklet.proxy.postgres.port` 和 `kviklet.proxy.mysql.port` 配置),因此你需要暴露这些端口。
用户随后可以创建一个临时访问请求,并在请求被批准后点击“启动代理”。每个请求都会获得一个临时用户名和密码;Kviklet 通过用户名将每个连接路由到其对应的请求。使用这些凭据,他们可以连接到数据库。Kviklet 验证临时用户和密码,并将所有请求代理到数据库上的底层用户。任何执行的语句都会像通过 Web 界面运行一样记录在审计日志中。

注意:代理目前不支持结果跟踪。因此执行的语句会被记录,但结果或语句是否成功或失败不会被记录。

![Postgres Proxy](https://assets.kitploit.com/production/public/readmes/7140/153b5b3e85c492079f01f1ffda490a53df2be01cfd808553abc511eb90fc1731.png)
![Postgres Proxy](https://assets.kitploit.com/production/public/readmes/7140/2c886b3cb184b13bbee9120ca5f1cdd9f45dd7743c5cf7a01fe8d5f7474d507a.png)

#### 代理 - TLS

Kviklet 终止到数据库的 TLS 连接。这意味着默认情况下,进出代理本身的任何流量都未加密。  
如果你希望 kviklet 重新加密流量,你可以通过设置以下环境变量为 Kviklet 提供代理的 TLS 证书和密钥:```
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) 来报告错误和提出功能请求。

如果您想贡献,欢迎 fork 并为小改动创建 PR。如果您计划开发较大的功能,我希望能在 GitHub issue 或 Discord 上先进行一些讨论。

您也可以通过 [email protected] 联系我。

分类