Comments (3)
I ended up with the below, which is okay, I guess. Bit annoying having to shell out to a subprocess to set the password, but...
import subprocess
from requests import Session
from qlient.http import HTTPBackend, HTTPClient, Fields
USER=""
PASS=""
SERVER_URL=""
SEED = {
"groups": ["group_1"],
"users": [
{
"id": "service_user_a",
"email": "[email protected]",
"displayName": "Service A",
"groups": ["lldap_password_manager"],
"password_file": "./pass_a",
},
{
"id": "server_user_b",
"email": "[email protected]",
"displayName": "Service B",
"groups": ["lldap_strict_readonly"],
"password_file": "./pass_b",
},
],
}
session = Session()
jwt_token = session.post(url = f"{SERVER_URL}/auth/simple/login", json={
"username": USER,
"password": PASS,
}).json()["token"]
session.headers["Authorization"] = f"Bearer {jwt_token}"
client = HTTPClient(HTTPBackend(f"{SERVER_URL}/api/graphql", session=session))
GROUP_FIELDS = Fields("id", "displayName")
USER_FIELDS = Fields("id", "email", "displayName", groups=GROUP_FIELDS)
existing_groups = client.query.groups(GROUP_FIELDS).data["groups"]
existing_groups_map = {group["displayName"]: group for group in existing_groups}
def create_group(name: str):
group = client.mutation.createGroup(name=name, _fields=GROUP_FIELDS).data["createGroup"]
existing_groups[name] = group
print(f"\tCreated group '{name}'.")
return group
def create_user(user_original):
user = user_original.copy()
del user_original
groups = user.pop("groups", [])
password_file = user.pop("password_file")
with open(password_file, "r") as f:
password = f.read()
# create user
req = client.mutation.createUser(user=user, _fields=USER_FIELDS)
assert req.errors is None, req.raw
# add to groups
for group in groups:
req = client.mutation.addUserToGroup(userId=user["id"], groupId=group["id"])
assert req.errors is None, req.raw
# set password
ret = subprocess.run([
"lldap_set_password",
"--base-url", SERVER_URL,
"--username", user["id"],
"--password", password,
"--token", jwt_token,
], capture_output=True)
ret.check_returncode()
print("\tCreated user '{}'".format(user["id"]))
for must_exist_group in sorted(SEED.get("groups", [])):
if must_exist_group not in existing_groups_map:
print(f"Group '{must_exist_group}' does not exist, creating...")
create_group(must_exist_group)
else:
print(f"Group '{must_exist_group}' exists, skipping")
failed = False
existing_users = client.query.users(USER_FIELDS).data["users"]
existing_users_map = { user["id"]: user for user in existing_users}
for must_exist_user in sorted(SEED.get("users", []), key=lambda x: x["id"]):
must_exist_user_id = must_exist_user["id"]
# Seed file groups is just a list of names, API returns id + displayName
# TODO: This modifies the SEED inplace
must_exist_user["groups"][:] = [
existing_groups_map[group_name] for group_name in must_exist_user["groups"]
]
if must_exist_user_id not in existing_users_map:
print(f"User '{must_exist_user_id}' does not exist, creating...")
create_user(must_exist_user)
else:
print(f"User '{must_exist_user_id}' exists, verifying details match... ", end="")
existing_user = existing_users_map[must_exist_user_id]
if must_exist_user != existing_user:
failed = True
print("failed")
for attribute in must_exist_user.keys():
requested = must_exist_user[attribute]
existing = existing_user[attribute]
if requested != existing:
print(f"\tAttribute '{attribute}' does not match: (requested) '{requested}', (existing) '{existing}'.")
else:
print("ok")
if failed:
print("\nUser details did not match... please fix these manually.")
quit(1)
from lldap.
Hey!
I think the easiest would be to have a small script use the graphql api to create the groups/users on startup (or fail silently if they exist).
Check our docs on scripting: https://github.com/lldap/lldap/blob/main/docs/scripting.md
from lldap.
Looks great! For setting the password, the alternative would be to set it through the LDAP protocol, but that's not as safe: with the subprocess, you actually get a zero-knowledge password setting, so the server doesn't ever learn the password.
from lldap.
Related Issues (20)
- [INTEGRATION] Trying to use LLDAP with etherpad (plus ep_ldapauth_ng plugin) HOT 6
- [BUG] subpath don't work with image lldap/lldap:2024-03-07-debian|alpine HOT 4
- [INTEGRATION] AMP by cubecoders HOT 5
- [BUG] Ldap query to filter user present in two groups is always empty
- [FEATURE REQUEST] Paranoid logging mode
- [BUG] `lldap_password_manager` role does not see other users in the web UI HOT 5
- [INTEGRATION] Stalwart Mailserver HOT 3
- Traefik's PathPrefix supported? HOT 1
- [FEATURE REQUEST] Helm chart implementation details HOT 6
- [FEATURE REQUEST] Include bootstrap.sh in Docker image HOT 2
- [INTEGRATION] Trying to use LLDAP with LAM (Ldap Account Manager)
- [BUG] password reset: mail server error discloses user email
- Nested groups HOT 1
- [BUG] Email through Starttls not working HOT 2
- [FEATURE REQUEST] Return schema in RootDSE for better compatibility with Apache Directory Studio Browser HOT 6
- [FEATURE REQUEST] File-only database HOT 1
- [BUG] LDAP groups not working with Nextcloud HOT 2
- [FEATURE REQUEST] modifyTimestamp
- [FEATURE REQUEST] One checkbox per user to temporarily deny/allow access HOT 1
- [INTEGRATION] uidNumber: missing on nslcd authentication HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from lldap.