Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f417427635 | ||
|
|
1f26262e13 | ||
|
|
42fccf4713 | ||
|
|
928faa4bcc | ||
|
|
3895a5050d | ||
|
|
f92035b6fd | ||
|
|
37a10c871f | ||
|
|
8397d536d9 | ||
|
|
acd39d20b1 | ||
|
|
0ddeab8caa | ||
|
|
64514ddfc6 | ||
|
|
c47be779a3 | ||
|
|
fea2ed5b79 | ||
|
|
e982908768 | ||
|
|
713dbde4cb | ||
|
|
579dd5e1b6 | ||
|
|
3828ec7624 | ||
|
|
b8c06ebd75 | ||
|
|
130d2552ac |
50
.github/workflows/docker-build-static.yml
vendored
50
.github/workflows/docker-build-static.yml
vendored
@@ -216,6 +216,8 @@ jobs:
|
||||
LLDAP_database_url: postgres://lldapuser:lldappass@localhost/lldap
|
||||
LLDAP_ldap_port: 3890
|
||||
LLDAP_http_port: 17170
|
||||
LLDAP_JWT_SECRET: verysecret
|
||||
LLDAP_LDAP_USER_PASS: password
|
||||
|
||||
|
||||
- name: Run lldap with mariadb DB (MySQL Compatible) and healthcheck
|
||||
@@ -227,6 +229,8 @@ jobs:
|
||||
LLDAP_database_url: mysql://lldapuser:lldappass@localhost/lldap
|
||||
LLDAP_ldap_port: 3891
|
||||
LLDAP_http_port: 17171
|
||||
LLDAP_JWT_SECRET: verysecret
|
||||
LLDAP_LDAP_USER_PASS: password
|
||||
|
||||
|
||||
- name: Run lldap with sqlite DB and healthcheck
|
||||
@@ -238,6 +242,8 @@ jobs:
|
||||
LLDAP_database_url: sqlite://users.db?mode=rwc
|
||||
LLDAP_ldap_port: 3892
|
||||
LLDAP_http_port: 17172
|
||||
LLDAP_JWT_SECRET: verysecret
|
||||
LLDAP_LDAP_USER_PASS: password
|
||||
|
||||
- name: Check DB container logs
|
||||
run: |
|
||||
@@ -324,9 +330,9 @@ jobs:
|
||||
sleep 10s
|
||||
bin/lldap healthcheck
|
||||
env:
|
||||
LLDAP_database_url: sqlite://users.db?mode=rwc
|
||||
LLDAP_ldap_port: 3890
|
||||
LLDAP_http_port: 17170
|
||||
LLDAP_DATABASE_URL: sqlite://users.db?mode=rwc
|
||||
LLDAP_LDAP_PORT: 3890
|
||||
LLDAP_HTTP_PORT: 17170
|
||||
LLDAP_LDAP_USER_PASS: ldappass
|
||||
LLDAP_JWT_SECRET: somejwtsecret
|
||||
|
||||
@@ -350,8 +356,11 @@ jobs:
|
||||
sed -i -r -e "s/X'([[:xdigit:]]+'[^'])/'\\\x\\1/g" -e ":a; s/(INSERT INTO (user_attribute_schema|jwt_storage)\(.*\) VALUES\(.*),1([^']*\);)$/\1,true\3/; s/(INSERT INTO (user_attribute_schema|jwt_storage)\(.*\) VALUES\(.*),0([^']*\);)$/\1,false\3/; ta" -e '1s/^/BEGIN;\n/' -e '$aCOMMIT;' ./dump.sql
|
||||
|
||||
- name: Create schema on postgres
|
||||
env:
|
||||
LLDAP_DATABASE_URL: postgres://lldapuser:lldappass@localhost:5432/lldap
|
||||
LLDAP_JWT_SECRET: somejwtsecret
|
||||
run: |
|
||||
bin/lldap create_schema -d postgres://lldapuser:lldappass@localhost:5432/lldap
|
||||
bin/lldap create_schema
|
||||
|
||||
- name: Copy converted db to postgress and import
|
||||
run: |
|
||||
@@ -368,7 +377,10 @@ jobs:
|
||||
sed -i '1 i\SET FOREIGN_KEY_CHECKS = 0;' ./dump.sql
|
||||
|
||||
- name: Create schema on mariadb
|
||||
run: bin/lldap create_schema -d mysql://lldapuser:lldappass@localhost:3306/lldap
|
||||
env:
|
||||
LLDAP_DATABASE_URL: mysql://lldapuser:lldappass@localhost:3306/lldap
|
||||
LLDAP_JWT_SECRET: somejwtsecret
|
||||
run: bin/lldap create_schema
|
||||
|
||||
- name: Copy converted db to mariadb and import
|
||||
run: |
|
||||
@@ -384,7 +396,10 @@ jobs:
|
||||
sed -i '1 i\SET FOREIGN_KEY_CHECKS = 0;' ./dump.sql
|
||||
|
||||
- name: Create schema on mysql
|
||||
run: bin/lldap create_schema -d mysql://lldapuser:lldappass@localhost:3307/lldap
|
||||
env:
|
||||
LLDAP_DATABASE_URL: mysql://lldapuser:lldappass@localhost:3307/lldap
|
||||
LLDAP_JWT_SECRET: somejwtsecret
|
||||
run: bin/lldap create_schema
|
||||
|
||||
- name: Copy converted db to mysql and import
|
||||
run: |
|
||||
@@ -399,10 +414,9 @@ jobs:
|
||||
sleep 10s
|
||||
bin/lldap healthcheck
|
||||
env:
|
||||
LLDAP_database_url: postgres://lldapuser:lldappass@localhost:5432/lldap
|
||||
LLDAP_ldap_port: 3891
|
||||
LLDAP_http_port: 17171
|
||||
LLDAP_LDAP_USER_PASS: ldappass
|
||||
LLDAP_DATABASE_URL: postgres://lldapuser:lldappass@localhost:5432/lldap
|
||||
LLDAP_LDAP_PORT: 3891
|
||||
LLDAP_HTTP_PORT: 17171
|
||||
LLDAP_JWT_SECRET: somejwtsecret
|
||||
|
||||
- name: Run lldap with mariaDB and healthcheck again
|
||||
@@ -411,9 +425,9 @@ jobs:
|
||||
sleep 10s
|
||||
bin/lldap healthcheck
|
||||
env:
|
||||
LLDAP_database_url: mysql://lldapuser:lldappass@localhost:3306/lldap
|
||||
LLDAP_ldap_port: 3892
|
||||
LLDAP_http_port: 17172
|
||||
LLDAP_DATABASE_URL: mysql://lldapuser:lldappass@localhost:3306/lldap
|
||||
LLDAP_LDAP_PORT: 3892
|
||||
LLDAP_HTTP_PORT: 17172
|
||||
LLDAP_JWT_SECRET: somejwtsecret
|
||||
|
||||
- name: Run lldap with mysql and healthcheck again
|
||||
@@ -422,9 +436,9 @@ jobs:
|
||||
sleep 10s
|
||||
bin/lldap healthcheck
|
||||
env:
|
||||
LLDAP_database_url: mysql://lldapuser:lldappass@localhost:3307/lldap
|
||||
LLDAP_ldap_port: 3893
|
||||
LLDAP_http_port: 17173
|
||||
LLDAP_DATABASE_URL: mysql://lldapuser:lldappass@localhost:3307/lldap
|
||||
LLDAP_LDAP_PORT: 3893
|
||||
LLDAP_HTTP_PORT: 17173
|
||||
LLDAP_JWT_SECRET: somejwtsecret
|
||||
|
||||
- name: Test Dummy User Postgres
|
||||
@@ -738,5 +752,9 @@ jobs:
|
||||
artifacts: aarch64-lldap.tar.gz,
|
||||
amd64-lldap.tar.gz,
|
||||
armhf-lldap.tar.gz
|
||||
draft: true
|
||||
omitBodyDuringUpdate: true
|
||||
omitDraftDuringUpdate: true
|
||||
omitNameDuringUpdate: true
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
|
||||
20
.github/workflows/release-bot.yml
vendored
20
.github/workflows/release-bot.yml
vendored
@@ -1,20 +0,0 @@
|
||||
name: Release Bot
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
comment:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: nflaig/release-comment-on-pr@master
|
||||
with:
|
||||
token: ${{ secrets.RELEASE_BOT_TOKEN }}
|
||||
message: |
|
||||
Thank you everyone for the contribution!
|
||||
This feature is now available in the latest release, [${releaseTag}](${releaseUrl}).
|
||||
You can support LLDAP by starring our repo, contributing some configuration examples and becoming a sponsor.
|
||||
21
CHANGELOG.md
21
CHANGELOG.md
@@ -5,6 +5,27 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [0.6.1] 2024-11-22
|
||||
|
||||
Small release, mainly to fix a migration issue with Sqlite and Postgresql.
|
||||
|
||||
### Added
|
||||
|
||||
- Added a link to a community terraform provider (#1035)
|
||||
|
||||
### Changed
|
||||
|
||||
- The opaque dependency now points to the official crate rather than a fork (#1040)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Migration of the DB schema from 7 to 8 is now automatic for sqlite, and fixed for postgres (#1045)
|
||||
- The startup warning about `key_seed` applying instead of `key_file` now has instructions on how to silence it (#1032)
|
||||
|
||||
### New services
|
||||
|
||||
- OneDev
|
||||
|
||||
## [0.6.0] 2024-11-09
|
||||
|
||||
### Breaking
|
||||
|
||||
190
Cargo.lock
generated
190
Cargo.lock
generated
@@ -113,7 +113,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.86",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -250,7 +250,7 @@ dependencies = [
|
||||
"actix-router",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.86",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -276,7 +276,7 @@ checksum = "b6ac1e58cded18cb28ddc17143c4dea5345b3ad575e14f32f66e4054a56eb271"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.86",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -360,9 +360,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.15"
|
||||
version = "0.6.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526"
|
||||
checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
@@ -375,43 +375,43 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.8"
|
||||
version = "1.0.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1"
|
||||
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
version = "0.2.5"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb"
|
||||
checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
|
||||
dependencies = [
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-query"
|
||||
version = "1.1.1"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a"
|
||||
checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
|
||||
dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "3.0.4"
|
||||
version = "3.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8"
|
||||
checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.89"
|
||||
version = "1.0.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6"
|
||||
checksum = "74f37166d7d48a0284b99dd824694c26119c700b53bf0d1540cdb147dbdaaf13"
|
||||
|
||||
[[package]]
|
||||
name = "arrayref"
|
||||
@@ -505,7 +505,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.86",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -516,7 +516,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.86",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -710,9 +710,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.7.2"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3"
|
||||
checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da"
|
||||
|
||||
[[package]]
|
||||
name = "bytestring"
|
||||
@@ -725,9 +725,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.1.30"
|
||||
version = "1.1.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945"
|
||||
checksum = "e3788d6ac30243803df38a3e9991cf37e41210232916d41a8222ae378f912624"
|
||||
dependencies = [
|
||||
"jobserver",
|
||||
"libc",
|
||||
@@ -786,7 +786,7 @@ dependencies = [
|
||||
"heck 0.5.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.86",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -803,9 +803,9 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.2"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0"
|
||||
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
|
||||
|
||||
[[package]]
|
||||
name = "combine"
|
||||
@@ -1158,7 +1158,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustc_version",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.86",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1178,7 +1178,7 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.86",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
@@ -1245,7 +1245,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.86",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1293,9 +1293,9 @@ checksum = "e079f19b08ca6239f47f8ba8509c11cf3ea30095831f7fed61441475edd8c449"
|
||||
|
||||
[[package]]
|
||||
name = "encoding_rs"
|
||||
version = "0.8.34"
|
||||
version = "0.8.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59"
|
||||
checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
@@ -1422,9 +1422,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "flume"
|
||||
version = "0.11.0"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181"
|
||||
checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
@@ -1540,7 +1540,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.86",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2233,7 +2233,7 @@ checksum = "0122b7114117e64a63ac49f752a5ca4624d534c7b1c7de796ac196381cd2d947"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.86",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2384,7 +2384,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "lber"
|
||||
version = "0.4.3"
|
||||
source = "git+https://github.com/inejge/ldap3/#5238c544aa0785b6999f20702131b9982e132e18"
|
||||
source = "git+https://github.com/inejge/ldap3/#ba38bc573d63b109b92dca80898633512d5c47df"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"nom",
|
||||
@@ -2464,15 +2464,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.159"
|
||||
version = "0.2.161"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5"
|
||||
checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1"
|
||||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
version = "0.2.8"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
|
||||
checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa"
|
||||
|
||||
[[package]]
|
||||
name = "libsqlite3-sys"
|
||||
@@ -2499,7 +2499,7 @@ checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
|
||||
|
||||
[[package]]
|
||||
name = "lldap"
|
||||
version = "0.6.0"
|
||||
version = "0.6.2-alpha"
|
||||
dependencies = [
|
||||
"actix",
|
||||
"actix-files",
|
||||
@@ -2575,7 +2575,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "lldap_app"
|
||||
version = "0.6.0"
|
||||
version = "0.6.2-alpha"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base64 0.13.1",
|
||||
@@ -2949,8 +2949,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
|
||||
|
||||
[[package]]
|
||||
name = "opaque-ke"
|
||||
version = "0.6.1"
|
||||
source = "git+https://github.com/nitnelave/opaque-ke/?branch=zeroize_1.5#2f7f3a694516a7d1be4182945bed3d910cad777a"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aadda6db12e367812aea6e025158bf7f334d21aae853f7c46e0a3bdde70a26f5"
|
||||
dependencies = [
|
||||
"base64 0.13.1",
|
||||
"curve25519-dalek",
|
||||
@@ -3016,7 +3017,7 @@ dependencies = [
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.86",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3074,7 +3075,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"proc-macro2-diagnostics",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.86",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3121,29 +3122,29 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
|
||||
|
||||
[[package]]
|
||||
name = "pin-project"
|
||||
version = "1.1.6"
|
||||
version = "1.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf123a161dde1e524adf36f90bc5d8d3462824a9c43553ad07a8183161189ec"
|
||||
checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95"
|
||||
dependencies = [
|
||||
"pin-project-internal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-internal"
|
||||
version = "1.1.6"
|
||||
version = "1.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4502d8515ca9f32f1fb543d987f63d95a14934883db45bdb48060b6b69257f8"
|
||||
checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.86",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.14"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
|
||||
checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff"
|
||||
|
||||
[[package]]
|
||||
name = "pin-utils"
|
||||
@@ -3287,14 +3288,14 @@ dependencies = [
|
||||
"proc-macro-error-attr2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.86",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.88"
|
||||
version = "1.0.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9"
|
||||
checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@@ -3307,7 +3308,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.86",
|
||||
"version_check",
|
||||
"yansi",
|
||||
]
|
||||
@@ -3409,9 +3410,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.11.0"
|
||||
version = "1.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8"
|
||||
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
@@ -3616,9 +3617,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.37"
|
||||
version = "0.38.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811"
|
||||
checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"errno",
|
||||
@@ -3745,7 +3746,7 @@ dependencies = [
|
||||
"proc-macro-error2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.86",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3782,7 +3783,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"sea-bae",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.86",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
@@ -3852,9 +3853,9 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.210"
|
||||
version = "1.0.214"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a"
|
||||
checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
@@ -3882,20 +3883,20 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.210"
|
||||
version = "1.0.214"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
|
||||
checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.86",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.128"
|
||||
version = "1.0.132"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8"
|
||||
checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03"
|
||||
dependencies = [
|
||||
"indexmap 2.6.0",
|
||||
"itoa",
|
||||
@@ -3946,7 +3947,7 @@ checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.86",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4379,7 +4380,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustversion",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.86",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4401,9 +4402,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.79"
|
||||
version = "2.0.86"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590"
|
||||
checksum = "e89275301d38033efb81a6e60e3497e734dfcc62571f2854bf4b16690398824c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -4481,22 +4482,22 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.64"
|
||||
version = "1.0.66"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84"
|
||||
checksum = "5d171f59dbaa811dbbb1aee1e73db92ec2b122911a48e1390dfe327a821ddede"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.64"
|
||||
version = "1.0.66"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3"
|
||||
checksum = "b08be0f17bd307950653ce45db00cd31200d82b624b36e181337d9c7d92765b5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.86",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4557,9 +4558,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.40.0"
|
||||
version = "1.41.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998"
|
||||
checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"bytes",
|
||||
@@ -4581,7 +4582,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.86",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4683,9 +4684,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tracing-actix-web"
|
||||
version = "0.7.13"
|
||||
version = "0.7.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "15bc0cd5f72e837e310f4d978a90abf202a7f7d8ef3272246bae381d0086d3bf"
|
||||
checksum = "6b87073920bcce23e9f5cb0d2671e9f01d6803bb5229c159b2f5ce6806d73ffc"
|
||||
dependencies = [
|
||||
"actix-web",
|
||||
"mutually_exclusive_features",
|
||||
@@ -4702,7 +4703,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.86",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4781,12 +4782,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "unicase"
|
||||
version = "2.7.0"
|
||||
version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89"
|
||||
dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
@@ -5046,7 +5044,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.86",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
@@ -5080,7 +5078,7 @@ checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.86",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
@@ -5472,14 +5470,14 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.86",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zeroize"
|
||||
version = "1.5.7"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f"
|
||||
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
|
||||
dependencies = [
|
||||
"zeroize_derive",
|
||||
]
|
||||
@@ -5492,7 +5490,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
"syn 2.0.86",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -17,9 +17,5 @@ lto = true
|
||||
[profile.release.package.lldap_app]
|
||||
opt-level = 's'
|
||||
|
||||
[patch.crates-io.opaque-ke]
|
||||
git = 'https://github.com/nitnelave/opaque-ke/'
|
||||
branch = 'zeroize_1.5'
|
||||
|
||||
[patch.crates-io.lber]
|
||||
git = 'https://github.com/inejge/ldap3/'
|
||||
|
||||
34
README.md
34
README.md
@@ -156,6 +156,7 @@ services:
|
||||
- LLDAP_JWT_SECRET=REPLACE_WITH_RANDOM
|
||||
- LLDAP_KEY_SEED=REPLACE_WITH_RANDOM
|
||||
- LLDAP_LDAP_BASE_DN=dc=example,dc=com
|
||||
- LLDAP_LDAP_USER_PASS=adminPas$word
|
||||
# If using LDAPS, set enabled true and configure cert and key path
|
||||
# - LLDAP_LDAPS_OPTIONS__ENABLED=true
|
||||
# - LLDAP_LDAPS_OPTIONS__CERT_FILE=/path/to/certfile.crt
|
||||
@@ -198,32 +199,36 @@ Each package offers a [systemd service](https://wiki.archlinux.org/title/systemd
|
||||
When using the distributed packages, the default login is `admin/password`. You can change that from the web UI after starting the service.
|
||||
|
||||
<details>
|
||||
<summary><b>Arch</b></summary>
|
||||
<summary><b>Arch Linux</b></summary>
|
||||
<br>
|
||||
Arch Linux offers unofficial support through the <a href="https://wiki.archlinux.org/title/Arch_User_Repository">Arch User Repository (AUR)</a>.<br>
|
||||
The package descriptions can be used <a href="https://wiki.archlinux.org/title/Arch_User_Repository#Getting_started">to create and install packages</a>.<br><br>
|
||||
Maintainer: <a href="https://github.com/Zepmann">@Zepmann</a><br>
|
||||
Support: <a href="https://github.com/lldap/lldap/discussions">Discussions</a><br>
|
||||
Package repository: <a href="https://aur.archlinux.org/packages">Arch user repository</a><br>
|
||||
Support: <a href="https://github.com/lldap/lldap/discussions/1044">Discussions</a><br>
|
||||
Package repository: <a href="https://aur.archlinux.org/packages">Arch User Repository</a><br><br>
|
||||
<table>
|
||||
<tr>
|
||||
<td>Available packages:</td>
|
||||
<td>Package name</td>
|
||||
<td>Maintainer</td>
|
||||
<td>Description</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="https://aur.archlinux.org/packages/lldap">lldap</a></td>
|
||||
<td><a href="https://github.com/Zepmann">@Zepmann</a></td>
|
||||
<td>Builds the latest stable version.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td><a href="https://aur.archlinux.org/packages/lldap-bin">lldap-bin</a></td>
|
||||
<td>Uses the latest pre-compiled binaries from the <a href="https://aur.archlinux.org/packages/lldap-bin">releases in this repository</a>.<br>
|
||||
This package is recommended if you want to run lldap on a system with limited resources.</td>
|
||||
<td><a href="https://github.com/Zepmann">@Zepmann</a></td>
|
||||
<td>Uses the latest pre-compiled binaries from the <a href="https://github.com/lldap/lldap/releases">releases in this repository</a>.<br>
|
||||
This package is recommended if you want to run LLDAP on a system with limited resources.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td><a href="https://aur.archlinux.org/packages/lldap-git">lldap-git</a></td>
|
||||
<td></td>
|
||||
<td>Builds the latest main branch code.</td>
|
||||
</tr>
|
||||
</table>
|
||||
LLDPA configuration file: /etc/lldap.toml<br>
|
||||
LLDAP configuration file: /etc/lldap.toml<br>
|
||||
</details>
|
||||
<details>
|
||||
<summary><b>Debian</b></summary>
|
||||
@@ -491,6 +496,9 @@ for some service integrations.
|
||||
The [bootstrap.sh](scripts/bootstrap.sh) script can enforce a list of
|
||||
users/groups/attributes from a given file, reflecting it on the server.
|
||||
|
||||
To manage the user, group and membership lifecycle in an infrastructure-as-code
|
||||
scenario you can use the unofficial [LLDAP terraform provider in the terraform registry](https://registry.terraform.io/providers/tasansga/lldap/latest).
|
||||
|
||||
LLDAP is also very scriptable, through its GraphQL API. See the
|
||||
[Scripting](docs/scripting.md) docs for more info.
|
||||
|
||||
@@ -584,6 +592,7 @@ folder for help with:
|
||||
- [Grafana](example_configs/grafana_ldap_config.toml)
|
||||
- [Grocy](example_configs/grocy.md)
|
||||
- [Harbor](example_configs/harbor.md)
|
||||
- [HashiCorp Vault](example_configs/hashicorp-vault.md)
|
||||
- [Hedgedoc](example_configs/hedgedoc.md)
|
||||
- [Home Assistant](example_configs/home-assistant.md)
|
||||
- [Jellyfin](example_configs/jellyfin.md)
|
||||
@@ -591,6 +600,7 @@ folder for help with:
|
||||
- [Jitsi Meet](example_configs/jitsi_meet.conf)
|
||||
- [Kasm](example_configs/kasm.md)
|
||||
- [KeyCloak](example_configs/keycloak.md)
|
||||
- [Kimai](example_configs/kimai.yaml)
|
||||
- [LibreNMS](example_configs/librenms.md)
|
||||
- [Maddy](example_configs/maddy.md)
|
||||
- [Mastodon](example_configs/mastodon.env.example)
|
||||
@@ -603,6 +613,7 @@ folder for help with:
|
||||
- [Nextcloud](example_configs/nextcloud.md)
|
||||
- [Nexus](example_configs/nexus.md)
|
||||
- [OCIS (OwnCloud Infinite Scale)](example_configs/ocis.md)
|
||||
- [OneDev](example_configs/onedev.md)
|
||||
- [Organizr](example_configs/Organizr.md)
|
||||
- [Portainer](example_configs/portainer.md)
|
||||
- [PowerDNS Admin](example_configs/powerdns_admin.md)
|
||||
@@ -703,6 +714,9 @@ modern identity protocols, check out Kanidm.
|
||||
If you just set up the server, can get to the login page but the password you
|
||||
set isn't working, try the following:
|
||||
|
||||
- If you have changed the admin password in the config after the first run, it
|
||||
won't be used (unless you force its use with `force_ldap_user_pass_reset`).
|
||||
The config password is only for the initial admin creation.
|
||||
- (For docker): Make sure that the `/data` folder is persistent, either to a
|
||||
docker volume or mounted from the host filesystem.
|
||||
- Check if there is a `lldap_config.toml` file (either in `/data` for docker
|
||||
|
||||
@@ -6,7 +6,7 @@ homepage = "https://github.com/lldap/lldap"
|
||||
license = "GPL-3.0-only"
|
||||
name = "lldap_app"
|
||||
repository = "https://github.com/lldap/lldap"
|
||||
version = "0.6.0"
|
||||
version = "0.6.2-alpha"
|
||||
include = ["src/**/*", "queries/**/*", "Cargo.toml", "../schema.graphql"]
|
||||
|
||||
[dependencies]
|
||||
|
||||
@@ -31,14 +31,14 @@ default-features = false
|
||||
version = "1"
|
||||
|
||||
[dependencies.opaque-ke]
|
||||
version = "0.6"
|
||||
version = "0.7"
|
||||
|
||||
[dependencies.chrono]
|
||||
version = "*"
|
||||
features = [ "serde" ]
|
||||
features = ["serde"]
|
||||
|
||||
[dependencies.sea-orm]
|
||||
version= "0.12"
|
||||
version = "0.12"
|
||||
default-features = false
|
||||
features = ["macros"]
|
||||
optional = true
|
||||
|
||||
@@ -14,15 +14,14 @@ Backend:
|
||||
is defined in `schema.graphql`.
|
||||
* The static frontend files are served by this port too.
|
||||
|
||||
Note that secure protocols (LDAPS, HTTPS) are currently not supported. This can
|
||||
be worked around by using a reverse proxy in front of the server (for the HTTP
|
||||
API) that wraps/unwraps the HTTPS messages, or only open the service to
|
||||
localhost or other trusted docker containers (for the LDAP API).
|
||||
Note that HTTPS is currently not supported. This can be worked around by using
|
||||
a reverse proxy in front of the server (for the HTTP API) that wraps/unwraps
|
||||
the HTTPS messages. LDAPS is supported.
|
||||
|
||||
Frontend:
|
||||
* User management UI.
|
||||
* Written in Rust compiled to WASM as an SPA with the Yew library.
|
||||
* Based on components, with a React-like organization.
|
||||
* Based on components, with a React-like framework.
|
||||
|
||||
Data storage:
|
||||
* The data (users, groups, memberships, active JWTs, ...) is stored in SQL.
|
||||
@@ -50,19 +49,19 @@ Data storage:
|
||||
Authentication is done via the OPAQUE protocol, meaning that the passwords are
|
||||
never sent to the server, but instead the client proves that they know the
|
||||
correct password (zero-knowledge proof). This is likely overkill, especially
|
||||
considered that the LDAP interface requires sending the password to the server,
|
||||
but it's one less potential flaw (especially since the LDAP interface can be
|
||||
restricted to an internal docker-only network while the web app is exposed to
|
||||
the Internet).
|
||||
considered that the LDAP interface requires sending the password in cleartext
|
||||
to the server, but it's one less potential flaw (especially since the LDAP
|
||||
interface can be restricted to an internal docker-only network while the web
|
||||
app is exposed to the Internet).
|
||||
|
||||
OPAQUE's "passwords" (user-specific blobs of data that can only be used in a
|
||||
zero-knowledge proof that the password is correct) are hashed using Argon2, the
|
||||
state of the art in terms of password storage. They are hashed using a secret
|
||||
provided in the configuration (which can be given as environment variable or
|
||||
command line argument as well): this should be kept secret and shouldn't change
|
||||
(it would invalidate all passwords). Note that even if it was compromised, the
|
||||
attacker wouldn't be able to decrypt the passwords without running an expensive
|
||||
brute-force search independently for each password.
|
||||
provided in the configuration (which can be given as environment variable,
|
||||
command line argument or a file as well): this should be kept secret and
|
||||
shouldn't change (it would invalidate all passwords). Note that even if it was
|
||||
compromised, the attacker wouldn't be able to decrypt the passwords without
|
||||
running an expensive brute-force search independently for each password.
|
||||
|
||||
### JWTs and refresh tokens
|
||||
|
||||
|
||||
77
example_configs/hashicorp-vault.md
Normal file
77
example_configs/hashicorp-vault.md
Normal file
@@ -0,0 +1,77 @@
|
||||
# Configuration for HashiCorp Vault
|
||||
|
||||
Official LDAP configuration documentation is located [here](https://developer.hashicorp.com/vault/docs/auth/ldap).
|
||||
|
||||
**You'll need to authenticate using your root token or as a user who has permission to modify authentication methods!**
|
||||
|
||||
## User Interface
|
||||
|
||||
1. Navigate to `Access -> Authentication Methods`
|
||||
2. Click `Enable new method +` in the top right and choose `LDAP` under `Infra`
|
||||
3. Name the path whatever you want (preferably keep it default) and click `Enable method` at the bottom
|
||||
|
||||
* URL: `ldap://lldap.example.com:3890` or `ldaps://lldap.example.com:6360`
|
||||
* LDAP Options
|
||||
* If you're using LDAPS and your server does not have your LDAPS certificate installed check `Insecure TLS` otherwise leave this unchecked
|
||||
* User Attribute: `uid`
|
||||
* User Principal (UPN) Domain: **LEAVE THIS BLANK**
|
||||
* Customize User Search
|
||||
* Name of Object to bind (binddn): `cn=admin,ou=people,dc=example,dc=com`
|
||||
* User DN: `ou=people,dc=example,dc=com`
|
||||
* Bindpass: `ChangeMe!`
|
||||
* User Search Filter: `(&(uid={{.Username}})(objectClass=person))`
|
||||
* Customize Group Member Search
|
||||
* Group Filter: `(&(member={{.UserDN}})(objectclass=groupOfUniqueNames))`
|
||||
* Group Attribute: `cn`
|
||||
* Group DN: `ou=groups,dc=example,dc=com`
|
||||
|
||||
4. Click `Save` at the bottom
|
||||
5. Click into the auth menthod and then `Create group +` under the `Groups` tab
|
||||
6. Set the name as the group you want users to have to authenticate to HashiCorp Vault
|
||||
7. Set policy as `default` or whatever policy you want to tie to this group
|
||||
8. Click `Save` at the bottom
|
||||
|
||||
As long as your user is in the group you specified, you should now be able to select `LDAP` from the dropdown on the login page and use your credentials.
|
||||
|
||||
## CLI
|
||||
|
||||
**This requires the vault CLI to be installed on your machine**
|
||||
|
||||
1. Set VAULT_ADDR environment variable
|
||||
|
||||
```bash
|
||||
export VAULT_ADDR=https://vault.example.com
|
||||
```
|
||||
2. Login to vault and provide token when prompted
|
||||
|
||||
```bash
|
||||
vault login
|
||||
````
|
||||
3. Enable the LDAP authentication method
|
||||
|
||||
```bash
|
||||
vault auth enable ldap
|
||||
```
|
||||
4. Configure the LDAP authentication method
|
||||
|
||||
```bash
|
||||
vault write auth/ldap/config \
|
||||
url="ldaps://lldaps.example.com:6360" \
|
||||
binddn="cn=admin,ou=people,dc=example,dc=com" \
|
||||
bindpass="ChangeMe!" \
|
||||
userdn="ou=people,dc=example,dc=com" \
|
||||
userfilter="(&(uid={{.Username}})(objectClass=person))" \
|
||||
groupdn="ou=groups,dc=example,dc=com" \
|
||||
groupfilter="(&(member={{.UserDN}})(objectclass=groupOfUniqueNames))" \
|
||||
userattr="uid" \
|
||||
groupattr="cn" \
|
||||
discoverdn=false
|
||||
```
|
||||
If you are using plain LDAP, change the URL accordingly. If you're using LDAPS and your server does not have your LDAPS certificate installed append `insecure_tls=true` to the bottom of the command.
|
||||
5. Add your group to the LDAP configuration and set the policy
|
||||
|
||||
```bash
|
||||
vault write auth/ldap/groups/vault_users policies=default
|
||||
```
|
||||
|
||||
As long as your user is in the group you specified, you should now be able to select `LDAP` from the dropdown on the login page and use your credentials.
|
||||
36
example_configs/kimai.yaml
Normal file
36
example_configs/kimai.yaml
Normal file
@@ -0,0 +1,36 @@
|
||||
# See https://www.kimai.org/documentation/local-yaml.html
|
||||
# this file should be renamed local.yaml
|
||||
kimai:
|
||||
ldap:
|
||||
activate: true
|
||||
connection:
|
||||
host: lldap
|
||||
port: 3890 # 6360 for LDAPS
|
||||
useSsl: false # true for LDAPS
|
||||
useStartTls: false
|
||||
username: uid=admin,ou=people,dc=example,dc=com
|
||||
password: <PASSWORD_HERE>
|
||||
accountFilterFormat: (&(objectClass=person)(uid=%s))
|
||||
bindRequiresDn: true
|
||||
optReferrals: false
|
||||
|
||||
user:
|
||||
baseDn: ou=people, dc=example, dc=com
|
||||
usernameAttribute: uid
|
||||
filter: (&(objectClass=person)) # to filter by group, add (memberof=cn=kimai,ou=groups,dc=example,dc=com) [group 'kimai' must be created in web UI]
|
||||
attributes:
|
||||
- { ldap_attr: "uid", user_method: setUserIdentifier }
|
||||
- { ldap_attr: "mail", user_method: setEmail }
|
||||
- { ldap_attr: "cn", user_method: setAlias }
|
||||
|
||||
role:
|
||||
baseDn: ou=groups, dc=example, dc=com
|
||||
filter: (&(objectClass=groupOfUniqueNames))
|
||||
usernameAttribute: cn
|
||||
nameAttribute: cn
|
||||
userDnAttribute: member
|
||||
|
||||
# Convert LDAP group name (nameAttribute) to Kimai role. Available roles are listed here: https://www.kimai.org/documentation/permissions.html
|
||||
groups:
|
||||
- { ldap_value: lldap_admin, role: ROLE_SUPER_ADMIN }
|
||||
# add additional group mappings here
|
||||
23
example_configs/onedev.md
Normal file
23
example_configs/onedev.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# Configuration for OneDev
|
||||
In Onedev, go to `Administration > External Authentication Source > Authenticator` and Select `Generic LDAP`
|
||||
|
||||
* LDAP URL: ldap://lldap_ip_or_hostname:3890 or ldaps://lldap_ip_or_hostname:6360
|
||||
* Authentication Required: On
|
||||
* Manager DN: `uid=admin,ou=people,dc=example,dc=com`
|
||||
* Manager Password: Your bind user's password
|
||||
* User Search Base: `ou=people,dc=example,dc=com`
|
||||
* User Search Filter: `(&(uid={0})(objectclass=person))`
|
||||
* User Full Name Attribute: `displayName`
|
||||
* Email Attribute: mail
|
||||
* User SSH Key Attribute: (Leave Blank)
|
||||
* Group Retrieval: "Search Groups Using Filter"
|
||||
* Group Search Base: `ou=groups,dc=example,dc=com`
|
||||
* Group Search Filter: `(&(uniqueMember={0})(objectclass=groupOfUniqueNames))`
|
||||
* Group Name Attribute: cn
|
||||
* Create User As Guest: Off
|
||||
* Default Group: "No Default Group"
|
||||
* Timeout: 300
|
||||
|
||||
Replace every instance of `dc=example,dc=com` with your configured domain.
|
||||
|
||||
After applying the above settings, users should be able to log in with their user name.
|
||||
@@ -1,7 +1,3 @@
|
||||
> [!IMPORTANT]
|
||||
> The integration requires custom ldap properties which are not supported on
|
||||
> stable (as of 2024-09-19), please use nightly/latest tag.
|
||||
|
||||
# Configure lldap
|
||||
|
||||
You MUST use LDAPS. You MUST NOT use plain ldap. Even over a private network
|
||||
@@ -46,11 +42,6 @@ The provided implementation uses custom attributes to mark users and groups
|
||||
that should be included in the system (for instance, you don't want LDAP
|
||||
accounts of other services to have a matching unix user).
|
||||
|
||||
> [!TIP]
|
||||
> You can create custom attributes in the Web UI, but to provide values, you
|
||||
> need to communicate with the API, see [scripting]. Example using lldap-cli:
|
||||
> `./lldap-cli user update set example-user unix-uid 5000`
|
||||
|
||||
For users, you need to add an (integer) `unix-uid` attribute to the schema, and
|
||||
manually set the value for the users you want to enable to login with PAM.
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ keywords = ["cli", "ldap", "graphql", "server", "authentication"]
|
||||
license = "GPL-3.0-only"
|
||||
name = "lldap"
|
||||
repository = "https://github.com/lldap/lldap"
|
||||
version = "0.6.0"
|
||||
version = "0.6.2-alpha"
|
||||
|
||||
[dependencies]
|
||||
actix = "0.13"
|
||||
@@ -86,7 +86,7 @@ path = "../auth"
|
||||
features = ["opaque_server", "opaque_client", "sea_orm"]
|
||||
|
||||
[dependencies.opaque-ke]
|
||||
version = "0.6"
|
||||
version = "0.7"
|
||||
|
||||
[dependencies.rand]
|
||||
features = ["small_rng", "getrandom"]
|
||||
@@ -122,9 +122,15 @@ default-features = false
|
||||
version = "0.24"
|
||||
|
||||
[dependencies.sea-orm]
|
||||
version= "0.12"
|
||||
version = "0.12"
|
||||
default-features = false
|
||||
features = ["macros", "with-chrono", "with-uuid", "sqlx-all", "runtime-actix-rustls"]
|
||||
features = [
|
||||
"macros",
|
||||
"with-chrono",
|
||||
"with-uuid",
|
||||
"sqlx-all",
|
||||
"runtime-actix-rustls",
|
||||
]
|
||||
|
||||
[dependencies.reqwest]
|
||||
version = "0.11"
|
||||
|
||||
@@ -5,8 +5,8 @@ use crate::domain::{
|
||||
use itertools::Itertools;
|
||||
use sea_orm::{
|
||||
sea_query::{
|
||||
self, all, Alias, BinOper, BlobSize::Blob, ColumnDef, Expr, ForeignKey, ForeignKeyAction,
|
||||
Func, Index, Query, SimpleExpr, Table, Value,
|
||||
self, all, BinOper, BlobSize::Blob, ColumnDef, Expr, ForeignKey, ForeignKeyAction, Func,
|
||||
Index, Query, SimpleExpr, Table, Value,
|
||||
},
|
||||
ConnectionTrait, DatabaseTransaction, DbErr, DeriveIden, FromQueryResult, Iden, Order,
|
||||
Statement, TransactionTrait,
|
||||
@@ -970,21 +970,15 @@ async fn migrate_to_v8(transaction: DatabaseTransaction) -> Result<DatabaseTrans
|
||||
let builder = transaction.get_database_backend();
|
||||
// Remove duplicate memberships.
|
||||
#[derive(FromQueryResult)]
|
||||
#[allow(dead_code)]
|
||||
struct MembershipInfo {
|
||||
user_id: UserId,
|
||||
group_id: GroupId,
|
||||
cnt: i64,
|
||||
}
|
||||
let mut delete_queries = MembershipInfo::find_by_statement(
|
||||
for MembershipInfo { user_id, group_id } in MembershipInfo::find_by_statement(
|
||||
builder.build(
|
||||
Query::select()
|
||||
.from(Memberships::Table)
|
||||
.columns([Memberships::UserId, Memberships::GroupId])
|
||||
.expr_as(
|
||||
Expr::count(Expr::col((Memberships::Table, Memberships::UserId))),
|
||||
Alias::new("cnt"),
|
||||
)
|
||||
.group_by_columns([Memberships::UserId, Memberships::GroupId])
|
||||
.cond_having(all![SimpleExpr::Binary(
|
||||
Box::new(Expr::col((Memberships::Table, Memberships::UserId)).count()),
|
||||
@@ -996,38 +990,29 @@ async fn migrate_to_v8(transaction: DatabaseTransaction) -> Result<DatabaseTrans
|
||||
.all(&transaction)
|
||||
.await?
|
||||
.into_iter()
|
||||
.map(
|
||||
|MembershipInfo {
|
||||
user_id,
|
||||
group_id,
|
||||
cnt,
|
||||
}| {
|
||||
builder
|
||||
.build(
|
||||
{
|
||||
transaction
|
||||
.execute(
|
||||
builder.build(
|
||||
Query::delete()
|
||||
.from_table(Memberships::Table)
|
||||
.cond_where(all![
|
||||
Expr::col(Memberships::UserId).eq(user_id),
|
||||
Expr::col(Memberships::UserId).eq(&user_id),
|
||||
Expr::col(Memberships::GroupId).eq(group_id)
|
||||
])
|
||||
.limit(cnt as u64 - 1),
|
||||
)
|
||||
.to_owned()
|
||||
},
|
||||
)
|
||||
.peekable();
|
||||
if delete_queries.peek().is_some() {
|
||||
match transaction.get_database_backend() {
|
||||
sea_orm::DatabaseBackend::Sqlite => {
|
||||
return Err(DbErr::Migration(format!(
|
||||
"The Sqlite driver does not support LIMIT in DELETE. Run these queries manually:\n{}" , delete_queries.map(|s| s.to_string()).join("\n"))));
|
||||
}
|
||||
sea_orm::DatabaseBackend::MySql | sea_orm::DatabaseBackend::Postgres => {
|
||||
for query in delete_queries {
|
||||
transaction.execute(query).await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
]),
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
transaction
|
||||
.execute(
|
||||
builder.build(
|
||||
Query::insert()
|
||||
.into_table(Memberships::Table)
|
||||
.columns([Memberships::UserId, Memberships::GroupId])
|
||||
.values_panic([user_id.into(), group_id.into()]),
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
transaction
|
||||
.execute(
|
||||
|
||||
@@ -314,8 +314,8 @@ pub struct UserRestrictedListerBackendHandler<'a, Handler> {
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<'a, Handler: ReadSchemaBackendHandler + Sync> ReadSchemaBackendHandler
|
||||
for UserRestrictedListerBackendHandler<'a, Handler>
|
||||
impl<Handler: ReadSchemaBackendHandler + Sync> ReadSchemaBackendHandler
|
||||
for UserRestrictedListerBackendHandler<'_, Handler>
|
||||
{
|
||||
async fn get_schema(&self) -> Result<Schema> {
|
||||
let mut schema = self.handler.get_schema().await?;
|
||||
@@ -331,8 +331,8 @@ impl<'a, Handler: ReadSchemaBackendHandler + Sync> ReadSchemaBackendHandler
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<'a, Handler: UserListerBackendHandler + Sync> UserListerBackendHandler
|
||||
for UserRestrictedListerBackendHandler<'a, Handler>
|
||||
impl<Handler: UserListerBackendHandler + Sync> UserListerBackendHandler
|
||||
for UserRestrictedListerBackendHandler<'_, Handler>
|
||||
{
|
||||
async fn list_users(
|
||||
&self,
|
||||
@@ -354,8 +354,8 @@ impl<'a, Handler: UserListerBackendHandler + Sync> UserListerBackendHandler
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<'a, Handler: GroupListerBackendHandler + Sync> GroupListerBackendHandler
|
||||
for UserRestrictedListerBackendHandler<'a, Handler>
|
||||
impl<Handler: GroupListerBackendHandler + Sync> GroupListerBackendHandler
|
||||
for UserRestrictedListerBackendHandler<'_, Handler>
|
||||
{
|
||||
async fn list_groups(&self, filters: Option<GroupRequestFilter>) -> Result<Vec<Group>> {
|
||||
let group_filter = self
|
||||
@@ -379,7 +379,7 @@ pub trait UserAndGroupListerBackendHandler:
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<'a, Handler: GroupListerBackendHandler + UserListerBackendHandler + Sync>
|
||||
UserAndGroupListerBackendHandler for UserRestrictedListerBackendHandler<'a, Handler>
|
||||
impl<Handler: GroupListerBackendHandler + UserListerBackendHandler + Sync>
|
||||
UserAndGroupListerBackendHandler for UserRestrictedListerBackendHandler<'_, Handler>
|
||||
{
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ impl<'de> Deserialize<'de> for TrueFalseAlways {
|
||||
|
||||
struct Visitor;
|
||||
|
||||
impl<'de> serde::de::Visitor<'de> for Visitor {
|
||||
impl serde::de::Visitor<'_> for Visitor {
|
||||
type Value = TrueFalseAlways;
|
||||
|
||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
|
||||
@@ -97,16 +97,16 @@ pub struct Configuration {
|
||||
pub http_host: String,
|
||||
#[builder(default = "17170")]
|
||||
pub http_port: u16,
|
||||
#[builder(default = r#"SecUtf8::from("secretjwtsecret")"#)]
|
||||
pub jwt_secret: SecUtf8,
|
||||
#[builder(default)]
|
||||
pub jwt_secret: Option<SecUtf8>,
|
||||
#[builder(default = r#"String::from("dc=example,dc=com")"#)]
|
||||
pub ldap_base_dn: String,
|
||||
#[builder(default = r#"UserId::new("admin")"#)]
|
||||
pub ldap_user_dn: UserId,
|
||||
#[builder(default)]
|
||||
pub ldap_user_email: String,
|
||||
#[builder(default = r#"SecUtf8::from("password")"#)]
|
||||
pub ldap_user_pass: SecUtf8,
|
||||
#[builder(default)]
|
||||
pub ldap_user_pass: Option<SecUtf8>,
|
||||
#[builder(default)]
|
||||
pub force_ldap_user_pass_reset: TrueFalseAlways,
|
||||
#[builder(default = "false")]
|
||||
@@ -361,7 +361,7 @@ fn get_server_setup<L: Into<PrivateKeyLocationOrFigment>>(
|
||||
file_path
|
||||
);
|
||||
} else if file_path == "server_key" {
|
||||
eprintln!("WARNING: A key_seed was given, we will ignore the server_key and generate one from the seed! Set server_key to an empty string in the config to silence this message.");
|
||||
eprintln!("WARNING: A key_seed was given, we will ignore the key_file and generate one from the seed! Set key_file to an empty string in the config to silence this message.");
|
||||
} else {
|
||||
println!("Generating the private key from the key_seed");
|
||||
}
|
||||
@@ -607,11 +607,24 @@ where
|
||||
.unwrap_or_default(),
|
||||
figment_config,
|
||||
)?);
|
||||
if config.jwt_secret == SecUtf8::from("secretjwtsecret") {
|
||||
println!("WARNING: Default JWT secret used! This is highly unsafe and can allow attackers to log in as admin.");
|
||||
}
|
||||
if config.ldap_user_pass == SecUtf8::from("password") {
|
||||
println!("WARNING: Unsecure default admin password is used.");
|
||||
if config.jwt_secret.is_none() {
|
||||
use rand::{seq::SliceRandom, Rng};
|
||||
struct Symbols;
|
||||
|
||||
impl rand::prelude::Distribution<char> for Symbols {
|
||||
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> char {
|
||||
*b"01234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+,-./:;<=>?_~!@#$%^&*()[]{}:;".choose(rng).unwrap() as char
|
||||
}
|
||||
}
|
||||
bail!("The JWT secret must be initialized to a random string, preferably at least 32 characters long. \
|
||||
Either set the `jwt_secret` config value or the `LLDAP_JWT_SECRET` environment variable. \
|
||||
You can generate the value by running\n\
|
||||
LC_ALL=C tr -dc 'A-Za-z0-9!#%&'\\''()*+,-./:;<=>?@[\\]^_{{|}}~' </dev/urandom | head -c 32; echo ''\n\
|
||||
or you can use this random value: {}",
|
||||
rand::thread_rng()
|
||||
.sample_iter(&Symbols)
|
||||
.take(32)
|
||||
.collect::<String>());
|
||||
}
|
||||
if config.smtp_options.tls_required.is_some() {
|
||||
println!("DEPRECATED: smtp_options.tls_required field is deprecated, it never did anything. You can replace it with smtp_options.smtp_encryption.");
|
||||
@@ -669,7 +682,9 @@ mod tests {
|
||||
fn figment_location_extraction_key_file() {
|
||||
Jail::expect_with(|jail| {
|
||||
jail.create_file("lldap_config.toml", r#"key_file = "test""#)?;
|
||||
jail.clear_env();
|
||||
jail.set_env("LLDAP_KEY_SEED", "a123");
|
||||
jail.set_env("LLDAP_JWT_SECRET", "secret");
|
||||
let ignore_keys = ["key_file", "cert_file"];
|
||||
let figment_config = Figment::from(Serialized::defaults(
|
||||
ConfigurationBuilder::default().private_build().unwrap(),
|
||||
@@ -696,7 +711,9 @@ mod tests {
|
||||
fn check_server_setup_key_extraction_seed_success_with_nonexistant_file() {
|
||||
Jail::expect_with(|jail| {
|
||||
jail.create_file("lldap_config.toml", r#"key_file = "test""#)?;
|
||||
jail.clear_env();
|
||||
jail.set_env("LLDAP_KEY_SEED", "a123");
|
||||
jail.set_env("LLDAP_JWT_SECRET", "secret");
|
||||
init(default_run_opts()).unwrap();
|
||||
Ok(())
|
||||
});
|
||||
@@ -706,7 +723,9 @@ mod tests {
|
||||
fn check_server_setup_key_extraction_seed_failure_with_existing_file() {
|
||||
Jail::expect_with(|jail| {
|
||||
jail.create_file("lldap_config.toml", r#"key_file = "test""#)?;
|
||||
jail.clear_env();
|
||||
jail.set_env("LLDAP_KEY_SEED", "a123");
|
||||
jail.set_env("LLDAP_JWT_SECRET", "secret");
|
||||
write_random_key(jail, "test");
|
||||
init(default_run_opts()).unwrap_err();
|
||||
Ok(())
|
||||
@@ -717,6 +736,8 @@ mod tests {
|
||||
fn check_server_setup_key_extraction_file_success_with_existing_file() {
|
||||
Jail::expect_with(|jail| {
|
||||
jail.create_file("lldap_config.toml", r#"key_file = "test""#)?;
|
||||
jail.clear_env();
|
||||
jail.set_env("LLDAP_JWT_SECRET", "secret");
|
||||
write_random_key(jail, "test");
|
||||
init(default_run_opts()).unwrap();
|
||||
Ok(())
|
||||
@@ -727,6 +748,8 @@ mod tests {
|
||||
fn check_server_setup_key_extraction_file_success_with_nonexistent_file() {
|
||||
Jail::expect_with(|jail| {
|
||||
jail.create_file("lldap_config.toml", r#"key_file = "test""#)?;
|
||||
jail.clear_env();
|
||||
jail.set_env("LLDAP_JWT_SECRET", "secret");
|
||||
init(default_run_opts()).unwrap();
|
||||
Ok(())
|
||||
});
|
||||
@@ -736,6 +759,8 @@ mod tests {
|
||||
fn check_server_setup_key_extraction_file_with_previous_different_file() {
|
||||
Jail::expect_with(|jail| {
|
||||
jail.create_file("lldap_config.toml", r#"key_file = "test""#)?;
|
||||
jail.clear_env();
|
||||
jail.set_env("LLDAP_JWT_SECRET", "secret");
|
||||
write_random_key(jail, "test");
|
||||
let config = init(default_run_opts()).unwrap();
|
||||
let info = config.get_private_key_info();
|
||||
@@ -766,6 +791,8 @@ mod tests {
|
||||
#[test]
|
||||
fn check_server_setup_key_extraction_file_to_seed() {
|
||||
Jail::expect_with(|jail| {
|
||||
jail.clear_env();
|
||||
jail.set_env("LLDAP_JWT_SECRET", "secret");
|
||||
jail.create_file("lldap_config.toml", "")?;
|
||||
write_random_key(jail, "server_key");
|
||||
init(default_run_opts()).unwrap();
|
||||
@@ -782,6 +809,8 @@ mod tests {
|
||||
#[test]
|
||||
fn check_server_setup_key_extraction_file_to_seed_removed_file() {
|
||||
Jail::expect_with(|jail| {
|
||||
jail.clear_env();
|
||||
jail.set_env("LLDAP_JWT_SECRET", "secret");
|
||||
jail.create_file("lldap_config.toml", "")?;
|
||||
write_random_key(jail, "server_key");
|
||||
let config = init(default_run_opts()).unwrap();
|
||||
|
||||
@@ -189,7 +189,7 @@ pub async fn build_tcp_server<Backend>(
|
||||
where
|
||||
Backend: TcpBackendHandler + BackendHandler + LoginHandler + OpaqueHandler + Clone + 'static,
|
||||
{
|
||||
let jwt_secret = config.jwt_secret.clone();
|
||||
let jwt_secret = config.jwt_secret.clone().unwrap();
|
||||
let jwt_blacklist = backend_handler
|
||||
.get_jwt_blacklist()
|
||||
.await
|
||||
|
||||
@@ -33,8 +33,17 @@ use tracing::{debug, error, info, instrument, span, warn, Instrument, Level};
|
||||
mod domain;
|
||||
mod infra;
|
||||
|
||||
const ADMIN_PASSWORD_MISSING_ERROR : &str = "The LDAP admin password must be initialized. \
|
||||
Either set the `ldap_user_pass` config value or the `LLDAP_LDAP_USER_PASS` environment variable. \
|
||||
A minimum of 8 characters is recommended.";
|
||||
|
||||
async fn create_admin_user(handler: &SqlBackendHandler, config: &Configuration) -> Result<()> {
|
||||
let pass_length = config.ldap_user_pass.unsecure().len();
|
||||
let pass_length = config
|
||||
.ldap_user_pass
|
||||
.as_ref()
|
||||
.expect(ADMIN_PASSWORD_MISSING_ERROR)
|
||||
.unsecure()
|
||||
.len();
|
||||
assert!(
|
||||
pass_length >= 8,
|
||||
"Minimum password length is 8 characters, got {} characters",
|
||||
@@ -48,7 +57,11 @@ async fn create_admin_user(handler: &SqlBackendHandler, config: &Configuration)
|
||||
..Default::default()
|
||||
})
|
||||
.and_then(|_| {
|
||||
register_password(handler, config.ldap_user_dn.clone(), &config.ldap_user_pass)
|
||||
register_password(
|
||||
handler,
|
||||
config.ldap_user_dn.clone(),
|
||||
config.ldap_user_pass.as_ref().unwrap(),
|
||||
)
|
||||
})
|
||||
.await
|
||||
.context("Error creating admin user")?;
|
||||
@@ -161,7 +174,10 @@ async fn set_up_server(config: Configuration) -> Result<ServerBuilder> {
|
||||
register_password(
|
||||
&backend_handler,
|
||||
config.ldap_user_dn.clone(),
|
||||
&config.ldap_user_pass,
|
||||
config
|
||||
.ldap_user_pass
|
||||
.as_ref()
|
||||
.expect(ADMIN_PASSWORD_MISSING_ERROR),
|
||||
)
|
||||
.instrument(span)
|
||||
.await
|
||||
|
||||
@@ -3,6 +3,8 @@ use std::env::var;
|
||||
|
||||
pub const DB_KEY: &str = "LLDAP_DATABASE_URL";
|
||||
pub const PRIVATE_KEY_SEED: &str = "LLDAP_KEY_SEED";
|
||||
pub const JWT_SECRET: &str = "LLDAP_JWT_SECRET";
|
||||
pub const LDAP_USER_PASSWORD: &str = "LLDAP_LDAP_USER_PASS";
|
||||
|
||||
pub fn database_url() -> String {
|
||||
let url = var(DB_KEY).ok();
|
||||
|
||||
@@ -43,14 +43,13 @@ const MAX_HEALTHCHECK_ATTEMPS: u8 = 10;
|
||||
|
||||
impl LLDAPFixture {
|
||||
pub fn new() -> Self {
|
||||
let mut cmd = create_lldap_command();
|
||||
cmd.arg("run");
|
||||
cmd.arg("--verbose");
|
||||
let child = cmd.spawn().expect("Unable to start server");
|
||||
let child = create_lldap_command("run")
|
||||
.arg("--verbose")
|
||||
.spawn()
|
||||
.expect("Unable to start server");
|
||||
let mut started = false;
|
||||
for _ in 0..MAX_HEALTHCHECK_ATTEMPS {
|
||||
let status = create_lldap_command()
|
||||
.arg("healthcheck")
|
||||
let status = create_lldap_command("healthcheck")
|
||||
.status()
|
||||
.expect("healthcheck fail");
|
||||
if status.success() {
|
||||
@@ -229,7 +228,7 @@ pub fn new_id(prefix: Option<&str>) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
fn create_lldap_command() -> Command {
|
||||
fn create_lldap_command(subcommand: &str) -> Command {
|
||||
let mut cmd = Command::cargo_bin(env!("CARGO_PKG_NAME")).expect("cargo bin not found");
|
||||
// This gives us the absolute path of the repo base instead of running it in server/
|
||||
let path = canonicalize("..").expect("canonical path");
|
||||
@@ -237,5 +236,10 @@ fn create_lldap_command() -> Command {
|
||||
cmd.current_dir(path);
|
||||
cmd.env(env::DB_KEY, db_url);
|
||||
cmd.env(env::PRIVATE_KEY_SEED, "Random value");
|
||||
cmd.env(env::JWT_SECRET, "Random value");
|
||||
cmd.env(env::LDAP_USER_PASSWORD, "password");
|
||||
cmd.arg(subcommand);
|
||||
cmd.arg("--config-file=/dev/null");
|
||||
cmd.arg("--server-key-file=''");
|
||||
cmd
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user