From 55e82cc958a8607fd30b4adb10235ed9ecee04e0 Mon Sep 17 00:00:00 2001 From: Daan Hoogland Date: Mon, 3 Nov 2025 08:50:15 +0100 Subject: [PATCH 01/12] dependency added --- plugins/user-authenticators/ldap/pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/plugins/user-authenticators/ldap/pom.xml b/plugins/user-authenticators/ldap/pom.xml index c02d3d511e6e..c78447105e8b 100644 --- a/plugins/user-authenticators/ldap/pom.xml +++ b/plugins/user-authenticators/ldap/pom.xml @@ -215,5 +215,11 @@ commons-io ${cs.commons-io.version} + + org.apache.cloudstack + cloud-api + 4.22.0.0-SNAPSHOT + compile + From 4be82d22a86611a30f34f12684ba1a8686c91578 Mon Sep 17 00:00:00 2001 From: Daan Hoogland Date: Mon, 3 Nov 2025 08:51:22 +0100 Subject: [PATCH 02/12] removed deprecated parameter --- .../api/command/LinkDomainToLdapCmd.java | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/LinkDomainToLdapCmd.java b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/LinkDomainToLdapCmd.java index c351924de6de..b6c32fe49b5e 100644 --- a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/LinkDomainToLdapCmd.java +++ b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/LinkDomainToLdapCmd.java @@ -51,14 +51,10 @@ public class LinkDomainToLdapCmd extends BaseCmd { @Parameter(name = ApiConstants.TYPE, type = CommandType.STRING, required = true, description = "type of the ldap name. GROUP or OU") private String type; - @Parameter(name = ApiConstants.LDAP_DOMAIN, type = CommandType.STRING, required = false, description = "name of the group or OU in LDAP") + @Parameter(name = ApiConstants.LDAP_DOMAIN, type = CommandType.STRING, required = true, description = "name of the group or OU in LDAP") private String ldapDomain; - @Deprecated - @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = false, description = "name of the group or OU in LDAP") - private String name; - - @Parameter(name = ApiConstants.ADMIN, type = CommandType.STRING, required = false, description = "domain admin username in LDAP ") + @Parameter(name = ApiConstants.ADMIN, type = CommandType.STRING, description = "domain admin username in LDAP ") private String admin; @Parameter(name = ApiConstants.ACCOUNT_TYPE, type = CommandType.INTEGER, required = true, description = "Type of the account to auto import. Specify 0 for user and 2 for " + @@ -77,7 +73,7 @@ public String getType() { } public String getLdapDomain() { - return ldapDomain == null ? name : ldapDomain; + return ldapDomain; } public String getAdmin() { @@ -98,7 +94,7 @@ public void execute() throws ServerApiException { try { ldapUser = _ldapManager.getUser(admin, type, getLdapDomain(), domainId); } catch (NoLdapUserMatchingQueryException e) { - logger.debug("no ldap user matching username " + admin + " in the given group/ou", e); + logger.debug("no ldap user matching username {} in the given group/ou", admin, e); } if (ldapUser != null && !ldapUser.isDisabled()) { Account account = _accountService.getActiveAccountByName(admin, domainId); @@ -115,7 +111,7 @@ public void execute() throws ServerApiException { logger.debug("an account with name {} already exists in the domain {} with id {}", admin, _domainService.getDomain(domainId), domainId); } } else { - logger.debug("ldap user with username "+admin+" is disabled in the given group/ou"); + logger.debug("ldap user with username {} is disabled in the given group/ou", admin); } } response.setObjectName("LinkDomainToLdap"); From 6ccb83878555fff3e50171a4040b38739be29942 Mon Sep 17 00:00:00 2001 From: Daan Hoogland Date: Mon, 3 Nov 2025 09:06:02 +0100 Subject: [PATCH 03/12] unlink a domain from ldap --- .../api/command/UnlinkDomainFromLdapCmd.java | 70 +++++++++++++++++++ .../apache/cloudstack/ldap/LdapManager.java | 5 +- .../cloudstack/ldap/LdapManagerImpl.java | 19 ++++- 3 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/UnlinkDomainFromLdapCmd.java diff --git a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/UnlinkDomainFromLdapCmd.java b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/UnlinkDomainFromLdapCmd.java new file mode 100644 index 000000000000..3ca1531d6bc2 --- /dev/null +++ b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/UnlinkDomainFromLdapCmd.java @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cloudstack.api.command; + +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.NetworkRuleConflictException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.user.Account; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.cloudstack.api.response.DomainResponse; +import org.apache.cloudstack.ldap.LdapManager; + +import javax.inject.Inject; + +@APICommand(name = "unlinkDomainFromLdap", description = "remove the linkage of a cloudstack domain to group or OU in ldap", + responseObject = SuccessResponse.class, since = "4.23.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) +public class UnlinkDomainFromLdapCmd extends BaseCmd { + @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, required = true, entityType = DomainResponse.class, + description = "The id of the domain which has to be linked to LDAP.") + private Long domainId; + + @Inject + private LdapManager _ldapManager; + + public Long getDomainId() { + return domainId; + } + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { + boolean rc = _ldapManager.unlinkDomainFromLdap(this); + SuccessResponse response = new SuccessResponse(); + if (rc) { + response.setDisplayText("Domain unlinked from LDAP successfully"); + response.setSuccess(true); + } else { + response.setDisplayText("Failed to unlink domain from LDAP"); + response.setSuccess(false); + } + setResponseObject(response); + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } +} diff --git a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/LdapManager.java b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/LdapManager.java index ded6e94c12a8..ac50a8130c13 100644 --- a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/LdapManager.java +++ b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/LdapManager.java @@ -23,6 +23,7 @@ import org.apache.cloudstack.api.command.LdapListConfigurationCmd; import org.apache.cloudstack.api.command.LinkAccountToLdapCmd; import org.apache.cloudstack.api.command.LinkDomainToLdapCmd; +import org.apache.cloudstack.api.command.UnlinkDomainFromLdapCmd; import org.apache.cloudstack.api.response.LdapConfigurationResponse; import org.apache.cloudstack.api.response.LdapUserResponse; @@ -34,7 +35,7 @@ public interface LdapManager extends PluggableService { - enum LinkType { GROUP, OU;} + enum LinkType { GROUP, OU} LdapConfigurationResponse addConfiguration(final LdapAddConfigurationCmd cmd) throws InvalidParameterValueException; @@ -69,6 +70,8 @@ enum LinkType { GROUP, OU;} LinkDomainToLdapResponse linkDomainToLdap(LinkDomainToLdapCmd cmd); + boolean unlinkDomainFromLdap(UnlinkDomainFromLdapCmd cmd); + LdapTrustMapVO getDomainLinkedToLdap(long domainId); List getDomainLinkage(long domainId); diff --git a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/LdapManagerImpl.java b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/LdapManagerImpl.java index abf47d4094e8..7d0dec70527d 100644 --- a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/LdapManagerImpl.java +++ b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/LdapManagerImpl.java @@ -43,6 +43,7 @@ import org.apache.cloudstack.api.command.LdapUserSearchCmd; import org.apache.cloudstack.api.command.LinkAccountToLdapCmd; import org.apache.cloudstack.api.command.LinkDomainToLdapCmd; +import org.apache.cloudstack.api.command.UnlinkDomainFromLdapCmd; import org.apache.cloudstack.api.response.LdapConfigurationResponse; import org.apache.cloudstack.api.response.LdapUserResponse; import org.apache.cloudstack.api.response.LinkAccountToLdapResponse; @@ -292,7 +293,7 @@ private LdapConfigurationResponse deleteConfigurationInternal(final String hostn @Override public List> getCommands() { - final List> cmdList = new ArrayList>(); + final List> cmdList = new ArrayList<>(); cmdList.add(LdapUserSearchCmd.class); cmdList.add(LdapListUsersCmd.class); cmdList.add(LdapAddConfigurationCmd.class); @@ -393,7 +394,7 @@ public Pair, Integer> listConfigurations(fin final boolean listAll = cmd.listAll(); final Long id = cmd.getId(); final Pair, Integer> result = _ldapConfigurationDao.searchConfigurations(id, hostname, port, domainId, listAll); - return new Pair, Integer>(result.first(), result.second()); + return new Pair<>(result.first(), result.second()); } @Override @@ -423,6 +424,11 @@ public LinkDomainToLdapResponse linkDomainToLdap(LinkDomainToLdapCmd cmd) { return linkDomainToLdap(cmd.getDomainId(),cmd.getType(), ldapDomain,cmd.getAccountType()); } + @Override + public boolean unlinkDomainFromLdap(UnlinkDomainFromLdapCmd cmd) { + return unlinkDomainFromLdap(cmd.getDomainId()); + } + private LinkDomainToLdapResponse linkDomainToLdap(Long domainId, String type, String name, Account.Type accountType) { Validate.notNull(type, "type cannot be null. It should either be GROUP or OU"); Validate.notNull(domainId, "domainId cannot be null."); @@ -442,6 +448,15 @@ private LinkDomainToLdapResponse linkDomainToLdap(Long domainId, String type, St return response; } + private boolean unlinkDomainFromLdap(Long domainId) { + LdapTrustMapVO vo = _ldapTrustMapDao.findByDomainId(domainId); + if (vo != null) { + removeTrustmap(vo); + return true; + } + return false; + } + @Override public LdapTrustMapVO getDomainLinkedToLdap(long domainId){ return _ldapTrustMapDao.findByDomainId(domainId); From 71a1563fea6f5b6e0bee98d2be7b08e6adc39764 Mon Sep 17 00:00:00 2001 From: dahn Date: Mon, 3 Nov 2025 12:33:05 +0100 Subject: [PATCH 04/12] Update responce handling Co-authored-by: Abhishek Kumar --- .../apache/cloudstack/api/command/UnlinkDomainFromLdapCmd.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/UnlinkDomainFromLdapCmd.java b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/UnlinkDomainFromLdapCmd.java index 3ca1531d6bc2..782830ea99be 100644 --- a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/UnlinkDomainFromLdapCmd.java +++ b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/UnlinkDomainFromLdapCmd.java @@ -53,12 +53,11 @@ public Long getDomainId() { public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { boolean rc = _ldapManager.unlinkDomainFromLdap(this); SuccessResponse response = new SuccessResponse(); + response.setSuccess(rc); if (rc) { response.setDisplayText("Domain unlinked from LDAP successfully"); - response.setSuccess(true); } else { response.setDisplayText("Failed to unlink domain from LDAP"); - response.setSuccess(false); } setResponseObject(response); } From abb26100f5a95269a8156c79f3c5fb2027c37248 Mon Sep 17 00:00:00 2001 From: dahn Date: Mon, 3 Nov 2025 12:33:38 +0100 Subject: [PATCH 05/12] Update dependency version Co-authored-by: Abhishek Kumar --- plugins/user-authenticators/ldap/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/user-authenticators/ldap/pom.xml b/plugins/user-authenticators/ldap/pom.xml index c78447105e8b..3c1a294cbfdc 100644 --- a/plugins/user-authenticators/ldap/pom.xml +++ b/plugins/user-authenticators/ldap/pom.xml @@ -218,7 +218,7 @@ org.apache.cloudstack cloud-api - 4.22.0.0-SNAPSHOT + ${project.version} compile From 8397bf7d77ee39557ac1c31fbc55006c7a3ec89c Mon Sep 17 00:00:00 2001 From: Daan Hoogland Date: Mon, 3 Nov 2025 13:10:03 +0100 Subject: [PATCH 06/12] text updates (polishing) --- .../cloudstack/api/command/UnlinkDomainFromLdapCmd.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/UnlinkDomainFromLdapCmd.java b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/UnlinkDomainFromLdapCmd.java index 782830ea99be..09429639c25d 100644 --- a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/UnlinkDomainFromLdapCmd.java +++ b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/UnlinkDomainFromLdapCmd.java @@ -35,11 +35,11 @@ import javax.inject.Inject; -@APICommand(name = "unlinkDomainFromLdap", description = "remove the linkage of a cloudstack domain to group or OU in ldap", +@APICommand(name = "unlinkDomainFromLdap", description = "remove the linkage of a Domain to a group or OU in ldap", responseObject = SuccessResponse.class, since = "4.23.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UnlinkDomainFromLdapCmd extends BaseCmd { @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, required = true, entityType = DomainResponse.class, - description = "The id of the domain which has to be linked to LDAP.") + description = "The id of the Domain which has to be unlinked from LDAP.") private Long domainId; @Inject From 70e06647b0275ef87352e7f114ac1e76317248d3 Mon Sep 17 00:00:00 2001 From: Daan Hoogland Date: Wed, 5 Nov 2025 08:32:45 +0100 Subject: [PATCH 07/12] add command to manager --- .../main/java/org/apache/cloudstack/ldap/LdapManagerImpl.java | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/LdapManagerImpl.java b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/LdapManagerImpl.java index 7d0dec70527d..a139688700a4 100644 --- a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/LdapManagerImpl.java +++ b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/LdapManagerImpl.java @@ -305,6 +305,7 @@ public List> getCommands() { cmdList.add(LDAPRemoveCmd.class); cmdList.add(LinkDomainToLdapCmd.class); cmdList.add(LinkAccountToLdapCmd.class); + cmdList.add(UnlinkDomainFromLdapCmd.class); return cmdList; } From 6b633cefef97e4ff7bd7aa0988463929270ce762 Mon Sep 17 00:00:00 2001 From: Daan Hoogland Date: Wed, 5 Nov 2025 12:31:28 +0100 Subject: [PATCH 08/12] unlink a domain from ldap from ui --- ui/src/config/section/domain.js | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/ui/src/config/section/domain.js b/ui/src/config/section/domain.js index fbe20ef8891b..706cbf805cfa 100644 --- a/ui/src/config/section/domain.js +++ b/ui/src/config/section/domain.js @@ -144,7 +144,7 @@ export default { docHelp: 'adminguide/accounts.html#using-an-ldap-server-for-user-authentication', listView: true, dataView: true, - args: ['type', 'domainid', 'name', 'accounttype', 'admin'], + args: ['type', 'domainid', 'ldapdomain', 'accounttype', 'admin'], mapping: { type: { options: ['GROUP', 'OU'] @@ -157,6 +157,20 @@ export default { } } }, + { + api: 'unlinkDomainFromLdap', + icon: 'ArrowsAltOutlined', + label: 'label.unlink.domain.from.ldap', + docHelp: 'adminguide/accounts.html#using-an-ldap-server-for-user-authentication', + listView: true, + dataView: true, + args: ['domainid'], + mapping: { + domainid: { + value: (record) => { return record.id } + } + } + }, { api: 'deleteDomain', icon: 'delete-outlined', From 60e7c49f7728b808ca0ba1999e2c8d1e53ebf231 Mon Sep 17 00:00:00 2001 From: Daan Hoogland Date: Wed, 5 Nov 2025 14:18:09 +0100 Subject: [PATCH 09/12] set command name in resopnse --- .../apache/cloudstack/api/command/UnlinkDomainFromLdapCmd.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/UnlinkDomainFromLdapCmd.java b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/UnlinkDomainFromLdapCmd.java index 09429639c25d..353779a53101 100644 --- a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/UnlinkDomainFromLdapCmd.java +++ b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/UnlinkDomainFromLdapCmd.java @@ -52,7 +52,7 @@ public Long getDomainId() { @Override public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { boolean rc = _ldapManager.unlinkDomainFromLdap(this); - SuccessResponse response = new SuccessResponse(); + SuccessResponse response = new SuccessResponse(getCommandName()); response.setSuccess(rc); if (rc) { response.setDisplayText("Domain unlinked from LDAP successfully"); From de3719058322617f3a2ba646c300f66887ae1ba7 Mon Sep 17 00:00:00 2001 From: Daan Hoogland Date: Wed, 12 Nov 2025 08:38:49 +0100 Subject: [PATCH 10/12] add message --- ui/public/locales/en.json | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index 9dc2c60fd18c..0de05256b594 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -2587,6 +2587,7 @@ "label.undefined": "Undefined", "label.unit": "Usage unit", "label.unknown": "Unknown", +"label.unlink.domain.from.ldap": "Unlink the Domain from LDAP", "label.unlimited": "Unlimited", "label.unmanaged": "Unmanaged", "label.unmanage.instance": "Unmanage Instance", From 98faea947a54c8916b5a018e456ec441439d4bd2 Mon Sep 17 00:00:00 2001 From: Daan Hoogland Date: Wed, 3 Dec 2025 09:42:20 +0100 Subject: [PATCH 11/12] label --- ui/public/locales/en.json | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index 0de05256b594..d29bab3521a1 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -1452,6 +1452,7 @@ "label.lbruleid": "Load balancer ID", "label.lbtype": "Load balancer type", "label.ldap": "LDAP", +"label.ldapdomain": "LDAP Domain", "label.ldap.configuration": "LDAP Configuration", "label.ldap.group.name": "LDAP Group", "label.level": "Level", From 9c68433ee7ff9f438ce754ff9a9b64a2bb580fbb Mon Sep 17 00:00:00 2001 From: dahn Date: Wed, 10 Dec 2025 12:06:08 +0100 Subject: [PATCH 12/12] ID instead of id Co-authored-by: Suresh Kumar Anaparti --- .../apache/cloudstack/api/command/UnlinkDomainFromLdapCmd.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/UnlinkDomainFromLdapCmd.java b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/UnlinkDomainFromLdapCmd.java index 353779a53101..08f5e99bc2de 100644 --- a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/UnlinkDomainFromLdapCmd.java +++ b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/UnlinkDomainFromLdapCmd.java @@ -39,7 +39,7 @@ responseObject = SuccessResponse.class, since = "4.23.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UnlinkDomainFromLdapCmd extends BaseCmd { @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, required = true, entityType = DomainResponse.class, - description = "The id of the Domain which has to be unlinked from LDAP.") + description = "The ID of the Domain which has to be unlinked from LDAP.") private Long domainId; @Inject