diff --git a/plugins/user-authenticators/ldap/pom.xml b/plugins/user-authenticators/ldap/pom.xml index c02d3d511e6e..3c1a294cbfdc 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 + ${project.version} + compile + 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"); 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..353779a53101 --- /dev/null +++ b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/UnlinkDomainFromLdapCmd.java @@ -0,0 +1,69 @@ +/* + * 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 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 unlinked from 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(getCommandName()); + response.setSuccess(rc); + if (rc) { + response.setDisplayText("Domain unlinked from LDAP successfully"); + } else { + response.setDisplayText("Failed to unlink domain from LDAP"); + } + 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..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 @@ -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); @@ -304,6 +305,7 @@ public List> getCommands() { cmdList.add(LDAPRemoveCmd.class); cmdList.add(LinkDomainToLdapCmd.class); cmdList.add(LinkAccountToLdapCmd.class); + cmdList.add(UnlinkDomainFromLdapCmd.class); return cmdList; } @@ -393,7 +395,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 +425,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 +449,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); diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index 529929eb5243..a9ef76c656a7 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -1451,6 +1451,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", @@ -2585,6 +2586,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", 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',