Skip to content

Commit

Permalink
add optional ldap relation
Browse files Browse the repository at this point in the history
  • Loading branch information
AmberCharitos committed Mar 5, 2024
1 parent 3468c77 commit 80d131f
Show file tree
Hide file tree
Showing 8 changed files with 264 additions and 27 deletions.
11 changes: 0 additions & 11 deletions config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,10 @@ options:
The url of the ldap to synchronize users from.
In format `ldap://<host>:<port>`.
type: string
default: ldap://comsys-openldap-k8s:389
sync-ldap-bind-dn:
description: |
The bind domain name for ldap synchronization.
type: string
default: cn=admin,dc=canonical,dc=dev,dc=com
sync-ldap-bind-password:
description: |
The bind password for ldap synchronization.
Expand All @@ -38,7 +36,6 @@ options:
description: |
Search base for ldap users and groups.
type: string
default: dc=canonical,dc=dev,dc=com
sync-ldap-user-object-class:
description: |
The object class corresponding to users for ldapsearch.
Expand All @@ -53,7 +50,6 @@ options:
description: |
Search base for ldap users.
type: string
default: dc=canonical,dc=dev,dc=com
sync-group-user-map-sync-enabled:
description: |
Set to true to sync groups without users.
Expand All @@ -69,7 +65,6 @@ options:
Search base for ldap groups.
If not specified this takes the value of `sync-ldap-search-base`.
type: string
default: dc=canonical,dc=dev,dc=com
sync-ldap-user-search-scope:
description: |
Search scope for the users.
Expand Down Expand Up @@ -113,12 +108,6 @@ options:
Enable to incrementally sync as opposed to full sync after initial run.
type: boolean
default: true
ranger-usersync-password:
description: |
The password for the Ranger usersync user.
Must be updated to match in Ranger admin.
type: string
default: rangerR0cks!
policy-mgr-url:
type: string
default: http://ranger-k8s:6080
Expand Down
2 changes: 2 additions & 0 deletions metadata.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ requires:
limit: 1
nginx-route:
interface: nginx-route
ldap:
interface: ldap

provides:
policy:
Expand Down
24 changes: 18 additions & 6 deletions src/charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@
ADMIN_ENTRYPOINT,
APP_NAME,
APPLICATION_PORT,
RELATION_VALUES,
USERSYNC_ENTRYPOINT,
)
from relations.ldap import LDAPRelationHandler
from relations.postgres import PostgresRelationHandler
from relations.provider import RangerProvider
from state import State
Expand Down Expand Up @@ -78,6 +80,7 @@ def __init__(self, *args):
)
self.postgres_relation_handler = PostgresRelationHandler(self)
self.provider = RangerProvider(self)
self.ldap = LDAPRelationHandler(self)

# Handle Ingress
self._require_nginx_route()
Expand Down Expand Up @@ -213,17 +216,20 @@ def _configure_ranger_usersync(self, container):
context: Environment variables for pebble plan.
"""
context = {}
ldap = self._state.ldap or {}
for key, value in vars(self.config).items():
if key.startswith("sync"):
updated_key = key.upper().replace("-", "_")
context[updated_key] = value
if not key.startswith("sync"):
continue

if key in RELATION_VALUES:
value = ldap.get(key) or self.config[key]

updated_key = key.upper()
context[updated_key] = value

context.update(
{
"POLICY_MGR_URL": self.config["policy-mgr-url"],
"RANGER_USERSYNC_PASSWORD": self.config[
"ranger-usersync-password"
],
}
)
config = render("ranger-usersync-config.jinja", context)
Expand All @@ -246,12 +252,18 @@ def validate(self):
if self.config["charm-function"].value == "admin":
self.postgres_relation_handler.validate()

if self.config["charm-function"].value == "usersync":
self.ldap.validate()

def update(self, event):
"""Update the Ranger server configuration and re-plan its execution.
Args:
event: The event triggered when the relation changed.
"""
if not self.unit.is_leader():
return

try:
self.validate()
except ValueError as err:
Expand Down
8 changes: 8 additions & 0 deletions src/literals.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,11 @@
APP_NAME = "ranger-k8s"
ADMIN_ENTRYPOINT = "/home/ranger/scripts/ranger-admin-entrypoint.sh"
USERSYNC_ENTRYPOINT = "/home/ranger/scripts/ranger-usersync-entrypoint.sh"
RELATION_VALUES = [
"sync_ldap_bind_dn",
"sync_ldap_bind_password",
"sync_ldap_search_base",
"sync_ldap_user_search_base",
"sync_group_search_base",
"sync_ldap_url",
]
115 changes: 115 additions & 0 deletions src/relations/ldap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# Copyright 2023 Canonical Ltd.
# See LICENSE file for licensing details.

"""Defines ldap relation event handling methods."""

import logging

from ops import framework

from literals import RELATION_VALUES
from utils import log_event_handler

logger = logging.getLogger(__name__)


class LDAPRelationHandler(framework.Object):
"""Client for ldap relations."""

def __init__(self, charm, relation_name="ldap"):
"""Construct.
Args:
charm: The charm to attach the hooks to.
relation_name: The name of the relation defaults to ldap.
"""
super().__init__(charm, "ldap")
self.charm = charm
self.relation_name = relation_name

# Handle database relation.
self.framework.observe(
charm.on[self.relation_name].relation_created,
self._on_relation_created,
)
self.framework.observe(
charm.on[self.relation_name].relation_changed,
self._on_relation_changed,
)
self.framework.observe(
charm.on[self.relation_name].relation_broken,
self._on_relation_broken,
)

@log_event_handler(logger)
def _on_relation_created(self, event):
"""Handle ldap relation created.
Args:
event: The relation created event.
"""
if self.charm.config["charm-function"] != "usersync":
return

if event.relation:
event.relation.data[self.charm.app].update({"user": "admin"})

@log_event_handler(logger)
def _on_relation_changed(self, event):
"""Handle ldap relation changed.
Args:
event: Relation changed event.
"""
if self.charm.config["charm-function"] != "usersync":
return

container = self.charm.model.unit.get_container(self.charm.name)
if not container.can_connect():
event.defer()
return

event_data = event.relation.data[event.app]
base_dn = event_data.get("base_dn")
self.charm._state.ldap = {
"sync_ldap_bind_password": event_data.get("admin_password"),
"sync_ldap_bind_dn": f"cn=admin,{base_dn}",
"sync_ldap_search_base": base_dn,
"sync_ldap_user_search_base": base_dn,
"sync_group_search_base": base_dn,
"sync_ldap_url": event_data.get("ldap_url"),
}

self.charm.update(event)

@log_event_handler(logger)
def _on_relation_broken(self, event):
"""Handle ldap relation broken.
Args:
event: Relation broken event.
"""
if self.charm.config["charm-function"] != "usersync":
return

container = self.charm.model.unit.get_container(self.charm.name)
if not container.can_connect():
event.defer()
return

self.charm._state.ldap = {}
self.charm.update(event)

def validate(self):
"""Check if the required ldap parameters are available.
Raises:
ValueError: if ldap parameters are not available.
"""
config = vars(self.charm.config)
if not self.charm._state.ldap:
for value in RELATION_VALUES:
if not config.get(value):
raise ValueError(
"Add an LDAP relation or update config values."
)
2 changes: 1 addition & 1 deletion templates/ranger-usersync-config.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ unix_group=ranger

# This password should be changed from the default.
# Please note that this password should be as per rangerusersync user in ranger admin.
rangerUsersync_password= {{ RANGER_USERSYNC_PASSWORD}}
rangerUsersync_password= rangerR0cks!

hadoop_conf=/etc/hadoop/conf

Expand Down
1 change: 1 addition & 0 deletions tests/integration/test_usersync.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ async def test_user_sync(self, ops_test: OpsTest):
config=ranger_config,
)

await ops_test.model.integrate(USERSYNC_NAME, LDAP_NAME)
await ops_test.model.set_config({"update-status-hook-interval": "5m"})
await ops_test.model.wait_for_idle(
apps=[USERSYNC_NAME, LDAP_NAME],
Expand Down
Loading

0 comments on commit 80d131f

Please sign in to comment.