mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2025-07-04 16:03:09 +02:00
Added gid to applications to make them posix group ldap compatible
This commit is contained in:
parent
a93e1520d4
commit
56b3f854c5
6
Makefile
6
Makefile
@ -31,7 +31,5 @@ install: build
|
||||
@echo "⚙️ Install complete."
|
||||
|
||||
test:
|
||||
@echo "🧪 Running Unit Tests..."
|
||||
python -m unittest discover -s tests/unit
|
||||
@echo "🔬 Running Integration Tests..."
|
||||
python -m unittest discover -s tests/integration
|
||||
@echo "🧪 Running Tests..."
|
||||
python -m unittest discover -s tests
|
0
__init__.py
Normal file
0
__init__.py
Normal file
@ -6,6 +6,11 @@ import yaml
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
plugin_path = Path(__file__).resolve().parent / ".." / "lookup_plugins"
|
||||
sys.path.insert(0, str(plugin_path))
|
||||
|
||||
from application_gid import LookupModule
|
||||
|
||||
def load_yaml_file(path):
|
||||
"""Load a YAML file if it exists, otherwise return an empty dict."""
|
||||
if not path.exists():
|
||||
@ -37,6 +42,7 @@ def main():
|
||||
# Initialize result structure
|
||||
result = {"defaults_applications": {}}
|
||||
|
||||
gid_lookup = LookupModule()
|
||||
# Process each role for application configs
|
||||
for role_dir in sorted(roles_dir.iterdir()):
|
||||
role_name = role_dir.name
|
||||
@ -67,6 +73,12 @@ def main():
|
||||
|
||||
config_data = load_yaml_file(config_file)
|
||||
if config_data:
|
||||
try:
|
||||
gid_number = gid_lookup.run([application_id], roles_dir=str(roles_dir))[0]
|
||||
except Exception as e:
|
||||
print(f"Warning: failed to determine gid for '{application_id}': {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
config_data["group_id"] = gid_number
|
||||
result["defaults_applications"][application_id] = config_data
|
||||
users_meta_file = role_dir / "meta" / "users.yml"
|
||||
transformed_users = {}
|
||||
|
42
lookup_plugins/application_gid.py
Normal file
42
lookup_plugins/application_gid.py
Normal file
@ -0,0 +1,42 @@
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
import os
|
||||
import yaml
|
||||
|
||||
from ansible.plugins.lookup import LookupBase
|
||||
from ansible.errors import AnsibleError
|
||||
|
||||
class LookupModule(LookupBase):
|
||||
|
||||
def run(self, terms, variables=None, **kwargs):
|
||||
application_id = terms[0]
|
||||
base_gid = kwargs.get('base_gid', 10000)
|
||||
roles_dir = kwargs.get('roles_dir', 'roles')
|
||||
|
||||
if not os.path.isdir(roles_dir):
|
||||
raise AnsibleError(f"Roles directory '{roles_dir}' not found")
|
||||
|
||||
matched_roles = []
|
||||
|
||||
for root, dirs, files in os.walk(roles_dir):
|
||||
if os.path.basename(root) == "vars" and "main.yml" in files:
|
||||
vars_path = os.path.join(root, "main.yml")
|
||||
try:
|
||||
with open(vars_path, 'r') as f:
|
||||
data = yaml.safe_load(f) or {}
|
||||
app_id = data.get('application_id')
|
||||
if app_id:
|
||||
matched_roles.append((app_id, vars_path))
|
||||
except Exception as e:
|
||||
raise AnsibleError(f"Error parsing {vars_path}: {e}")
|
||||
|
||||
# sort alphabetically by application_id
|
||||
sorted_ids = sorted(app_id for app_id, _ in matched_roles)
|
||||
|
||||
try:
|
||||
index = sorted_ids.index(application_id)
|
||||
except ValueError:
|
||||
raise AnsibleError(f"Application ID '{application_id}' not found in any role")
|
||||
|
||||
return [base_gid + index]
|
@ -46,6 +46,10 @@ docker exec -it ldap bash -c "ldapsearch -LLL -o ldif-wrap=no -x -D \"\$LDAP_ADM
|
||||
### Delete Groups and Subgroup
|
||||
To delete the group inclusive all subgroups use:
|
||||
```bash
|
||||
docker exec -it ldap bash -c "ldapsearch -LLL -o ldif-wrap=no -x -D \"\$LDAP_ADMIN_DN\" -w \"\$LDAP_ADMIN_PASSWORD\" -b \"ou=applications,ou=groups,\$LDAP_ROOT\" dn | sed -n 's/^dn: //p' | tac | while read -r dn; do echo \"Deleting \$dn\"; ldapdelete -x -D \"\$LDAP_ADMIN_DN\" -w \"\$LDAP_ADMIN_PASSWORD\" \"\$dn\"; done"
|
||||
|
||||
docker exec -it ldap \
|
||||
ldapdelete -x \
|
||||
-D "$LDAP_ADMIN_DN" \
|
||||
-w "$LDAP_ADMIN_PASSWORD" \
|
||||
-r \
|
||||
"ou=groups,dc=veen,dc=world"
|
||||
```
|
@ -1,34 +1,30 @@
|
||||
{% for application_id, application_config in applications.items() %}
|
||||
|
||||
{# 1. Build up roles dict, defaulting to {} if rbac oder roles fehlt, then ensure administrator immer dabei ist #}
|
||||
{% set base_roles = application_config.rbac.roles | default({}) %}
|
||||
{% set roles = base_roles | combine({
|
||||
'administrator': {
|
||||
'description': 'Has full administrative access: manage themes, plugins, settings, and users'
|
||||
}
|
||||
})
|
||||
{%- for application_id, application_config in applications.items() %}
|
||||
{%- set base_roles = application_config.rbac.roles | default({}) %}
|
||||
{%- set roles = base_roles | combine({
|
||||
'administrator': {
|
||||
'description': 'Has full administrative access: manage themes, plugins, settings, and users'
|
||||
}
|
||||
})
|
||||
%}
|
||||
|
||||
{# 2. Emit role definitions #}
|
||||
{% for role_name, role_conf in roles.items() %}
|
||||
{%- for role_name, role_conf in roles.items() %}
|
||||
dn: cn={{ application_id }}-{{ role_name }},{{ ldap.dn.ou.roles }}
|
||||
objectClass: top
|
||||
objectClass: organizationalRole
|
||||
objectClass: posixGroup
|
||||
gidNumber: {{ application_config['group_id'] }}
|
||||
cn: {{ application_id }}-{{ role_name }}
|
||||
description: {{ role_conf.description }}
|
||||
|
||||
{# 3. Assign only if user has that role #}
|
||||
{% for username, user_config in users.items() %}
|
||||
{% set user_roles = user_config.roles | default([]) %}
|
||||
{% if role_name in user_roles %}
|
||||
{%- for username, user_config in users.items() %}
|
||||
{%- set user_roles = user_config.roles | default([]) %}
|
||||
{%- if role_name in user_roles %}
|
||||
dn: cn={{ application_id }}-{{ role_name }},{{ ldap.dn.ou.roles }}
|
||||
changetype: modify
|
||||
add: roleOccupant
|
||||
roleOccupant: {{ ldap.attributes.user_id }}={{ username }},{{ ldap.dn.ou.users }}
|
||||
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
{% endfor %}
|
||||
{%- endif %}
|
||||
{%- endfor %}
|
||||
{%- endfor %}
|
||||
{%- endfor %}
|
||||
|
0
tests/__init__.py
Normal file
0
tests/__init__.py
Normal file
0
tests/integration/__init__.py
Normal file
0
tests/integration/__init__.py
Normal file
0
tests/unit/__init__.py
Normal file
0
tests/unit/__init__.py
Normal file
62
tests/unit/test_application_gid.py
Normal file
62
tests/unit/test_application_gid.py
Normal file
@ -0,0 +1,62 @@
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
import shutil
|
||||
import unittest
|
||||
import yaml
|
||||
|
||||
dir_path = os.path.abspath(
|
||||
os.path.join(os.path.dirname(__file__), '../../lookup_plugins')
|
||||
)
|
||||
sys.path.insert(0, dir_path)
|
||||
|
||||
from application_gid import LookupModule
|
||||
|
||||
|
||||
class TestApplicationGidLookup(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
# Create a temporary roles directory
|
||||
self.temp_dir = tempfile.mkdtemp()
|
||||
self.roles_dir = os.path.join(self.temp_dir, "roles")
|
||||
os.mkdir(self.roles_dir)
|
||||
|
||||
# Define mock application_ids
|
||||
self.applications = {
|
||||
"nextcloud": "docker-nextcloud",
|
||||
"moodle": "docker-moodle",
|
||||
"wordpress": "docker-wordpress",
|
||||
"taiga": "docker-taiga"
|
||||
}
|
||||
|
||||
# Create fake role dirs and vars/main.yml
|
||||
for app_id, dirname in self.applications.items():
|
||||
role_path = os.path.join(self.roles_dir, dirname, "vars")
|
||||
os.makedirs(role_path)
|
||||
with open(os.path.join(role_path, "main.yml"), "w") as f:
|
||||
yaml.dump({"application_id": app_id}, f)
|
||||
|
||||
self.lookup = LookupModule()
|
||||
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self.temp_dir)
|
||||
|
||||
def test_gid_lookup(self):
|
||||
# The sorted application_ids: [moodle, nextcloud, taiga, wordpress]
|
||||
expected_order = ["moodle", "nextcloud", "taiga", "wordpress"]
|
||||
for i, app_id in enumerate(expected_order):
|
||||
result = self.lookup.run([app_id], roles_dir=self.roles_dir)
|
||||
self.assertEqual(result, [10000 + i])
|
||||
|
||||
def test_custom_base_gid(self):
|
||||
result = self.lookup.run(["taiga"], roles_dir=self.roles_dir, base_gid=20000)
|
||||
self.assertEqual(result, [20002]) # 2nd index in sorted list
|
||||
|
||||
def test_application_id_not_found(self):
|
||||
with self.assertRaises(Exception) as context:
|
||||
self.lookup.run(["unknownapp"], roles_dir=self.roles_dir)
|
||||
self.assertIn("Application ID 'unknownapp' not found", str(context.exception))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
Loading…
x
Reference in New Issue
Block a user