
kviklet v0.9.0
تدفق مراجعة/موافقة شبيه بـ Pull Request لاستعلامات قاعدة البيانات. للوصول السلس والمتوافق للمهندسين إلى الإنتاج.
Kviklet
Kviklet.dev | ملاحظات الإصدار | Discord
وصول آمن إلى بيئات الإنتاج دون التأثير على إنتاجية المطورين.

يطبّق Kviklet (يُنطق Quick-let) مبدأ العيون الأربع على الوصول إلى قواعد بيانات الإنتاج، مع سير عمل مراجعة وموافقة شبيه بطلبات السحب (pull request) للتعليمات SQL الفردية أو جلسات قواعد البيانات المحدودة زمنياً. يمكن للمهندسين مراجعة طلبات بعضهم البعض والموافقة عليها دون تمرير كل استعلام عبر مسؤول قواعد البيانات (DBA) أو فريق العمليات.
Kviklet مستضاف ذاتياً ويعمل كحاوية Docker مع قاعدة بيانات PostgreSQL لحالة التطبيق. تتيح لك واجهته الرسومية إرسال الطلبات ومراجعتها وتنفيذها. يفتح ترخيص المؤسسات الاختياري ميزات مصادقة SAML، ومتطلبات المراجعة القائمة على الأدوار، ومزامنة الأدوار، ومفاتيح API. اطلب ترخيص المؤسسات من kviklet.dev.
قواعد البيانات المدعومة هي Postgres وMySQL وMariaDB وMS SQL Server وMongoDB.
نموذج الوصول
نوصي بربط Kviklet بمزود الهوية الحالي لديك. يدعم Kviklet تسجيل الدخول الموحّد (SSO) عبر OIDC (Google، Keycloak، إلخ) أو SAML (للمؤسسات فقط)، بالإضافة إلى مصادقة LDAP (Active Directory، إلخ).
ثم ينشئ المستخدمون طلبات لـاتصالات تُقابل مستخدم قاعدة بيانات محدد. تكون هذه الطلبات إما:
- استعلام واحد: تعليمة SQL محددة تُقدَّم للمراجعة.
- وصول مؤقت: جلسة محدودة زمنياً يمكنك فيها تنفيذ عدة تعليمات.
حسب الإعدادات، يراجع الطلبات ويوافق عليها مستخدمون آخرون قبل أن يسمح Kviklet بالتنفيذ.
يتصل Kviklet بقاعدة البيانات نيابةً عن المستخدم. لا تُعرض كلمة مرور قاعدة بيانات الاتصال للمستخدم أبداً.
يمكن للمسؤول تكوين الدور الذي يملك صلاحية الوصول إلى أي اتصال وبوابات المراجعة المطلوبة للتنفيذ. تُدار صلاحيات الوصول على مستوى قاعدة البيانات عبر آليات RBAC الخاصة بقاعدة البيانات الأساسية. على سبيل المثال، يمكن إنشاء دور للقراءة فقط لاتصال للقراءة فقط وتخصيص متطلبات مراجعة أقل له من اتصال للكتابة.
يسجّل Kviklet التعليمات المنفذة ويربطها بالمستخدم وطلب الوصول. لتغطية كاملة للوصول اليدوي إلى قاعدة البيانات، قيّد الاتصالات المباشرة ووجّه أي وصول يدوي عبر Kviklet. لا يحتاج المهندسون إلى استلام أو مشاركة بيانات اعتماد قاعدة البيانات الأساسية.
تشمل ميزات المؤسسات الإضافية:
- SAML: دعم مصادقة SAML.
- Proxy (Postgres، MariaDB، MySQL): استخدم عميل قاعدة البيانات المفضل لديك عبر جلسة وصول مؤقت معتمدة بكلمة مرور مؤقتة. تُسجَّل التعليمات المنفذة في سجل تدقيق Kviklet.
- بوابات المراجعة القائمة على الأدوار: اشترط موافقات من أدوار محددة قبل التنفيذ.
- مزامنة الأدوار: زامن أدوار المستخدمين تلقائياً من مجموعات مزود الهوية لديك.
- مفاتيح API: وصول برمجي إلى واجهة Kviklet API.
المزيد من لقطات الشاشة
الطلبات
توجد جميع طلبات البيانات في مكان واحد. مثل طلبات السحب المفتوحة لقواعد بيانات الإنتاج لديك:

الجلسات المباشرة
يفتح طلب وصول مؤقت معتمد جلسة SQL مباشرة في المتصفح:

سجل التدقيق
تُسجَّل كل تعليمة منفذة — سواء نُفذت كاستعلام واحد خاضع للمراجعة، أو في جلسة مباشرة، أو عبر وكيل قاعدة البيانات:

الميزات حسب نوع قاعدة البيانات/الاتصال
معظم الميزات متاحة لجميع قواعد البيانات (SSO، LDAP، RBAC، تدفق المراجعة/الموافقة، سجل التدقيق، إلخ). لكن بعض الميزات مقيّدة، إما لأنها لم تُبنَ بعد أو لأنها لا معنى لها لهذا الغرض المحدد. يوضح الجدول التالي الميزات المتاحة لكل نوع من أنواع قواعد البيانات:
| Database | Statement Review | Temporary Access | Proxy(Beta) | Explain Plan |
|---|---|---|---|---|
| Postgres | ✓ | ✓ | ✓ | ✓ |
| MySQL | ✓ | ✓ | ✓ | ✓ |
| MariaDB | ✓ | ✓ | ✓ | ✓ |
| SQL Server | ✓ | ✓ | ✗ | ✓ |
| MongoDB | ✓ | ✓ | ✗ | ✗ |
| Kubernetes | ✓ | ✗ | ✗ | ✗ |
الإعداد
يُشحن Kviklet كحاوية docker بسيطة.
يمكنك العثور على الإصدارات المتاحة ضمن الإصدارات. نوصي بتحديث الإصدار الذي تستخدمه بانتظام بينما نواصل بناء ميزات جديدة.
أحدث إصدار حالياً هو 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.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 خاصة به (أو على الأقل 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_EMAIL و INITIAL_USER_PASSWORD حتى تتمكن من تسجيل الدخول إلى واجهة الويب. يمكنك تغيير كلمة المرور بعد ذلك عبر واجهة المستخدم.
مثال:```
INITIAL_USER_EMAIL=[email protected]
INITIAL_USER_PASSWORD=someverysecurepassword
نقوم بنشر حاوياتنا إلى حزم GitHub في الوقت الحالي، لذا مع إعداد كل هذا يمكنك تشغيل `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
SSO عبر OIDC / OAuth2
إذا كنت ترغب في إعداد SSO لنسخة Kviklet الخاصة بك (وهو أمر منطقي جدًا، وإلا فسيتعين عليك إدارة كلمات المرور مرة أخرى). تحتاج إلى إعداد متغيرات البيئة الثلاثة هذه:``` KVIKLET_IDENTITYPROVIDER_CLIENTID KVIKLET_IDENTITYPROVIDER_CLIENTSECRET KVIKLET_IDENTITYPROVIDER_TYPE=google
يمكنك الحصول على معرّف عميل google والسر بسهولة باتباع تعليمات google هنا:
https://developers.google.com/identity/gsi/web/guides/get-google-api-clientid
بالنسبة لعناوين URI لإعادة التوجيه الصالحة، يجب عليك تكوين: https://[kviklet_host]/api/login/oauth2/code/google
بالنسبة إلى الأصول المسموح بها (Allowed Origins)، ببساطة عنوان url الخاص بـ kviklet المستضاف لديك.
بعد تعيين متغيرات البيئة هذه، يمكن لأي شخص في مؤسستك تسجيل الدخول باستخدام زر sign in with google. لكن لن تكون لديهم أي أذونات افتراضيًا، وسيتعين عليك تعيين دور لهم بعد تسجيل دخولهم مرة واحدة.
#### Keycloak
إذا كنت تريد إعداد SSO باستخدام Keycloak بدلاً من ذلك، فأنت بحاجة إلى تعيين متغيرات البيئة الأربعة هذه:```
KVIKLET_IDENTITYPROVIDER_CLIENTID
KVIKLET_IDENTITYPROVIDER_CLIENTSECRET
KVIKLET_IDENTITYPROVIDER_TYPE=keycloak
KVIKLET_IDENTITYPROVIDER_ISSUERURI=http://[host]:[port]/realms/[realm]
تحصل على client id و secret عند إنشاء تطبيق في Keycloak. بالنسبة لـ valid redirect URIs، يجب عليك تكوين: https://[kviklet_host]/api/login/oauth2/code/keycloak بالنسبة لـ Allowed Origins، ببساطة رابط kviklet المستضاف لديك.
بعد تعيين متغيرات البيئة هذه، يجب أن تعرض صفحة تسجيل الدخول زر Login with Keycloak الذي يعيد التوجيه إلى نسخة keycloak الخاصة بك. في الإصدار المؤسسي، يمكنك تمكين مزامنة الأدوار لمزامنة الأدوار تلقائيًا من نسخة keycloak الخاصة بك إلى kviklet. راجع قسم Role Sync لمزيد من التفاصيل.
GitHub (Beta)
Beta: مصادقة GitHub جديدة ولا تدعم role sync بعد — كل مستخدم جديد يصل بالدور الافتراضي ويجب تعيين الأدوار له يدويًا.
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 المستضاف الخاص بك
`KVIKLET_IDENTITYPROVIDER_GITHUB_ALLOWEDORGS` **مطلوب** (يرفض Kviklet بدء التشغيل بدونه). لا يمكن لتطبيقات GitHub OAuth تقييد من يكمل تدفق OAuth، لذلك يستدعي Kviklet المسار `/user/orgs` بعد المصادقة ويرفض المستخدمين الذين ليسوا أعضاء في مؤسسة واحدة على الأقل من القائمة المسموح بها (غير حساس لحالة الأحرف، يتم فحص أول 100 مؤسسة).
لكي يرى فحص المؤسسة عضوية المستخدم، يجب على المستخدم النقر على **Grant** (أو **Request**) بجانب كل مؤسسة مسموح بها على شاشة موافقة OAuth. إذا كانت المؤسسة قد فعّلت "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: عنوان URL لخادم LDAP الخاص بك.LDAP_BASE: الـ DN الأساسي لعمليات بحث LDAP.LDAP_PRINCIPAL: الـ DN لمستخدم المسؤول للربط بخادم LDAP.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 only)
يدعم 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 لديك
- `SAML_SSOSERVICELOCATION`: عنوان URL لخدمة SSO الخاص بمزوّد الهوية لديك
- `SAML_VERIFICATIONCERTIFICATE`: شهادة X.509 المستخدمة للتحقق من استجابات SAML (ضمّن سطري 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، يجب عليك أولاً تكوين اتصال قاعدة بيانات. انتقل إلى Settings -> Databases -> Add Connection.


هنا يمكنك تكوين متطلبات المراجعة وحدود التنفيذ لكل اتصال. راجع [Review Gates](#review-gates) للحصول على التفاصيل.
#### AWS IAM AUTH
يدعم Kviklet استخدام IAM Auth لاتصالات قواعد بيانات Postgres وMySQL وMariaDB، ولهذا اختر IAM Auth عند إنشاء اتصال جديد.


سيؤدي هذا إلى إزالة خيار تعيين كلمة مرور واستخدام بيانات اعتماد AWS بدلاً من ذلك للاتصال بقاعدة البيانات.
يستخدم Kviklet `DefaultCredentialsProvider` الخاص بـ AWS للعثور على بيانات الاعتماد وإنشاء الرمز المميز للاتصال. وهذا يعني أن جميع الأماكن المعتادة يجب أن تعمل (متغيرات البيئة أو أدوار المثيل المرتبطة)، والترتيب الدقيق موثق هنا: https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/auth/credentials/DefaultCredentialsProvider.html
بالإضافة إلى ذلك، يمكنك توفير AWS role ARN سيفترضه Kviklet، واستخدام تلك البيانات الاعتمادية لإنشاء رمز قاعدة البيانات المؤقت. هذا مفيد بشكل خاص للاتصال بقواعد بيانات ليست في نفس حساب AWS الخاص بـ Kviklet. لاستخدام هذه الميزة، ما عليك سوى إدخال role ARN في الحقل المخصص عند إنشاء أو تحرير اتصال IAM Auth. ترك الحقل فارغاً سيستخدم موفر البيانات الاعتمادية الافتراضي (بدون افتراض دور).
يتم استنتاج منطقة AWS المستخدمة أثناء إنشاء الرمز المميز من عنوان URL للاتصال، لذا لا يوجد خيار لتعيينها.
لمعرفة كيفية إعداد IAM Auth لقاعدة بياناتك، اتبع وثائق AWS الرسمية: https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.html
النقطتان الرئيسيتان هما:
- إنشاء مستخدم قاعدة بيانات مع خيار IAM auth والأذونات الصحيحة
- إنشاء سياسة IAM تسمح لكيان AWS بإنشاء رموز مميزة لهذا المستخدم
### Review Gates
بشكل افتراضي، يسمح Kviklet بتكوين بسيط لعدد المراجعات. يمكنك تكوين عدد الموافقات التي تحتاجها الطلبات على اتصال معين قبل أن يمكن تنفيذها.
يتم حساب حالة الموافقة على الطلب بناءً على آخر إجراء لكل مراجع. إذا وافق مراجع ثم طلب تغييرات لاحقاً، فإن طلب التغيير فقط هو الذي يُحتسب — وتُزال موافقته السابقة. يؤدي تحرير الطلب دائماً إلى إعادة تعيين جميع الموافقات السابقة، مما يضمن عدم إمكانية تنفيذ أي تغييرات دون مراجعتها أولاً. وبالمثل، إذا فشل التنفيذ (على سبيل المثال بسبب خطأ في صياغة SQL)، تُعاد تعيين الموافقات حتى يمكن تصحيح الطلب وإعادة الموافقة عليه دون الحاجة إلى إنشاء طلب جديد.
يمكنك أيضاً تكوين حد **max executions** لكل اتصال للتحكم في عدد المرات التي يمكن فيها تنفيذ طلب واحد معتمد. القيمة الافتراضية هي 1. تعيينها إلى 0 يسمح بتنفيذ غير محدود. لا تُحتسب التنفيذات الفاشلة ضمن هذا الحد.
#### متطلبات المراجعة القائمة على الأدوار (Enterprise)
مع ترخيص Kviklet Enterprise، يمكنك تكوين اتصالات فردية لطلب موافقات من مستخدمين بأدوار محددة. يتيح لك ذلك، على سبيل المثال، طلب موافقة من الفريق الذي يدير قاعدة بيانات معينة أو حماية الاتصالات الحساسة خلف موافقات DBA أو الإدارة.
**كيف يعمل:**
لكل اتصال عدد **total reviews required** (`numTotalRequired`) يعمل كحد أدنى — الحد الأدنى لعدد الموافقات المتميزة المطلوبة بغض النظر عن الأدوار. بالإضافة إلى ذلك، يمكنك إضافة **متطلبات الأدوار** التي تحدد عدد الموافقات التي يجب أن تأتي من مستخدمين بدور معين (على سبيل المثال، "1 من DBA، 1 من Security").
لا تتم الموافقة على الطلب إلا عند استيفاء **كلا** الشرطين:
- أن يفي العدد الإجمالي للموافقات المتميزة بـ `numTotalRequired`
- أن يتحقق كل متطلب دور على حدة
إذا كان المستخدم ينتمي إلى أدوار متعددة، فإن موافقة واحدة من ذلك المستخدم تُحتسب نحو جميع متطلبات الأدوار المطابقة. ومع ذلك، فإنها لا تزال تُحتسب كموافقة واحدة فقط نحو العدد الإجمالي.
**مثال:** يتطلب اتصال 3 موافقات إجمالية بما في ذلك 1 من DBA و1 من Security. يوافق مستخدم يمتلك كلاً من دور DBA ودور Security — وهذا يفي بمتطلبي الدورين لكنه يُحتسب فقط كواحدة من أصل 3 موافقات إجمالية مطلوبة. لا تزال هناك حاجة إلى موافقتين إضافيتين من أي مستخدمين.
إذا انتهت صلاحية ترخيص Enterprise الخاص بك، تظل متطلبات المراجعة القائمة على الأدوار الحالية مفروضة ولكن لا يمكن تعديلها بعد الآن. يمكنك فقط إزالتها للعودة إلى تكوين إجمالي المراجعات البسيط.
### الأدوار
يأتي Kviklet مع 3 أدوار: Default وAdmins وDevelopers.
- يوفر الدور الافتراضي صلاحية القراءة لجميع الاتصالات والطلبات. يُعيَّن هذا الدور لكل مستخدم ولا يمكن إزالته. ومع ذلك، يمكنك تغيير أذونات هذا الدور كما تشاء.
- يمتلك Admins الإذن لإنشاء وتحرير الاتصالات، بالإضافة إلى إضافة مستخدمين جدد وتعيين أذوناتهم.
- يمكن لـ Developers إنشاء الطلبات وكذلك الموافقة عليها والتعليق عليها، وبالطبع تنفيذ العبارات الفعلية.
يمكنك تخصيص الأدوار، على سبيل المثال منح دور صلاحية الوصول إلى اتصال معين أو مجموعة من اتصالات قواعد البيانات.
هذا مفيد على سبيل المثال إذا كان لديك فرق مختلفة بقواعد بيانات مختلفة وتريد التحكم في الوصول إليها بشكل أكثر تفصيلاً.
#### إنشاء دور جديد
يعمل إنشاء دور جديد على النحو التالي. انتقل إلى Settings -> Roles -> Add Role.


الإعدادات الافتراضية ليست ذات صلة بمعظم الأدوار، ويمكنك ببساطة منح User Read وRoleView Access وترك الأمر عند ذلك.
الأكثر إثارة للاهتمام هو إضافة أذونات فردية للاتصالات. هنا تضيف أولاً محدداً لاختيار اتصالات محددة. يمكن أن يكون هذا معرّفاً محدداً أو يمكنك استخدام أحرف البدل مع `*` لمطابقة اتصالات متعددة. على سبيل المثال، إذا كنت تريد دوراً لديه صلاحية الوصول إلى جميع قواعد بيانات dev (في حال كنت تدير أيضاً الوصول إليها باستخدام kviklet)، فستستخدم محدداً مثل `dev-*` وتتأكد من تعيين معرّفات الاتصالات بشكل صحيح.
يمكنك بالطبع أيضاً ابتكار نظام تستخدمه لفرقك المختلفة داخل مؤسستك.
### مزامنة الأدوار (Enterprise)
مزامنة أدوار المستخدمين تلقائياً من مجموعات مزود الهوية الخاص بك. تتطلب هذه الميزة ترخيص Enterprise.
يتم **التكوين** في 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 الخاص بك لتضمين claim باسم `groups` في ID token:
- **Keycloak**:
لا يتضمن Keycloak المجموعات في الرموز المميزة بشكل افتراضي، لذا ستحتاج إلى إضافة mapper إلى العميل.
1. انتقل إلى **Clients** في القائمة اليسرى
2. اختر عميل Kviklet الخاص بك
3. انتقل إلى تبويب **Client scopes**
4. انقر على النطاق المخصص (على سبيل المثال، `kviklet-dedicated`)
5. انتقل إلى تبويب **Mappers**
6. انقر على **Add mapper** → **By configuration**
7. اختر **Group Membership**
8. قم بتكوين الـ mapper:
| 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" مع "Groups Attribute" المُكوَّن في إعدادات Role Sync الخاصة بـ Kviklet (الافتراضي: `groups`).
- **مزودو OIDC الآخرون**: أضف mapper/claim للمجموعات يتضمن عضويات مجموعات المستخدم في ID token. يتم ذلك عادةً في واجهة إدارة المزود.
إذا واجهت مشكلات، فلا تتردد في إنشاء issue، لم نجرّب كل مزود OIDC موجود (حتى الآن) وقد تكون هناك اختلافات طفيفة في التنفيذ قد تتطلب تحديثات على جانب Kviklet.
#### إعداد LDAP
تستخدم مزامنة أدوار LDAP سمة `memberOf`:
1. تأكد من أن خادم LDAP الخاص بك لديه overlay الخاص بـ `memberOf` مُفعَّلاً
2. عيّن **Groups Attribute** إلى `memberOf` في Kviklet
3. يتم بعد ذلك استخراج أسماء المجموعات من سمة `memberOf` في سمات المستخدمين.
#### إعداد SAML
قم بتكوين SAML IdP الخاص بك لتضمين المجموعات في الـ assertion:
1. أضف attribute statement يعيّن عضويات مجموعات المستخدم
2. عيّن **Groups Attribute** في Kviklet ليطابق اسم سمة SAML الخاصة بك
3. يتم بعد ذلك استخراج أسماء المجموعات من سمة SAML في سمات المستخدمين.
### الإشعارات
يمكنك تكوين Kviklet لإرسال إشعارات إلى قناة في Slack أو Teams. هذا مفيد لإخطار فريقك بالطلبات الجديدة التي تحتاج إلى مراجعة. يمكنك تكوين ذلك في Settings -> General -> Notification Settings.
#### Slack
لتكوين إشعارات Slack، تحتاج إلى إنشاء Slack App وتمكين webhooks لها. يمكنك اتباع التعليمات هنا: https://api.slack.com/messaging/webhooks
#### Teams
تستخدم إشعارات Teams webhook من نوع Power Automate **Workflow**. يرسل Kviklet Adaptive Card، والذي ينشره قالب الـ webhook في قناتك.
**موصى به: استخدام قالب الـ workflow**
1. في Teams، افتح القناة التي تريد الإشعارات فيها، وانقر على **...** بجوار اسم القناة واختر **Workflows** (أو أضف تطبيق **Workflows**).
2. ابحث عن قالب **"Send webhook alerts to a channel"** وأنشئه.
3. سجّل الدخول عند المطالبة، ثم اختر Team وChannel الهدفين وأنشئ الـ workflow.
4. افتح خطوة الـ trigger وانسخ **HTTP POST URL** المُنشأ.
5. الصق عنوان URL في Kviklet ضمن Settings -> General -> Notification Settings وانقر على save.
**بديل: بناء الـ workflow يدوياً**
إذا كنت تفضل بناء الـ flow بنفسك (أو كان القالب غير متاح):
1. القناة **...** -> **Workflows** -> أنشئ flow مع trigger باسم **"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** من خطوة الـ trigger.
حالياً توجد إشعارات لـ:
- الطلبات الجديدة التي تحتاج إلى موافقات
- الموافقات الجديدة على الطلبات
#### تكوين Base URL
عند تشغيل Kviklet خلف reverse proxy أو Kubernetes Ingress، قد تستخدم روابط الإشعارات عنوان IP الداخلي بدلاً من نطاقك العام. يحاول Kviklet تتبع عنوان URL الصحيح من خلال النظر إلى الطلبات الواردة، لكن بعض reverse proxies لا تعيّن Forwarded headers بشكل صحيح. لإصلاح ذلك، عيّن base URL بشكل صريح:```
KVIKLET_BASE_URL=https://kviklet.example.com
يضمن هذا أن جميع روابط الإشعارات تشير إلى عنوان URL العام الصحيح.
القياس عن بُعد
يُرسل Kviklet إحصاءات استخدام مجهولة الهوية لمساعدتنا في فهم الميزات المستخدمة وأماكن حدوث الأخطاء. لإيقاف ذلك، اضبط:``` KVIKLET_TELEMETRY_ENABLED=false
يسجل Kviklet سطرًا واحدًا عند بدء التشغيل يوضح ما إذا كانت القياسات عن بُعد مفعّلة.
**ما الذي يُرسل.** يحمل كل حدث معرّف نسخة عشوائيًا (يُنشأ مرة واحدة ويُخزَّن في قاعدة بيانات Kviklet)، وعنوان URL الأساسي الذي يُوصل إليه Kviklet (انظر أعلاه؛ غالبًا اسم مضيف داخلي)، وإصدار Kviklet. يُعرَّف المستخدمون فقط بمعرّف مبهم مقيّد بالنسخة، بحيث يمكن عدّ المستخدمين الفريدين، لكن لا تُرسل عناوين البريد الإلكتروني أو الأسماء أبدًا. تُعرَّف الأحداث الدقيقة وخصائصها في `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
التشفير
إذا كنت لا تريد تخزين بيانات الاعتماد كنص صريح في قاعدة البيانات، فمن المستحسن تمكين تشفير قاعدة البيانات على قاعدة بيانات 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 في قسم Settings -> 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 في الإصدارات المستقبلية.
في النهاية، الحقيقة تكمن في الكود، لذا يمكنك دائمًا الاطلاع على الـ controller لمعرفة كيفية تعريف واجهة API. إذا كانت لديك أي أسئلة، فلا تتردد في فتح issue.
## الميزات التجريبية
توجد حاليًا ميزتان تجريبيتان. تم بناؤهما في الغالب بناءً على ملاحظات المجتمع. لا تتردد في تجربتهما وترك أي ملاحظات قد تكون لديك. نأمل أن نطوّر هذا أكثر في المستقبل ونجعله يعمل بشكل جيد مع تدفق الموافقة الأساسي.
### Kubernetes Exec
إذا كنت تريد استخدام ميزة Kubernetes Exec، فيجب عليك إنشاء اتصال Kubernetes منفصل. سيستخدم Kviklet مستخدم الـ pod المنشور لتنفيذ الأمر. لذا تأكد من أن المستخدم لديه الأذونات اللازمة لتنفيذ الأوامر على الـ pods التي تريد الوصول إليها.
يستخدم Kviklet أيضًا /bin/sh لتنفيذ الأمر، لذا ستحتاج إلى التأكد من أن الـ pods لديك تحتوي على shell أو على الأقل symlink في /bin/sh. إذا كان هذا يزعجك، فلا تتردد في فتح issue، يمكننا ربما جعل هذا قابلًا للتكوين أو إيجاد حل آخر.
تنتظر أوامر Kubernetes 5 ثوانٍ فقط للحصول على المخرجات، وإذا استغرق الأمر وقتًا أطول من ذلك، سينتظر Kviklet حتى ساعة قبل انتهاء مهلة الأمر. هذا حل مؤقت، ونحن نبحث في استخدام websockets لجعل هذا أكثر استجابة وربما تمكين جلسات terminal.
### Proxy - Postgres, MariaDB, MySQL (Enterprise)
إذا أنشأت طلبات للوصول المؤقت، يمكنك - بدلًا من استخدام واجهة الويب - تشغيل استعلاماتك عبر proxy يديره kviklet واستخدام عميل DB الذي تختاره.
الـ proxy هو ميزة enterprise: يتطلب ترخيصًا صالحًا، ويجب على المسؤول أيضًا تشغيله من الإعدادات -> عام -> Database Proxy.
لهذا يستمع الـ container على منافذ ثابتة (5432 و3306 افتراضيًا، قابلة للتكوين عبر `kviklet.proxy.postgres.port` و`kviklet.proxy.mysql.port`)، لذا تحتاج إلى كشف هذه المنافذ.
يمكن للمستخدمين بعد ذلك إنشاء طلب وصول مؤقت، والنقر على "Start Proxy" بمجرد الموافقة عليه. يحصل كل طلب على اسم مستخدم وكلمة مرور مؤقتين؛ يوجّه Kviklet كل اتصال إلى طلبه بناءً على اسم المستخدم. وباستخدام هذه البيانات يمكنهم الاتصال بقاعدة البيانات. يتحقق Kviklet من المستخدم المؤقت وكلمة المرور ويوجّه جميع الطلبات إلى المستخدم الأساسي على قاعدة البيانات. تُسجَّل أي عبارات تُنفَّذ في سجل التدقيق كما لو تم تشغيلها عبر واجهة الويب.
ملاحظة: لا يدعم الـ proxy حاليًا تتبع النتائج. لذا تُسجَّل العبارات المنفَّذة ولكن ليس النتائج أو ما إذا كانت العبارة قد نجحت أو فشلت.


#### Proxy - TLS
يُنهي Kviklet اتصال TLS بقاعدة البيانات. وهذا يعني أنه افتراضيًا لا تكون أي حركة مرور من وإلى الـ proxy نفسه مشفَّرة.
إذا كنت تريد أن يعيد kviklet تشفير حركة المرور، يمكنك إعطاء Kviklet شهادة TLS ومفتاحًا للـ proxy عن طريق تعيين متغيرات البيئة التالية:```
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 وإنشاء PRs للأمور الصغيرة. إذا كنت تخطط لميزات أكبر، سأقدّر بعض النقاش المسبق في GitHub issue أو على Discord.
يمكنك أيضًا التواصل معي على [email protected].