업데이트로 돌아가기
New releaseSep 22, 2026

kviklet v0.9.0

데이터베이스 쿼리에 대한 Pull Request 방식의 검토/승인 흐름. 규정을 준수하면서도 원활한 엔지니어의 프로덕션 접근을 위해.

공유

Kviklet

Kviklet.dev | 릴리스 노트 | Discord

개발자 생산성을 저하시키지 않으면서 프로덕션 환경에 안전하게 접근하세요.

Kviklet Kviklet

Kviklet(Quick-let으로 발음)은 프로덕션 데이터베이스 접근에 사안(四眼) 원칙을 적용하여, 개별 SQL 문 또는 시간 제한이 있는 데이터베이스 세션에 대해 풀 리퀘스트와 유사한 검토 및 승인 워크플로를 제공합니다. 엔지니어는 모든 쿼리를 DBA나 운영 팀을 거치지 않고도 서로의 요청을 검토하고 승인할 수 있습니다.

Kviklet은 자체 호스팅되며 애플리케이션 상태를 위한 PostgreSQL 데이터베이스와 함께 Docker 컨테이너로 실행됩니다. 웹 인터페이스를 통해 요청을 제출, 검토, 실행할 수 있습니다. 선택적 엔터프라이즈 라이선스는 SAML 인증, 역할 기반 검토 요구 사항, 역할 동기화, API 키를 활성화합니다. 엔터프라이즈 라이선스는 kviklet.dev에서 요청하세요.

지원되는 데이터베이스는 Postgres, MySQL, MariaDB, MS SQL Server, MongoDB입니다.

접근 모델

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에는 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 컨테이너를 시작할 때 다음 세 가지 환경 변수를 그에 맞게 설정해야 합니다:```
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는 일반적인 위치(환경 변수, 인스턴스 역할 등)에서 자격 증명을 로드하고 연결을 위한 토큰을 생성합니다.

  • 인증서: 데이터베이스 연결에 인증서를 사용할 수도 있습니다. 예시는 여기를 참조하세요.

초기 사용자

구성 목적으로 초기 관리자 사용자가 필요합니다. 이를 위해 2개의 환경 변수를 설정하세요: INITIAL_USER_EMAILINITIAL_USER_PASSWORD를 설정하면 웹 인터페이스에 로그인할 수 있습니다. 이후 UI를 통해 비밀번호를 변경할 수 있습니다.
예시:``` INITIAL_USER_EMAIL=[email protected] INITIAL_USER_PASSWORD=someverysecurepassword

현재로서는 컨테이너를 GitHub 패키지에 게시하고 있으므로, 이 모든 설정이 완료되면 `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

Google

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

유효한 redirect URI의 경우 다음을 구성해야 합니다: https://[kviklet_host]/api/login/oauth2/code/google
Allowed Origins의 경우, 간단히 호스팅된 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 허용된 Origin의 경우, 간단히 호스팅된 kviklet URL을 입력하면 됩니다.

이러한 환경 변수를 설정한 후 로그인 페이지에는 Keycloak 인스턴스로 리디렉션되는 Login with 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

GitHub OAuth App을 https://github.com/settings/developers 에서 생성하고 다음을 구성하세요:

- 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`이 됩니다.
문제가 발생하면 언제든지 이슈를 생성해 주세요. 우리는 (아직) 세상의 모든 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: 사용자 계정이 저장되는 Organizational Unit (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
- `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

Your identity provider should be configured with:

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

SAML을 구성한 후 사용자는 identity provider를 통해 로그인할 수 있습니다. 첫 로그인 시 기본 권한을 가진 사용자 계정이 생성됩니다.

IDP로 올바르게 리디렉션되었지만 이후 CORS 오류가 발생하는 경우, Kviklet에서 허용된 origins에 IDP의 호스트를 추가할 수 있습니다:``` CORS_ALLOWEDORIGINS=https://[idp_host]

## 구성

### 연결

Kviklet을 시작한 후 먼저 데이터베이스 연결을 구성해야 합니다. Settings -> Databases -> Add Connection으로 이동하세요.

![Add Connection](https://assets.kitploit.com/production/public/readmes/7140/3ded2a0b23e5d2f02feb21a854263c91dedea25a789fb75ab8342384c4e39b52.png)
![Add Connection](https://assets.kitploit.com/production/public/readmes/7140/585238c9eddad8ed4e2440096ce0616445a6696e1042f58676a1d0b038edde7f.png)

여기에서 각 연결에 대한 검토 요구 사항과 실행 제한을 구성할 수 있습니다. 자세한 내용은 [Review Gates](#review-gates)를 참조하세요.

#### AWS IAM AUTH

Kviklet은 Postgres, MySQL 및 MariaDB 데이터베이스 연결에 IAM Auth 사용을 지원합니다. 이를 위해서는 새 연결을 생성할 때 IAM Auth를 선택하세요.

![IAM Auth](https://assets.kitploit.com/production/public/readmes/7140/14ed42bd639eb9b0ba81b22850e277703f2da9495dd101f68066f95fc51f291c.png)
![IAM Auth](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

또한 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
주요 두 가지 사항은 다음과 같습니다:

- IAM auth 옵션과 올바른 권한을 가진 DB 사용자 생성
- AWS 엔터티가 이 사용자에 대한 토큰을 생성할 수 있도록 허용하는 IAM 정책 생성

### Review Gates

기본적으로 Kviklet은 간단한 검토 횟수 구성을 허용합니다. 특정 연결에 대한 요청이 실행되기 전에 필요한 승인 수를 구성할 수 있습니다.

요청의 승인 상태는 각 검토자의 최신 작업을 기반으로 계산됩니다. 검토자가 승인한 후 나중에 변경을 요청하면 변경 요청만 계산되며, 이전 승인은 제거됩니다. 요청을 편집하면 항상 모든 이전 승인이 재설정되어 검토 없이 변경 사항이 실행될 수 없도록 보장합니다. 마찬가지로 실행이 실패하면(예: SQL 구문 오류로 인해) 승인이 재설정되어 새 요청을 생성하지 않고도 요청을 수정하고 다시 승인할 수 있습니다.

또한 연결당 **최대 실행** 제한을 구성하여 단일 승인된 요청이 실행될 수 있는 빈도를 제어할 수 있습니다. 기본값은 1입니다. 이를 0으로 설정하면 무제한 실행이 가능합니다. 실패한 실행은 이 제한에 포함되지 않습니다.

#### 역할 기반 검토 요구 사항 (Enterprise)

Kviklet Enterprise 라이선스를 사용하면 개별 연결에 특정 역할을 가진 사용자의 승인을 요구하도록 구성할 수 있습니다. 이를 통해 예를 들어 특정 데이터베이스를 유지 관리하는 팀의 승인을 요구하거나 민감한 연결을 DBA 또는 관리 승인 뒤에 두도록 게이트할 수 있습니다.

**작동 방식:**

각 연결에는 **필요한 총 검토 수** (`numTotalRequired`)가 있으며, 이는 역할에 관계없이 필요한 최소 고유 승인 수의 하한선 역할을 합니다. 그 위에 특정 역할을 가진 사용자로부터 몇 개의 승인이 있어야 하는지 지정하는 **역할 요구 사항**을 추가할 수 있습니다(예: "DBA에서 1개, Security에서 1개").

요청은 **두** 조건이 모두 충족될 때만 승인됩니다:

- 고유 승인 총 수가 `numTotalRequired`를 충족
- 각 역할 요구 사항이 개별적으로 충족

사용자가 여러 역할에 속한 경우, 해당 사용자의 단일 승인은 일치하는 모든 역할 요구 사항에 계산됩니다. 그러나 총 수에는 하나의 승인으로만 계산됩니다.

**예시:** 연결에 DBA에서 1개, Security에서 1개를 포함하여 총 3개의 승인이 필요합니다. DBA와 Security 역할을 모두 가진 사용자가 승인하면 두 역할 요구 사항을 모두 충족하지만 필요한 총 3개 승인 중 1개로만 계산됩니다. 모든 사용자로부터 2개의 추가 승인이 여전히 필요합니다.

엔터프라이즈 라이선스가 만료되면 기존 역할 기반 검토 요구 사항은 계속 적용되지만 더 이상 수정할 수 없습니다. 간단한 총 검토 수 구성으로 되돌리려면 해당 요구 사항을 제거할 수만 있습니다.

### 역할

Kviklet은 Default, Admins, Developers의 3가지 역할과 함께 제공됩니다.

- 기본 역할은 모든 연결 및 Requests에 대한 Read 액세스를 제공합니다. 이 역할은 모든 사용자에게 할당되며 제거할 수 없습니다. 그러나 이 역할의 권한은 원하는 대로 변경할 수 있습니다.
- Admins는 연결을 생성 및 편집하고, 새 사용자를 추가하고 권한을 설정할 수 있는 권한을 가집니다.
- Developers는 Requests를 생성하고 승인 및 댓글을 달 수 있으며 물론 실제 명령문을 실행할 수 있습니다.

역할을 사용자 정의하고 예를 들어 특정 연결 또는 DB 연결 그룹에만 액세스 권한을 부여할 수 있습니다.
이는 예를 들어 서로 다른 데이터베이스를 가진 여러 팀이 있고 해당 데이터베이스에 대한 액세스를 더 세분화하여 제어하려는 경우에 유용합니다.

#### 새 역할 생성

새 역할을 생성하는 방법은 다음과 같습니다. Settings -> Roles -> Add Role로 이동하세요.

![Add Role](https://assets.kitploit.com/production/public/readmes/7140/a91b79287c0b3130b83bdde1c059f49b89c5d43a1c0deae33b211ea427956f8e.png)
![Add Role](https://assets.kitploit.com/production/public/readmes/7140/c535ac152759bb21bea04a0968ce43fa7bf946c7699feca23c71f9eaba41ceaf.png)

기본 설정은 대부분의 역할에 그다지 관련이 없으며 User Read 및 RoleView Access를 부여하고 그대로 두면 됩니다.
더 흥미로운 것은 Connections에 대한 개별 권한을 추가하는 것입니다. 여기에서 먼저 특정 연결을 선택하는 선택기를 추가합니다. 이는 특정 id일 수도 있고 `*` 와일드카드를 사용하여 여러 연결을 일치시킬 수도 있습니다. 예를 들어 모든 dev 데이터베이스에 액세스할 수 있는 역할을 원하는 경우(kviklet으로 해당 데이터베이스에 대한 액세스도 관리하는 경우) `dev-*`와 같은 선택기를 사용하고 연결의 id가 올바르게 설정되었는지 확인하세요.

물론 조직 내의 다양한 팀을 위해 사용하는 시스템을 직접 만들 수도 있습니다.

### 역할 동기화 (Enterprise)

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에서 수행됩니다.

  문제가 발생하면 이슈를 생성해 주세요. 우리는 (아직) 세상의 모든 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을 생성하고 웹훅을 활성화해야 합니다. 다음 지침을 따를 수 있습니다: https://api.slack.com/messaging/webhooks

#### Teams

Teams 알림은 Power Automate **Workflow** 웹훅을 사용합니다. Kviklet은 Adaptive Card를 전송하며, 웹훅 템플릿이 이를 채널에 게시합니다.

**권장: 워크플로 템플릿 사용**

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**을 복사합니다.

현재 다음과 같은 알림이 있습니다:

- 승인이 필요한 새 Requests
- 요청에 대한 새 승인

#### Base URL 구성

리버스 프록시 또는 Kubernetes Ingress 뒤에서 Kviklet을 실행할 때 알림 링크가 공용 도메인 대신 내부 IP 주소를 사용할 수 있습니다. Kviklet은 들어오는 요청을 확인하여 올바른 URL을 추적하려고 시도하지만 일부 리버스 프록시는 Forwarded 헤더를 올바르게 설정하지 않습니다. 이 문제를 해결하려면 base 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는 사람이 읽을 수 있는(pretty) 로그를 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 데이터베이스가 어떤 식으로든 침해된다면 이는 막대한 보안 위험입니다. 잠재적으로 모든 프로덕션 데이터스토어의 데이터베이스 자격 증명을 포함하고 있기 때문입니다. 따라서 저장 시 자격 증명 암호화를 활성화할 수 있습니다.

이를 위해서는 두 개의 환경 변수를 설정하기만 하면 됩니다.``` ENCRYPTION_ENABLED=true ENCRYPTION_KEY_CURRENT=some-secret

Kviklet는 시작 시 기존의 모든 자격 증명을 암호화하고, 앞으로 생성하는 연결에 해당 secret을 사용합니다.

### 키 교체

키를 교체하려면 이전 키에 대한 변수를 하나 더 추가하고 현재 키를 변경하면 됩니다:```
ENCRYPTION_KEY_PREVIOUS=some-secret
ENCRYPTION_KEY_CURRENT=another-secret

Kviklet는 시작 시 모든 연결을 다시 암호화하므로, 이전 키를 제거한 상태로 컨테이너를 재시작할 수 있습니다.

API 키

Kviklet는 시스템에 대한 프로그래밍 방식 접근을 위한 API 키를 지원합니다. 이는 엔터프라이즈 전용 기능이며 유효한 라이선스가 필요합니다. Settings -> API Keys 섹션에서 API 키를 생성할 수 있습니다.

API Keys API Keys

다음과 같이 사용하세요:```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가 어떻게 정의되어 있는지 확인하려면 언제든 컨트롤러를 살펴볼 수 있습니다. 궁금한 점이 있으면 언제든 이슈를 열어주세요.

## 실험적 기능

현재 두 가지 실험적 기능이 있습니다. 이들은 주로 커뮤니티 피드백을 바탕으로 만들어졌습니다. 편하게 사용해 보시고 의견이 있으시면 남겨주세요. 향후 이를 더 발전시키고 핵심 승인 흐름과 잘 작동하도록 만들고자 합니다.

### Kubernetes Exec

Kubernetes Exec 기능을 사용하려면 별도의 kubernetes 연결을 생성해야 합니다. Kviklet은 배포된 pod의 사용자를 사용하여 명령을 실행합니다. 따라서 해당 사용자가 접근하려는 pod에서 명령을 실행할 수 있는 필요한 권한을 가지고 있는지 확인하세요.

Kviklet은 또한 명령 실행에 /bin/sh를 사용하므로, pod에 셸이 있거나 최소한 /bin/sh에 심볼릭 링크가 있는지 확인해야 합니다. 이것이 불편하시다면 언제든 이슈를 열어주세요. 설정 가능하게 만들거나 다른 해결책을 찾을 수도 있습니다.

Kubernetes 명령은 출력을 5초 동안만 기다립니다. 명령이 그보다 오래 걸리면 Kviklet은 명령이 타임아웃되기 전까지 최대 한 시간 동안 기다립니다. 이는 임시 방편이며, 더 반응성을 높이고 잠재적으로 터미널 세션을 활성화하기 위해 websocket을 검토하고 있습니다.

### Proxy - Postgres, MariaDB, MySQL (Enterprise)

임시 접근 요청을 생성한 경우, 웹 인터페이스를 사용하는 대신 kviklet이 관리하는 프록시를 통해 쿼리를 실행하고 원하는 DB 클라이언트를 사용할 수 있습니다.
프록시는 엔터프라이즈 기능입니다. 유효한 라이선스가 필요하며, 관리자가 Settings -> General -> Database Proxy에서 추가로 활성화해야 합니다.
이를 위해 컨테이너는 고정 포트(기본적으로 5432 및 3306, `kviklet.proxy.postgres.port` 및 `kviklet.proxy.mysql.port`로 구성 가능)에서 수신 대기하므로 해당 포트를 노출해야 합니다.
그런 다음 사용자는 임시 접근 요청을 생성하고, 승인되면 "Start Proxy"를 클릭할 수 있습니다. 각 요청에는 임시 사용자 이름과 비밀번호가 부여되며, Kviklet은 사용자 이름을 기준으로 각 연결을 해당 요청으로 라우팅합니다. 이를 통해 데이터베이스에 연결할 수 있습니다. Kviklet은 임시 사용자와 비밀번호를 검증하고 모든 요청을 데이터베이스의 실제 사용자에게 프록시합니다. 실행된 모든 구문은 웹 인터페이스를 통해 실행된 것처럼 감사 로그에 기록됩니다.

참고: 프록시는 현재 결과 추적을 지원하지 않습니다. 따라서 실행된 구문은 기록되지만 결과나 구문의 성공 또는 실패 여부는 기록되지 않습니다.

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

#### Proxy - 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 이슈](https://github.com/kviklet/kviklet/issues)를 생성하셔도 됩니다.

기여하고 싶으시다면, 작은 부분은 자유롭게 포크하고 PR을 생성해 주세요. 더 큰 기능을 계획하고 계시다면, GitHub 이슈나 Discord에서 미리 논의해 주시면 감사하겠습니다.

[email protected]로 저에게 연락하실 수도 있습니다.

카테고리