
kviklet v0.8.0
데이터베이스 쿼리에 대한 Pull Request 방식의 검토/승인 흐름. 규정을 준수하면서도 원활한 엔지니어의 프로덕션 접근을 위해.
Kviklet
Kviklet.dev | 릴리즈 노트 | 디스코드
개발자 생산성을 저하시키지 않으면서 프로덕션 환경에 안전하게 액세스할 수 있습니다.

Kviklet(퀵-렛)은 네 눈 원칙(Four-Eyes Principle) 과 높은 수준의 구성 가능성을 수용하여 개별 SQL 문이나 데이터베이스 세션에 대해 풀 리퀘스트 스타일의 검토 및 승인 흐름을 제공합니다. 이를 통해 엔지니어링 팀은 누가 어떤 데이터에, 언제 접근할 수 있는지 자체적으로 규제할 수 있으며, 조직은 현대적이고 권한을 부여하며 진정한 "DevOps" 워크플로를 수용하면서도 보안과 규정 준수를 유지할 수 있습니다.
Kviklet은 자체 호스팅 Docker 컨테이너로, 싱글 페이지 웹 앱을 제공합니다. 로그인하여 SQL 요청을 생성하거나 다른 사람의 요청을 승인하세요. 선택적 엔터프라이즈 라이선스를 사용하면 SAML 인증, 역할 기반 검토 요구 사항, 역할 동기화, API 키와 같은 고급 기능을 잠금 해제할 수 있습니다. 엔터프라이즈 라이선스는 kviklet.dev에서 요청할 수 있습니다.
현재 Postgres, MySQL, MS SQL Server 및 MongoDB를 지원합니다.
기능
Kviklet은 엔지니어링 팀이 간단하면서도 안전한 방식으로 프로덕션 데이터베이스 액세스를 관리하는 데 필요한 다양한 기능을 제공합니다.
- SSO (OIDC, Google, Keycloak 등): 사용자 이름이나 비밀번호 없이 Kviklet에 로그인할 수 있습니다. 더 이상 DB 액세스를 위한 공유 자격 증명이 필요하지 않습니다.
- LDAP 지원: LDAP 자격 증명으로 Kviklet에 로그인할 수 있습니다.
- SAML 지원: SAML 자격 증명으로 Kviklet에 로그인할 수 있습니다. (엔터프라이즈 전용)
- 검토/승인 흐름: 다른 개발자의 데이터 요청에 댓글과 제안을 남길 수 있습니다.
- 임시 액세스 (1시간): 승인된 후 1시간 동안 DB에서 모든 문을 실행할 수 있습니다.
- 단일 쿼리: 단일 문을 실행합니다. 검토자가 실행 전에 쿼리를 검토할 수 있습니다.
- 감사 로그: 실행된 모든 문장을 작성자, 실행 이유 등과 함께 기록하는 단일 평면입니다.
- RBAC: 팀이 액세스할 수 있는 데이터베이스/테이블을 DB 엔진이 허용하는 세분성까지 구성할 수 있습니다.
- Postgres 프록시: 프록시 서버를 시작하여 원하는 DB 클라이언트를 사용할 수 있지만 모든 것은 Kviklet 감사 로그에 저장됩니다.
- Kubernetes Exec: Kubernetes 클러스터의 포드에서 문을 실행할 수 있습니다. (현재는 단일 명령 실행만 지원하며 라이브 세션은 아직 지원하지 않습니다)
- 역할 기반 검토 게이트: 실행 전에 특정 역할의 승인이 필요합니다. (엔터프라이즈 전용)
- 역할 동기화: ID 제공자 그룹에서 사용자 역할을 자동으로 동기화합니다. (엔터프라이즈 전용)
- API 키: Kviklet API에 프로그래매틱 방식으로 액세스할 수 있습니다. (엔터프라이즈 전용)
데이터베이스/연결 유형별 기능
대부분의 기능은 모든 데이터베이스에서 사용할 수 있습니다(SSO, LDAP, RBAC, 검토/승인 흐름, 감사 로그 등). 그러나 일부 기능은 아직 구축되지 않았거나 특정 용도에 적합하지 않아 제한될 수 있습니다. 다음 표는 각 데이터베이스 유형에서 사용할 수 있는 기능을 보여줍니다.
| Database | 문 검토 | 임시 액세스 | 프록시(베타) | 실행 계획 |
|---|---|---|---|---|
| Postgres | ✓ | ✓ | ✓ | ✓ |
| MySQL | ✓ | ✓ | ✗ | ✓ |
| MariaDB | ✓ | ✓ | ✗ | ✓ |
| SQL Server | ✓ | ✓ | ✗ | ✓ |
| MongoDB | ✓ | ✓ | ✗ | ✗ |
| Kubernetes | ✓ | ✗ | ✗ | ✗ |
설정
Kviklet은 간단한 Docker 컨테이너로 제공됩니다.
사용 가능한 버전은 릴리즈에서 확인할 수 있습니다. 새로운 기능이 계속 추가되므로 사용 중인 버전을 정기적으로 업데이트하는 것이 좋습니다.
현재 최신 버전은 ghcr.io/kviklet/kviklet:0.7.0이며, :main을 사용할 수도 있지만 때때로 버그가 있는 코드가 실수로 병합될 수 있습니다. 물론 그러한 상황을 피하려고 노력하고 있습니다.
빠른 시작
작동 방식을 시험해보고 싶다면:
-
다음은 최소한의 docker-compose.yaml입니다:
컴포즈 내용을 보려면 클릭하세요
``` 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.yml을docker-compose up -d로 실행하세요. Kviklet이 포트 80에서 실행됩니다.localhost로 접속하여 사용해보세요. 관리자 로그인은 [email protected]이며 비밀번호는admin입니다. -
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 데이터베이스(또는 최소한 스키마)가 필요합니다. 공식 이미지는 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_EMAIL 및 INITIAL_USER_PASSWORD를 설정하면 웹 인터페이스에 로그인할 수 있습니다. 이후 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
Kviklet 인스턴스에 SSO를 설정하려면 (그렇지 않으면 비밀번호를 다시 관리해야 하므로 매우 합리적입니다). 다음 3개의 환경 변수를 설정해야 합니다:``` KVIKLET_IDENTITYPROVIDER_CLIENTID KVIKLET_IDENTITYPROVIDER_CLIENTSECRET KVIKLET_IDENTITYPROVIDER_TYPE=google
Google 클라이언트 ID와 시크릿은 다음 Google 안내를 따라 쉽게 얻을 수 있습니다:
https://developers.google.com/identity/gsi/web/guides/get-google-api-clientid
유효한 리디렉션 URI의 경우 다음을 구성해야 합니다: https://[kviklet_host]/api/login/oauth2/code/google
허용된 출처(Allowed Origins)의 경우, 호스팅된 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 허용된 출처(Allowed Origins)에는 호스팅된 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
GitHub OAuth 앱을 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 앱은 OAuth 흐름을 완료할 수 있는 사용자를 제한할 수 없으므로, Kviklet은 인증 후 `/user/orgs`를 호출하여 허용 목록에 있는 org 중 하나의 멤버가 아닌 사용자를 거부합니다 (대소문자 구분 없이, 처음 100개 org 확인).
조직 확인을 통해 사용자의 멤버십을 확인하려면, 사용자는 OAuth 동의 화면에서 허용 목록에 있는 각 org 옆에 있는 **Grant** (또는 **Request**)를 클릭해야 합니다. org에서 "Restrict third-party OAuth applications"이 활성화된 경우, org 소유자가 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: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 (Enterprise 전용)
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 error가 발생하는 경우, Kviklet의 허용된 출처에 IDP 호스트를 추가할 수 있습니다:``` CORS_ALLOWEDORIGINS=https://[idp_host]
## 설정
### 연결
Kviklet을 시작한 후 먼저 데이터베이스 연결을 구성해야 합니다. 설정 -> 데이터베이스 -> 연결 추가로 이동합니다.


여기에서 각 연결에 대한 검토 요구 사항 및 실행 제한을 구성할 수 있습니다. 자세한 내용은 [검토 게이트](#review-gates)를 참조하세요.
#### AWS IAM AUTH
Kviklet은 Postgres 및 MySQL 데이터베이스 연결에 대해 IAM 인증 사용을 지원합니다. 새 연결을 만들 때 IAM 인증을 선택하세요.


이렇게 하면 비밀번호 설정 옵션이 사라지고 대신 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 인증 연결을 만들거나 편집할 때 지정된 필드에 역할 ARN을 입력하기만 하면 됩니다. 필드를 비워 두면 기본 자격 증명 공급자가 사용됩니다(역할 맡기 없음).
토큰 생성 중 사용할 AWS 리전은 연결 URL에서 자동으로 유추되므로 설정 옵션이 없습니다.
데이터베이스에 대해 IAM 인증을 설정하는 방법은 공식 AWS 문서를 참조하세요: https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.html
주요 두 가지 사항은 다음과 같습니다:
- IAM 인증 옵션과 올바른 권한이 있는 DB 사용자 생성
- AWS 엔터티가 이 사용자에 대해 토큰을 생성할 수 있도록 하는 IAM 정책 생성
### 검토 게이트
기본적으로 Kviklet은 간단한 검토 횟수 구성을 허용합니다. 특정 연결에서 승인 요청이 실행되기 전에 필요한 승인 수를 구성할 수 있습니다.
요청의 승인 상태는 각 검토자의 최신 작업을 기준으로 계산됩니다. 검토자가 승인한 후 변경을 요청하면 요청 변경만 계산되며, 이전 승인은 제거됩니다. 요청을 편집하면 항상 모든 이전 승인이 재설정되어 변경 사항이 검토 없이 실행될 수 없도록 합니다. 마찬가지로 실행이 실패하면(예: SQL 구문 오류로 인해) 승인이 재설정되어 새 요청을 만들 필요 없이 요청을 수정하고 재승인할 수 있습니다.
또한 연결별로 **최대 실행 횟수** 제한을 구성하여 승인된 단일 요청을 실행할 수 있는 횟수를 제어할 수 있습니다. 기본값은 1입니다. 이 값을 0으로 설정하면 무제한 실행이 가능합니다. 실패한 실행은 이 제한에 포함되지 않습니다.
#### 역할 기반 검토 요구 사항 (Enterprise)
Kviklet Enterprise 라이선스를 사용하면 개별 연결에 대해 특정 역할을 가진 사용자의 승인이 필요하도록 구성할 수 있습니다. 이를 통해 예를 들어 특정 데이터베이스를 유지 관리하는 팀의 승인을 요구하거나 민감한 연결을 DBA 또는 관리자 승인 뒤에 둘 수 있습니다.
**작동 방식:**
각 연결에는 **필요한 총 검토 수**(`numTotalRequired`)가 있으며, 이는 최소 요구 사항 역할을 합니다. 이 위에 역할 요구 사항을 추가하여 특정 역할을 가진 사용자로부터 필요한 승인 수를 지정할 수 있습니다(예: "DBA에서 1명, 보안에서 1명").
요청은 **다음 두 조건이 모두** 충족될 때만 승인됩니다:
- 고유한 승인 총 수가 `numTotalRequired`를 충족합니다.
- 각 역할 요구 사항이 개별적으로 충족됩니다.
사용자가 여러 역할에 속하는 경우 해당 사용자의 단일 승인은 일치하는 모든 역할 요구 사항에 적용됩니다. 그러나 총 승인 수에는 여전히 1회로만 계산됩니다.
**예시:** 연결에 3개의 총 승인이 필요하며, 그중 DBA 1명과 보안 1명이 포함되어야 합니다. DBA와 보안 역할을 모두 가진 사용자가 승인하면 두 역할 요구 사항이 모두 충족되지만 필요한 총 3개 승인 중 1개로만 계산됩니다. 다른 사용자의 승인 2개가 여전히 필요합니다.
엔터프라이즈 라이선스가 만료되면 기존 역할 기반 검토 요구 사항은 계속 적용되지만 더 이상 수정할 수 없습니다. 간단한 총 검토 구성으로 되돌리려면 제거만 가능합니다.
### 역할
Kviklet은 기본, 관리자 및 개발자라는 3개의 역할과 함께 제공됩니다.
- 기본 역할은 모든 연결 및 요청에 대한 읽기 액세스 권한을 제공합니다. 이 역할은 모든 사용자에게 할당되며 제거할 수 없습니다. 그러나 이 역할의 권한은 자유롭게 변경할 수 있습니다.
- 관리자는 연결을 만들고 편집할 수 있는 권한과 새 사용자를 추가하고 권한을 설정할 수 있는 권한이 있습니다.
- 개발자는 요청을 만들고 승인 및 댓글을 달 수 있으며 실제 명령문을 실행할 수 있습니다.
역할을 사용자 정의하고 예를 들어 특정 연결 또는 DB 연결 그룹에만 액세스 권한을 부여할 수 있습니다.
이는 예를 들어 다른 팀이 다른 데이터베이스를 가지고 있고 액세스를 더 세밀하게 제어하려는 경우 유용합니다.
#### 새 역할 만들기
새 역할을 만드는 방법은 다음과 같습니다. 설정 -> 역할 -> 역할 추가로 이동합니다.


대부분의 역할에 대해 기본 설정은 그다지 중요하지 않으며 사용자에게 읽기 및 역할 보기 액세스 권한을 부여하고 그대로 두면 됩니다.
더 흥미로운 점은 연결에 대한 개별 권한을 추가하는 것입니다. 여기서 먼저 선택기를 추가하여 특정 연결을 선택합니다. 이는 특정 ID이거나 와일드카드 `*`를 사용하여 여러 연결과 일치시킬 수 있습니다. 예를 들어 모든 개발 데이터베이스에 액세스할 수 있는 역할을 원하는 경우(kviklet으로 해당 데이터베이스에 대한 액세스를 관리하는 경우) `dev-*`와 같은 선택기를 사용하고 연결 ID가 올바르게 설정되어 있는지 확인하세요.
물론 조직 내에서 다른 팀에 사용하는 시스템을 직접 만들 수도 있습니다.
### 역할 동기화 (Enterprise)
ID 공급자 그룹에서 사용자 역할을 자동으로 동기화합니다. 이 기능은 엔터프라이즈 라이선스가 필요합니다.
**구성**은 설정 > 역할 동기화에서 수행됩니다:
- **역할 동기화 사용**: 동기화 켜기/끄기
- **동기화 모드**:
- **전체 동기화** - 사용자 역할이 IdP 그룹 매핑과 정확히 일치합니다(기본 역할 추가).
- **추가적** - IdP 그룹이 역할을 추가하지만 기존 역할은 제거하지 않습니다.
- **첫 로그인만** - 역할은 첫 로그인 시에만 동기화되며 이후 수동 변경 사항은 유지됩니다.
- **그룹 속성**: 그룹 구성원을 포함하는 IdP 속성(기본값: `groups`)
- **역할 매핑**: IdP 그룹 이름(예: `engineering`)을 Kviklet 역할에 매핑합니다.
#### OIDC 설정
ID 토큰에 `groups` 클레임을 포함하도록 OIDC 공급자를 구성합니다:
- **Keycloak**:
Keycloak은 기본적으로 토큰에 그룹을 포함하지 않으므로 클라이언트에 매퍼를 추가해야 합니다.
1. 왼쪽 메뉴에서 **클라이언트**로 이동합니다.
2. Kviklet 클라이언트를 선택합니다.
3. **클라이언트 범위** 탭으로 이동합니다.
4. 전용 범위(예: `kviklet-dedicated`)를 클릭합니다.
5. **매퍼** 탭으로 이동합니다.
6. **매퍼 추가** → **구성별**을 클릭합니다.
7. **그룹 구성원**을 선택합니다.
8. 매퍼를 구성합니다:
| 설정 | 값 |
|---------|-------|
| 이름 | `groups` |
| 토큰 클레임 이름 | `groups` |
| 전체 그룹 경로 | **끄기** |
| ID 토큰에 추가 | **켜기** |
| 액세스 토큰에 추가 | **켜기** |
| 사용자 정보에 추가 | **켜기** |
9. **저장**을 클릭합니다.
> **중요:** "토큰 클레임 이름"은 Kviklet의 역할 동기화 설정에서 구성된 "그룹 속성"(기본값: `groups`)과 일치해야 합니다.
- **기타 OIDC 공급자**: ID 토큰에 사용자의 그룹 구성원을 포함하는 그룹 매퍼/클레임을 추가합니다. 이는 일반적으로 공급자의 관리 UI에서 수행됩니다.
문제가 발생하면 이슈를 생성해 주세요. 아직 모든 OIDC 공급자를 테스트해 보지는 않았으며, Kviklet 측에서 업데이트가 필요한 구현상의 약간의 차이가 있을 수 있습니다.
#### LDAP 설정
LDAP 역할 동기화는 `memberOf` 속성을 사용합니다:
1. LDAP 서버에 `memberOf` 오버레이가 활성화되어 있는지 확인합니다.
2. Kviklet에서 **그룹 속성**을 `memberOf`로 설정합니다.
3. 그러면 사용자 속성의 `memberOf` 속성에서 그룹 이름이 추출됩니다.
#### SAML 설정
SAML IdP가 어설션에 그룹을 포함하도록 구성합니다:
1. 사용자 그룹 구성원을 매핑하는 속성 문을 추가합니다.
2. Kviklet에서 **그룹 속성**을 SAML 속성 이름과 일치하도록 설정합니다.
3. 그러면 사용자 속성의 SAML 속성에서 그룹 이름이 추출됩니다.
### 알림
Kviklet이 Slack 또는 Teams 채널에 알림을 보내도록 구성할 수 있습니다. 이는 검토가 필요한 새 요청에 대해 팀에 알리는 데 유용합니다. 설정 -> 일반 -> 알림 설정에서 구성할 수 있습니다.
#### Slack
Slack 알림을 구성하려면 Slack 앱을 만들고 웹훅을 활성화해야 합니다. 여기 지침을 따르세요: https://api.slack.com/messaging/webhooks
#### Teams
Teams 알림은 Power Automate **워크플로** 웹훅을 사용합니다. Kviklet은 적응형 카드를 보내고, 웹훅 템플릿이 이를 채널에 게시합니다.
**권장: 워크플로 템플릿 사용**
1. Teams에서 알림을 받을 채널을 열고 채널 이름 옆의 **...**을 클릭한 다음 **워크플로**를 선택합니다(또는 **워크플로** 앱을 추가).
2. **"채널에 웹훅 알림 보내기"** 템플릿을 검색하여 만듭니다.
3. 메시지가 나타나면 로그인한 다음 대상 팀과 채널을 선택하고 워크플로를 만듭니다.
4. 트리거 단계를 열고 생성된 **HTTP POST URL**을 복사합니다.
5. URL을 Kviklet의 설정 -> 일반 -> 알림 설정에 붙여넣고 저장을 클릭합니다.
**대안: 워크플로 수동 구축**
템플릿을 사용할 수 없거나 직접 흐름을 구축하려는 경우:
1. 채널 **...** -> **워크플로** -> 트리거 **"Teams 웹훅 요청이 수신되면"**으로 흐름을 만듭니다.
2. 작업 **Microsoft Teams -> "채팅 또는 채널에 카드 게시"**를 추가합니다.
3. 작업의 **적응형 카드** 필드를 표현식 `string(triggerBody())`로 설정하여 Kviklet이 보낸 카드를 게시하도록 합니다.
4. 대상 팀과 채널을 선택하고 **저장**을 클릭한 다음 트리거 단계에서 **HTTP POST URL**을 복사합니다.
현재 다음과 같은 알림이 있습니다:
- 승인이 필요한 새 요청
- 요청에 대한 새 승인
#### 기본 URL 구성
Kviklet을 리버스 프록시 또는 Kubernetes 인그레스 뒤에서 실행할 때 알림 링크가 공개 도메인 대신 내부 IP 주소를 사용할 수 있습니다. Kviklet은 들어오는 요청을 확인하여 올바른 URL을 추적하려고 하지만 일부 리버스 프록시는 전달된 헤더를 올바르게 설정하지 않습니다. 이를 수정하려면 기본 URL을 명시적으로 설정하세요:```
KVIKLET_BASE_URL=https://kviklet.example.com
이렇게 하면 모든 알림 링크가 올바른 공개 URL을 가리킵니다.
로깅
기본적으로 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은 시작 시 모든 기존 자격 증명을 암호화하며, 이후 생성하는 연결에 대해 해당 비밀을 사용합니다.
키 교체
키를 교체하려면 이전 키에 대한 다른 변수를 추가하고 현재 키를 변경하면 됩니다:``` ENCRYPTION_KEY_PREVIOUS=some-secret ENCRYPTION_KEY_CURRENT=another-secret
Kviklet는 시작 시 모든 연결을 다시 암호화하므로, 이전 키를 제거한 상태로 컨테이너를 다시 시작할 수 있습니다.
## API 키
Kviklet은 시스템에 대한 프로그래밍 방식 액세스를 위해 API 키를 지원합니다. 이는 엔터프라이즈 전용 기능이며 유효한 라이선스가 필요합니다. 설정 -> API 키 섹션에서 API 키를 생성할 수 있습니다.


다음과 같이 사용합니다:
```sql
SELECT * FROM users WHERE id = ?;
``````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 기능을 사용하려면 별도의 쿠버네티스 연결을 생성해야 합니다. Kviklet은 배포된 파드의 사용자를 사용하여 명령을 실행합니다. 따라서 해당 사용자가 액세스하려는 파드에서 명령을 실행할 수 있는 권한이 있는지 확인하세요.
Kviklet은 또한 명령 실행에 /bin/sh를 사용하므로, 파드에 셸이 있거나 최소한 /bin/sh에 심볼릭 링크가 있는지 확인해야 합니다. 이것이 불편하시면 이슈를 열어 주세요. 설정 가능하도록 만들거나 다른 해결책을 찾을 수 있습니다.
Kubernetes 명령은 출력을 위해 5초만 기다립니다. 명령이 더 오래 걸릴 경우 Kviklet은 최대 1시간까지 기다린 후 명령을 타임아웃 처리합니다. 이는 임시 방편입니다. 웹소켓을 도입하여 응답성을 높이고 터미널 세션을 가능하게 하는 방안을 검토 중입니다.
프록시, Postgres 전용
임시 액세스 요청을 생성하는 경우, 웹 인터페이스 대신 kviklet 관리 프록시를 통해 쿼리를 실행하고 원하는 DB 클라이언트를 사용할 수 있습니다. 이를 위해 컨테이너는 5438-6000 포트를 사용하므로, 해당 포트를 노출해야 합니다. 그러면 사용자는 임시 액세스 요청을 생성하고, 승인된 후 "Start Proxy"를 클릭할 수 있습니다. 각 요청에는 포트, 사용자 및 임시 비밀번호가 할당됩니다. 이를 통해 데이터베이스에 연결할 수 있습니다. Kviklet은 임시 사용자와 비밀번호를 검증하고 모든 요청을 데이터베이스의 기본 사용자에게 프록시합니다. 실행된 모든 문은 웹 인터페이스를 통해 실행된 것처럼 감사 로그에 기록됩니다. 프록시 측의 메시지 파싱이 모든 클라이언트에서 테스트되지 않았으므로, 예를 들어 문장이 기록되지 않는 문제가 발생하면 이슈를 열어 주세요.

Postgres 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 형식으로 저장되어야 합니다.
질문? 기여?
질문이 있거나, 피드백을 제공하고 싶거나, 설정에 도움이 필요하시면 Discord 커뮤니티에 가입해 주세요. 버그 신고나 기능 요청은 GitHub 이슈를 생성할 수도 있습니다.
기여하고 싶다면, 작은 부분에 대해 포크를 만들고 PR을 자유롭게 생성해 주세요. 더 큰 기능을 계획하고 계신다면, GitHub 이슈나 Discord에서 사전 논의를 해주시면 감사하겠습니다.
[email protected]로 연락하실 수도 있습니다.