Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ldap): alter external LDAP domains #806

Merged
merged 15 commits into from
Feb 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
4884efa
feat(external-domain): add LDAP validation and configuration for alte…
stephdl Feb 17, 2025
e9cff95
feat(domains): add EditExternalDomain component and integrate into Do…
stephdl Feb 17, 2025
2dd0a22
feat(domains): enhance CreateDomainModal with password visibility tog…
stephdl Feb 17, 2025
032e920
feat(domains): remove domain name from EditExternalDomain translation…
stephdl Feb 17, 2025
0a8b90c
feat(domains): add EditExternalDomainModal component and integrate in…
stephdl Feb 17, 2025
d9c1d10
feat(external-domain): refactor LDAP validation to use configuration …
stephdl Feb 18, 2025
6f011a7
feat(domains): simplify data structure in EditExternalDomainModal by …
stephdl Feb 18, 2025
50e3f58
feat(domains): remove unused left-margin style from EditExternalDomai…
stephdl Feb 18, 2025
1d27c43
feat(domains): update EditExternalDomainModal to disable TLS verifica…
stephdl Feb 18, 2025
d62de7b
feat(domains): add tooltip for external providers and update button s…
stephdl Feb 18, 2025
abecc0d
style(domains): format code for better readability in EditExternalDom…
stephdl Feb 18, 2025
aa56fa1
fix(domains): update button text in EditExternalDomainModal for clarity
stephdl Feb 18, 2025
4ad7599
feat(domains): replace tooltip component for external providers with …
stephdl Feb 18, 2025
1d6c15c
Update core/imageroot/var/lib/nethserver/cluster/actions/alter-extern…
stephdl Feb 18, 2025
b417ce0
Update core/ui/public/i18n/en/translation.json
stephdl Feb 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#!/usr/bin/env python3

#
# Copyright (C) 2025 Nethesis S.r.l.
# SPDX-License-Identifier: GPL-3.0-or-later
#

import sys
import json
import agent
import os
import cluster.userdomains

#
# Sample request:
# {
# "domain":"example.com",
# "protocol": "ldap",
# "bind_dn": "cn=ldapservice,dc=example,dc=com",
# "bind_password": "s3cret",
# "tls": true,
# "tls_verify": true
# }
request = json.load(sys.stdin)
domain = request['domain']
protocol = request['protocol']
rdb = agent.redis_connect(privileged=False)

agent.set_weight(os.path.basename(__file__), 0) # Validation step, no task progress at all

if protocol == 'ldap':
conf = rdb.hgetall(f"cluster/user_domain/ldap/{domain}/conf")
# Get the first provider: ["x.x.x.x:636"]
providers = rdb.lrange(f"cluster/user_domain/ldap/{domain}/providers", 0, -1)
host = providers[0].split(':')[0]
port = providers[0].split(':')[1]

validate= {
'bind_dn': request['bind_dn'],
'bind_password': request['bind_password'],
'tls': request['tls'],
'tls_verify': request['tls_verify'],
'domain': domain,
'protocol': protocol,
'host': host,
'port': int(port),
'schema':conf['schema'],
'base_dn': conf['base_dn']
}

errors, logex = cluster.userdomains.validate_ldap(validate)

if logex:
print(agent.SD_ERR + f"{logex.__class__.__name__}: {logex}", file=sys.stderr)

if errors:
agent.set_status('validation-failed')
json.dump(errors, fp=sys.stdout)
sys.exit(3)
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/usr/bin/env python3

#
# Copyright (C) 2025 Nethesis S.r.l.
# SPDX-License-Identifier: GPL-3.0-or-later
#

import sys
import json
import agent
import os

#
# Sample request:
# {
# "domain":"example.com",
# "protocol": "ldap",
# "bind_dn": "cn=ldapservice,dc=example,dc=com",
# "bind_password": "s3cret",
# "tls": true,
# "tls_verify": true
# }
request = json.load(sys.stdin)
domain = request['domain']
protocol = request['protocol']

rdb = agent.redis_connect(privileged=True)

if protocol == 'ldap':
conf = rdb.hgetall(f"cluster/user_domain/ldap/{domain}/conf")
rdb.hset(f"cluster/user_domain/ldap/{domain}/conf", mapping={
'bind_dn': request['bind_dn'],
'bind_password': request['bind_password'],
'tls': 'on' if request['tls'] else 'off',
'tls_verify': 'on' if request['tls_verify'] else 'off',
})

#
# Advertise new account provider setup
#
rdb.publish(os.getenv('AGENT_ID') + '/event/ldap-provider-changed', json.dumps({
'domain': domain,
'key': f"cluster/user_domain/ldap/{domain}/providers",
}))
# Advertise new user domain setup
rdb.publish(os.getenv('AGENT_ID') + '/event/user-domain-changed', json.dumps({
'domain': domain
}))
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "alter-external-domain input",
"description": "Configure an external user domain",
"$id": "http://schema.nethserver.org/cluster/alter-external-domain-input.json",
"examples": [
{
"domain": "example.com",
"protocol": "ldap",
"bind_dn": "cn=ldapservice,dc=example,dc=com",
"bind_password": "s3cret",
"tls": true,
"tls_verify": true
}
],
"type": "object",
"required": [
"domain",
"protocol"
],
"properties": {
"domain": {
"type": "string",
"title": "User domain name",
"minLength": 1
},
"protocol": {
"type": "string",
"title": "Provider protocol",
"description": "Protocol used to communicate with the domain providers.",
"enum": [
"ldap"
]
}
},
"$defs": {
"additional-properties-of-ldap": {
"type": "object",
"title": "LDAP domain properties",
"description": "Additional required properties of LDAP-based domains",
"properties": {
"bind_dn": {
"type": "string",
"minLength": 1
},
"bind_password": {
"type": "string",
"minLength": 1
},
"tls": {
"type": "boolean"
},
"tls_verify": {
"type": "boolean"
}
},
"required": [
"bind_dn",
"bind_password",
"tls",
"tls_verify"
]
}
}
}
7 changes: 5 additions & 2 deletions core/ui/public/i18n/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -1171,7 +1171,9 @@
"users_admin_page_description": "User administration self service portal",
"host_format": "Must be a valid domain name or IP address",
"provider_already_installed": "Provider already installed",
"no_node_eligible_for_provider_installation": "No node is eligible for provider installation"
"no_node_eligible_for_provider_installation": "No node is eligible for provider installation",
"domain_settings": "Domain settings",
"edit_external_domain": "Edit external domain"
},
"samba": {
"adminuser": "Samba admin username",
Expand Down Expand Up @@ -1276,7 +1278,8 @@
"provider_label_tooltip": "You can assign the provider an easy to remember name",
"unconfigured_provider": "Unconfigured provider",
"unconfigured_providers_title": "There are unconfigured providers",
"unconfigured_providers_description": "You can resume their configuration or delete them"
"unconfigured_providers_description": "You can resume their configuration or delete them",
"external_providers_tooltip_description": "Providers are the services that manage users and groups in a domain. You can have more than one provider in an external domain, but only if 'TLS verify' is disabled"
},
"nodes": {
"title": "Nodes",
Expand Down
3 changes: 3 additions & 0 deletions core/ui/src/components/domains/CreateDomainModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,12 @@
</cv-text-input>
<cv-text-input
:label="$t('domains.bind_password')"
type="password"
v-model="external.bind_password"
:invalid-message="$t(error.external.bind_password)"
:disabled="loading.external.addExternalDomain"
:password-hide-label="$t('password.hide_password')"
:password-show-label="$t('password.show_password')"
ref="bind_password"
>
</cv-text-input>
Expand Down
Loading