add initial ldap auth
This commit is contained in:
parent
b6bf4992c0
commit
d867e6db46
4 changed files with 106 additions and 0 deletions
12
crates/ldap/Cargo.toml
Normal file
12
crates/ldap/Cargo.toml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
[package]
|
||||||
|
name = "ldap"
|
||||||
|
version = { workspace = true }
|
||||||
|
edition = { workspace = true }
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
actix-web = "4"
|
||||||
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
ldap3 = "0.10"
|
||||||
|
tokio = { version = "1", features = ["full"] }
|
||||||
|
env_logger = "0.10"
|
||||||
|
log = "0.4"
|
63
crates/ldap/src/ldap.rs
Normal file
63
crates/ldap/src/ldap.rs
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
use actix_web::{post, web, App, HttpResponse, HttpServer, Responder};
|
||||||
|
use ldap3::{LdapConn, Scope, SearchEntry};
|
||||||
|
use serde::Deserialize;
|
||||||
|
use std::env;
|
||||||
|
|
||||||
|
// Struct to deserialize login request payload
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct LoginRequest {
|
||||||
|
username: String,
|
||||||
|
password: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
// HTTP POST endpoint for user login
|
||||||
|
#[post("/login")]
|
||||||
|
async fn login(credentials: web::Json<LoginRequest>) -> impl Responder {
|
||||||
|
// Authenticate user and return appropriate response
|
||||||
|
match authenticate_user(&credentials.username, &credentials.password) {
|
||||||
|
Ok(true) => HttpResponse::Ok().body("Login erfolgreich"), // Login successful
|
||||||
|
_ => HttpResponse::Unauthorized().body("Login fehlgeschlagen"), // Login failed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to authenticate user against LDAP server
|
||||||
|
fn authenticate_user(username: &str, password: &str) -> Result<bool, Box<dyn std::error::Error>> {
|
||||||
|
// Get LDAP server and base DN from environment variables or use defaults
|
||||||
|
let ldap_server = env::var("LDAP_SERVER").unwrap_or("ldap://127.0.0.1:389".to_string());
|
||||||
|
let base_dn = env::var("LDAP_BASE_DN").unwrap_or("dc=schule,dc=local".to_string());
|
||||||
|
|
||||||
|
// Establish connection to LDAP server
|
||||||
|
let ldap = LdapConn::new(&ldap_server)?;
|
||||||
|
|
||||||
|
// Search for the user in the LDAP directory
|
||||||
|
let (rs, _res) = ldap.search(
|
||||||
|
&format!("ou=users,{}", base_dn), // Search under "ou=users"
|
||||||
|
Scope::Subtree, // Search all levels
|
||||||
|
&format!("(uid={})", username), // Filter by username
|
||||||
|
vec!["dn"], // Retrieve the distinguished name (DN)
|
||||||
|
)?.success()?;
|
||||||
|
|
||||||
|
// If user is found, attempt to authenticate with their DN and password
|
||||||
|
if let Some(entry) = rs.into_iter().next() {
|
||||||
|
let user_dn = SearchEntry::construct(entry).dn; // Extract user DN
|
||||||
|
|
||||||
|
// Reconnect and bind with user credentials
|
||||||
|
let user_ldap = LdapConn::new(&ldap_server)?;
|
||||||
|
let auth_result = user_ldap.simple_bind(&user_dn, password)?.success();
|
||||||
|
return Ok(auth_result.is_ok()); // Return true if authentication succeeds
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(false) // Return false if user is not found
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main function to start the Actix Web server
|
||||||
|
#[actix_web::main]
|
||||||
|
async fn main() -> std::io::Result<()> {
|
||||||
|
env_logger::init(); // Initialize logger
|
||||||
|
|
||||||
|
// Start HTTP server and bind to localhost:8080
|
||||||
|
HttpServer::new(|| App::new().service(login))
|
||||||
|
.bind(("127.0.0.1", 8080))?
|
||||||
|
.run()
|
||||||
|
.await
|
||||||
|
}
|
29
crates/ldap/src/user.ldif
Normal file
29
crates/ldap/src/user.ldif
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
dn: ou=users,dc=schule,dc=local
|
||||||
|
objectClass: organizationalUnit
|
||||||
|
ou: users
|
||||||
|
|
||||||
|
dn: uid=schueler1,ou=users,dc=schule,dc=local
|
||||||
|
objectClass: inetOrgPerson
|
||||||
|
objectClass: posixAccount
|
||||||
|
objectClass: shadowAccount
|
||||||
|
cn: Schueler1
|
||||||
|
sn: Mustermann
|
||||||
|
uid: schueler1
|
||||||
|
uidNumber: 1001
|
||||||
|
gidNumber: 1001
|
||||||
|
homeDirectory: /home/schueler1
|
||||||
|
loginShell: /bin/bash
|
||||||
|
userPassword: {SSHA}JDJhJDEwJG5EUFZ6U0pOSmpUckhOajRQY0hWNS5DNEp4Q2Mwa1pQSTZWYVhXeVdDMkFUMkFMY1do
|
||||||
|
|
||||||
|
dn: uid=schueler2,ou=users,dc=schule,dc=local
|
||||||
|
objectClass: inetOrgPerson
|
||||||
|
objectClass: posixAccount
|
||||||
|
objectClass: shadowAccount
|
||||||
|
cn: Schueler2
|
||||||
|
sn: Beispiel
|
||||||
|
uid: schueler2
|
||||||
|
uidNumber: 1002
|
||||||
|
gidNumber: 1002
|
||||||
|
homeDirectory: /home/schueler2
|
||||||
|
loginShell: /bin/bash
|
||||||
|
userPassword: {SSHA}JDJhJDEwJEpNVTRzNUk4Z3dQclA1M2o1bU5FZWZKeTRHTlVndXZ0Q0VhblBuNlZXUENyaFZ4Q3NmS2lH
|
|
@ -36,6 +36,8 @@ services:
|
||||||
volumes:
|
volumes:
|
||||||
- openldap_data:/var/lib/ldap
|
- openldap_data:/var/lib/ldap
|
||||||
- openldap_config:/etc/ldap/slapd.d
|
- openldap_config:/etc/ldap/slapd.d
|
||||||
|
- users.ldif:/container/service/slapd/assets/config/bootstrap/ldif/custom/users.ldif
|
||||||
|
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "ldapsearch", "-x", "-H", "ldap://localhost", "-b", "dc=Schule,dc=intern"]
|
test: ["CMD", "ldapsearch", "-x", "-H", "ldap://localhost", "-b", "dc=Schule,dc=intern"]
|
||||||
interval: 30s
|
interval: 30s
|
||||||
|
|
Loading…
Add table
Reference in a new issue