Java tutorial
/* * * Copyright (c) 2012-2015 VMware, Inc. All Rights Reserved. * * Licensed 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. * */ /** * VMware Identity Service * * (LDAP) Directory Configuration Manager * * @author: Sriram Nambakam <snambakam@vmware.com> * * @version: 1.0 * @since: 2011-12-7 * */ package com.vmware.identity.idm.server.config.directory; import java.net.URI; import java.security.PrivateKey; import java.security.SecureRandom; import java.security.cert.Certificate; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.StringUtils; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; import com.vmware.identity.diagnostics.DiagnosticsLoggerFactory; import com.vmware.identity.diagnostics.IDiagnosticsLogger; import com.vmware.identity.idm.AlternativeOCSP; import com.vmware.identity.idm.AlternativeOCSPList; import com.vmware.identity.idm.AssertionConsumerService; import com.vmware.identity.idm.Attribute; import com.vmware.identity.idm.AttributeConfig; import com.vmware.identity.idm.AttributeConsumerService; import com.vmware.identity.idm.CertificateInUseException; import com.vmware.identity.idm.CertificateType; import com.vmware.identity.idm.CertificateUtil; import com.vmware.identity.idm.ClientCertPolicy; import com.vmware.identity.idm.DomainType; import com.vmware.identity.idm.DuplicateCertificateException; import com.vmware.identity.idm.DuplicateProviderException; import com.vmware.identity.idm.DuplicatedOIDCRedirectURLException; import com.vmware.identity.idm.IDMException; import com.vmware.identity.idm.IDPConfig; import com.vmware.identity.idm.IIdentityStoreData; import com.vmware.identity.idm.IIdentityStoreDataEx; import com.vmware.identity.idm.IdentityStoreAttributeMapping; import com.vmware.identity.idm.IdentityStoreObjectMapping; import com.vmware.identity.idm.IdentityStoreSchemaMapping; import com.vmware.identity.idm.IdentityStoreType; import com.vmware.identity.idm.LocalISRegistrationException; import com.vmware.identity.idm.NoSuchCertificateException; import com.vmware.identity.idm.NoSuchExternalIdpConfigException; import com.vmware.identity.idm.NoSuchIdpException; import com.vmware.identity.idm.NoSuchOIDCClientException; import com.vmware.identity.idm.NoSuchRelyingPartyException; import com.vmware.identity.idm.NoSuchResourceServerException; import com.vmware.identity.idm.NoSuchTenantException; import com.vmware.identity.idm.OIDCClient; import com.vmware.identity.idm.PasswordExpiration; import com.vmware.identity.idm.RSAAMInstanceInfo; import com.vmware.identity.idm.RSAAgentConfig; import com.vmware.identity.idm.RelyingParty; import com.vmware.identity.idm.ResourceServer; import com.vmware.identity.idm.ServiceEndpoint; import com.vmware.identity.idm.SignatureAlgorithm; import com.vmware.identity.idm.Tenant; import com.vmware.identity.idm.TokenClaimAttribute; import com.vmware.identity.idm.ValidateUtil; import com.vmware.identity.idm.server.CryptoAESE; import com.vmware.identity.idm.server.IdmCertificate; import com.vmware.identity.idm.server.ServerUtils; import com.vmware.identity.idm.server.config.IConfigStore; import com.vmware.identity.idm.server.config.IdmServerConfig; import com.vmware.identity.idm.server.config.ServerIdentityStoreData; import com.vmware.identity.idm.server.provider.localos.LocalOsIdentityProvider; import com.vmware.identity.interop.directory.Directory; import com.vmware.identity.interop.ldap.AlreadyExistsLdapException; import com.vmware.identity.interop.ldap.AttributeOrValueExistsLdapException; import com.vmware.identity.interop.ldap.ILdapConnectionEx; import com.vmware.identity.interop.ldap.LdapFilterString; import com.vmware.identity.interop.ldap.LdapMod; import com.vmware.identity.interop.ldap.LdapMod.LdapModOperation; import com.vmware.identity.interop.ldap.LdapScope; import com.vmware.identity.interop.ldap.LdapValue; import com.vmware.identity.interop.ldap.NoSuchAttributeLdapException; import com.vmware.identity.interop.ldap.NoSuchObjectLdapException; public class DirectoryConfigStore implements IConfigStore { private static final IDiagnosticsLogger logger = DiagnosticsLoggerFactory.getLogger(DirectoryConfigStore.class); public static final int FLAG_AUTHN_TYPE_ALLOW_NONE = 0x0; public static final int FLAG_AUTHN_TYPE_ALLOW_PASSWORD = 0x1; public static final int FLAG_AUTHN_TYPE_ALLOW_WINDOWS = 0x2; public static final int FLAG_AUTHN_TYPE_ALLOW_TLS_CERTIFICATE = 0x4; public static final int FLAG_AUTHN_TYPE_ALLOW_RSA_SECUREID = 0x8; private static final String CLAIM_GROUP_DELIMITER = "#"; private final Collection<URI> _uris; private final String _configRootDn; // dc=vsphere,dc=local private final String tenantCredNamePrefix = "TenantCredential"; private final String tenantTrustedCertChainPrefix = "TrustedCertChain"; private final String OBJECT_CLASS_CISLDU = "vmwCisLdu"; public DirectoryConfigStore(Collection<URI> uris, String configRootDn) { ValidateUtil.validateNotEmpty(configRootDn, "domain"); this._uris = uris; this._configRootDn = configRootDn; } private String randomKey() { SecureRandom random = new SecureRandom(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < 16; i++) sb.append((char) (random.nextInt(96) + 32)); return sb.toString(); } @Override public void addTenant(Tenant tenant, String adminAccountName, char[] adminPwd) throws Exception { ValidateUtil.validateNotNull(tenant, "tenant"); ValidateUtil.validateNotEmpty(tenant.getName(), "tenant.getName()"); ILdapConnectionEx connection = this.getConnection(); try { String identityManagerDn = this.getRootSystemConfigDn(connection, true); if (ServerUtils.isNullOrEmpty(tenant._guid)) { tenant._guid = UUID.randomUUID().toString(); } // Generate tenantKey tenant._tenantKey = this.randomKey(); // ensure tenants container String tenantsContainerDn = DirectoryConfigStore.ensureObjectExists(connection, identityManagerDn, TenantsContainerLdapObject.getInstance(), TenantsContainerLdapObject.CONTAINER_TENANTS, true); TenantLdapObject tenantObject = TenantLdapObject.getInstance(); String tenantDn = tenantObject.getDnFromObject(tenantsContainerDn, tenant); tenantObject.createObject(connection, tenantDn, tenant); this.createSystemDomainIdentityProviderForTenant(connection, tenant.getName(), tenantDn, adminAccountName, adminPwd); } finally { connection.close(); } } @Override public void deleteTenant(String name) throws Exception { ValidateUtil.validateNotEmpty(name, "name"); ILdapConnectionEx connection = this.getConnection(); try { String tenantsRootDn = this.lookupTenantsRootDn(connection, name); if (ServerUtils.isNullOrEmpty(tenantsRootDn) == false) { String defaultTenant = this.getDefaultTenant(connection); if (name.equalsIgnoreCase(defaultTenant)) { this.setDefaultTenant(connection, null); } TenantLdapObject tenantConfigObject = TenantLdapObject.getInstance(); tenantConfigObject.deleteObject(connection, tenantsRootDn); } } finally { connection.close(); } } @Override public Tenant getTenant(String name) throws Exception { ValidateUtil.validateNotEmpty(name, "name"); ILdapConnectionEx connection = this.getConnection(); try { return this.getTenant(connection, name); } finally { connection.close(); } } @Override public Collection<String> getAllTenants() throws Exception { ILdapConnectionEx connection = this.getConnection(); Collection<String> allTenantNames = null; try { allTenantNames = this.lookupAllTenantsDn(connection); } finally { connection.close(); } return allTenantNames; } @Override public void setTenant(Tenant tenant) throws Exception { ValidateUtil.validateNotNull(tenant, "tenant"); ValidateUtil.validateNotEmpty(tenant.getName(), "tenant.getName()"); ILdapConnectionEx connection = this.getConnection(); try { String tenantsRootDn = this.ensureTenantExists(connection, tenant.getName()); TenantLdapObject tenantConfigObject = TenantLdapObject.getInstance(); tenantConfigObject.updateObject(connection, tenantsRootDn, tenant); } finally { connection.close(); } } @Override public String getDefaultTenant() throws Exception { String defaultTenant = null; ILdapConnectionEx connection = this.getConnection(); try { defaultTenant = this.getDefaultTenant(connection); } finally { connection.close(); } return defaultTenant; } @Override public void setDefaultTenant(String tenantName) throws Exception { // should we allow null to "erase" the default tenant ? ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ILdapConnectionEx connection = this.getConnection(); try { this.ensureTenantExists(connection, tenantName); this.setDefaultTenant(connection, tenantName); } finally { connection.close(); } } @Override public String getSystemTenant() throws Exception { String systemTenant = null; ILdapConnectionEx connection = this.getConnection(); try { systemTenant = this.getSystemTenant(connection); } finally { connection.close(); } return systemTenant; } @Override public void setSystemTenant(String tenantName) throws Exception { // should we allow null to "erase" the default tenant ? ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ILdapConnectionEx connection = this.getConnection(); try { this.ensureTenantExists(connection, tenantName); this.setSystemTenant(connection, tenantName); } finally { connection.close(); } } @Override public Collection<List<Certificate>> getTenantCertChains(String tenantName) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ILdapConnectionEx connection = this.getConnection(); try { String tenantsRootDn = this.ensureTenantExists(connection, tenantName); return getTenantCertificatesForTenant(tenantName, tenantsRootDn, connection); } finally { connection.close(); } } @Override public List<Certificate> getTenantCertificate(String tenantName) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ILdapConnectionEx connection = this.getConnection(); try { String tenantsRootDn = this.ensureTenantExists(connection, tenantName); return getTenantCertificateForTenant(tenantName, tenantsRootDn, connection); } finally { connection.close(); } } @Override public void ensureSPContainerExist(String tenantName) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ILdapConnectionEx connection = this.getConnection(); try { DirectoryConfigStore.ensureObjectExists(connection, ServerUtils.getDomainDN(tenantName), ContainerLdapObject.getInstance(), ContainerLdapObject.CONTAINER_SOLUTION_USERS, true); } finally { connection.close(); } } private int getCurrMaxCredIndex(Set<String> credDns) { int currMaxCredIndex = 0; if (credDns == null || credDns.isEmpty()) { return 0; } // found the biggest index for (String credDn : credDns) { if (credDn != null && !credDn.isEmpty()) { // A sample credDn looks like: // CN=TenantCredential-i,CN=ldu-guid,CN=Ldus,CN=ComponentManager,dc=vsphere,dc=local for systemTenant String indexStr = credDn.substring(credDn.indexOf('-') + 1, credDn.indexOf(',')); if (indexStr != null && !indexStr.isEmpty()) { int currIndex = Integer.parseInt(indexStr); if (currMaxCredIndex < currIndex) { currMaxCredIndex = currIndex; } } } } return currMaxCredIndex; } private TenantCredentialInformation getLastSetTenantCred(String tenantName, String tenantRootDn, ILdapConnectionEx connection) throws Exception { TenantCredentialsLdapObject tenantCredsObj = TenantCredentialsLdapObject.getInstance(); TenantCredentialInformation lateSetTenantCred = null; // multi-tenantCredential is supported, // we only return the latest set tenant credential's certChain ( we need decide what algorithm to use // in order to determine which tenantCredential record should be used to return information for this API Set<String> tenantCredsDns = tenantCredsObj.lookupObjects(connection, tenantRootDn, LdapScope.SCOPE_ONE_LEVEL, null, TenantCredentialsLdapObject.OBJECT_CLASS); if (tenantCredsDns != null && tenantCredsDns.size() >= 1) { String tenantCredsDn = this.getTenantCredentialDn(getCurrMaxCredIndex(tenantCredsDns), tenantRootDn); lateSetTenantCred = tenantCredsObj.retrieveObject(connection, tenantCredsDn, LdapScope.SCOPE_BASE, null); } return lateSetTenantCred; } private List<Certificate> getTenantCertificateForTenant(String tenantName, String tenantRootDn, ILdapConnectionEx connection) throws Exception { TenantCredentialInformation lateSetTenantCred = getLastSetTenantCred(tenantName, tenantRootDn, connection); return (lateSetTenantCred == null) ? null : lateSetTenantCred.getCertificateChain(); } private Collection<List<Certificate>> getTenantCertificatesForTenant(String tenantName, String tenantRootDn, ILdapConnectionEx connection) throws Exception { Collection<List<Certificate>> certChains = Collections.emptyList(); Collection<TenantTrustedCertificateChain> trustedCertChains = retrieveObjectsCollection(connection, tenantRootDn, ContainerLdapObject.CONTAINER_TRUSTED_CERTIFICATE_CHAINS, TenantTrustedCertChainLdapObject.getInstance(), null); if (trustedCertChains != null && !trustedCertChains.isEmpty()) { certChains = new ArrayList<List<Certificate>>(trustedCertChains.size()); for (TenantTrustedCertificateChain tenantCred : trustedCertChains) { certChains.add(tenantCred.getCertificateChain()); } } return certChains; } @Override public void setTenantCredentials(String tenantName, Collection<Certificate> tenantCertificates, PrivateKey tenantPrivateKey) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ILdapConnectionEx connection = this.getConnection(); try { String tenantsRootDn = this.ensureTenantExists(connection, tenantName); setTenantCredentialsForTenant(tenantName, tenantsRootDn, connection, tenantCertificates, tenantPrivateKey); } finally { connection.close(); } } private void setTenantCredentialsForTenant(String tenantName, String tenantsRootDn, ILdapConnectionEx connection, Collection<Certificate> tenantCertificates, PrivateKey tenantPrivateKey) throws Exception { TenantCredentialsLdapObject tenantCredsObj = TenantCredentialsLdapObject.getInstance(); Set<String> tenantCredsDns = tenantCredsObj.lookupObjects(connection, tenantsRootDn, LdapScope.SCOPE_ONE_LEVEL, null, TenantCredentialsLdapObject.OBJECT_CLASS); // construct the new tenantCredential's CN by indexing it with the highest index plus 1 int credsIndex = getCurrMaxCredIndex(tenantCredsDns) + 1; TenantCredentialInformation tenantCredInfo = new TenantCredentialInformation( this.getTenantCredentialCn(credsIndex), tenantPrivateKey, new ArrayList<Certificate>(tenantCertificates)); String tenantCredsDn = tenantCredsObj.getDnFromObject(tenantsRootDn, tenantCredInfo); tenantCredsObj.createObject(connection, tenantCredsDn, tenantCredInfo); // Duplicate the tenant signing certs in trustedCertificatChain for better lookup // MEMO: upon a signing credential deletion, needs to remove this trusted CertChain record setTenantTrustedCertificateChainForTenant(tenantName, tenantsRootDn, connection, tenantCertificates); } private void deleteTenantCredentialsForTenant(String tenantName, String tenantsRootDn, ILdapConnectionEx connection, Collection<Certificate> tenantCertificates) throws Exception { TenantCredentialsLdapObject tenantCredsObj = TenantCredentialsLdapObject.getInstance(); Set<String> tenantCredsDns = tenantCredsObj.lookupObjects(connection, tenantsRootDn, LdapScope.SCOPE_ONE_LEVEL, null, TenantCredentialsLdapObject.OBJECT_CLASS); for (String tenantCredsDn : tenantCredsDns) { List<TenantCredentialInformation> tenantCred = tenantCredsObj.searchObjects(connection, tenantCredsDn, LdapScope.SCOPE_BASE); if (tenantCred != null && !tenantCred.isEmpty() && tenantCred.size() == 1) { if (tenantCred.get(0).getCertificateChain().equals(tenantCertificates)) { tenantCredsObj.deleteObject(connection, tenantCredsDn); } } } } @Override public void setTenantTrustedCertificateChain(String tenantName, Collection<Certificate> tenantCertificates) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ILdapConnectionEx connection = this.getConnection(); try { String tenantsRootDn = this.ensureTenantExists(connection, tenantName); setTenantTrustedCertificateChainForTenant(tenantName, tenantsRootDn, connection, tenantCertificates); } finally { connection.close(); } } private void setTenantTrustedCertificateChainForTenant(String tenantName, String tenantsRootDn, ILdapConnectionEx connection, Collection<Certificate> tenantCertificates) throws Exception { String tenantCertChainContainerDn = DirectoryConfigStore.ensureObjectExists(connection, tenantsRootDn, ContainerLdapObject.getInstance(), ContainerLdapObject.CONTAINER_TRUSTED_CERTIFICATE_CHAINS, true); TenantTrustedCertChainLdapObject tenantTrustedCertChainObj = TenantTrustedCertChainLdapObject.getInstance(); Set<String> tenantTrustedCertchainDns = tenantTrustedCertChainObj.lookupObjects(connection, tenantCertChainContainerDn, LdapScope.SCOPE_ONE_LEVEL, null, TenantTrustedCertChainLdapObject.OBJECT_CLASS); // construct the new tenantCredential's CN by indexing it with the highest index plus 1 int credsIndex = getCurrMaxCredIndex(tenantTrustedCertchainDns) + 1; TenantTrustedCertificateChain tenantTrusterCertChainInfo = new TenantTrustedCertificateChain( this.getTenantTrustedCertChainCn(credsIndex), new ArrayList<Certificate>(tenantCertificates)); String tenantTrustedCertChainDn = tenantTrustedCertChainObj.getDnFromObject(tenantCertChainContainerDn, tenantTrusterCertChainInfo); tenantTrustedCertChainObj.createObject(connection, tenantTrustedCertChainDn, tenantTrusterCertChainInfo); } private void deleteTenantTrustedCertificateChainForTenant(String tenantName, String tenantsRootDn, ILdapConnectionEx connection, List<Certificate> tenantCertificates) throws Exception { String tenantCertChainContainerDn = DirectoryConfigStore.ensureObjectExists(connection, tenantsRootDn, ContainerLdapObject.getInstance(), ContainerLdapObject.CONTAINER_TRUSTED_CERTIFICATE_CHAINS, true); TenantTrustedCertChainLdapObject tenantTrusterCerdChainObj = TenantTrustedCertChainLdapObject.getInstance(); Set<String> tenantTrustedCertchainDns = tenantTrusterCerdChainObj.lookupObjects(connection, tenantCertChainContainerDn, LdapScope.SCOPE_ONE_LEVEL, null, TenantTrustedCertChainLdapObject.OBJECT_CLASS); for (String certChainDn : tenantTrustedCertchainDns) { List<TenantTrustedCertificateChain> certChain = tenantTrusterCerdChainObj.searchObjects(connection, certChainDn, LdapScope.SCOPE_BASE); if (certChain != null && !certChain.isEmpty() && certChain.size() == 1) { if (certChain.get(0).getCertificateChain().equals(tenantCertificates)) { tenantTrusterCerdChainObj.deleteObject(connection, certChainDn); } } } } @Override public PrivateKey getTenantPrivateKey(String tenantName) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ILdapConnectionEx connection = this.getConnection(); try { String tenantsRootDn = this.ensureTenantExists(connection, tenantName); return getTenantPrivateKeyForTenant(tenantName, tenantsRootDn, connection); } finally { connection.close(); } } private PrivateKey getTenantPrivateKeyForTenant(String tenantName, String tenantRootDn, ILdapConnectionEx connection) throws Exception { TenantCredentialInformation lateSetTenantCred = getLastSetTenantCred(tenantName, tenantRootDn, connection); return (lateSetTenantCred == null) ? null : lateSetTenantCred.getPrivateKey(); } @Override public void setAlias(String tenantName, String alias) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateNotEmpty(alias, "alias"); LdapValue[] value = ServerUtils.getLdapValue(alias); this.setTenantProperty(tenantName, TenantLdapObject.PROPERTY_ALIAS, value); } @Override public void setTenantIDPSelectionEnabled(String tenantName, boolean enableIDPSelection) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); LdapValue[] value = ServerUtils.getLdapValue(enableIDPSelection); this.setTenantProperty(tenantName, TenantLdapObject.PROPERTY_ENABLE_IDP_SELECTION, value); } @Override public TenantAttributes getTokenPolicyExt(String tenantName) throws Exception { ILdapConnectionEx connection = this.getConnection(); String tenantsRootDn = null; TenantAttributes tenantAttributes = null; try { tenantsRootDn = this.lookupTenantsRootDn(connection, tenantName); if (ServerUtils.isNullOrEmpty(tenantsRootDn)) { throw new RuntimeException(String.format("Tenant '%s' does not exist.", tenantName)); } TenantAttributesLdapObject tenantAttributesObject = TenantAttributesLdapObject.getInstance(); tenantAttributes = tenantAttributesObject.retrieveObject(connection, tenantsRootDn, LdapScope.SCOPE_BASE, null); } finally { connection.close(); } return tenantAttributes; } @Override public long getClockTolerance(String tenantName) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); LdapValue[] value = this.getTenantProperty(tenantName, TenantLdapObject.PROPERTY_CLOCK_TOLERANCE); return value != null ? ServerUtils.getNativeLongValue(value) : IConfigStore.DEFAULT_CLOCK_TOLERANCE; } @Override public void setClockTolerance(String tenantName, long milliseconds) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateNonNegativeNumber(milliseconds, "milliseconds"); LdapValue[] value = ServerUtils.getLdapValue(milliseconds); this.setTenantProperty(tenantName, TenantLdapObject.PROPERTY_CLOCK_TOLERANCE, value); } @Override public String getSignatureAlgorithm(String tenantName) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); LdapValue[] value = this.getTenantProperty(tenantName, TenantLdapObject.PROPERTY_SIGNATURE_ALGORITHM); return value != null ? ServerUtils.getStringValue(value) : null; } @Override public void setSignatureAlgorithm(String tenantName, String signatureAlgorithm) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateNotEmpty(signatureAlgorithm, "signatureAlgorithm"); LdapValue[] value = ServerUtils.getLdapValue(signatureAlgorithm); this.setTenantProperty(tenantName, TenantLdapObject.PROPERTY_SIGNATURE_ALGORITHM, value); } @Override public String getBrandName(String tenantName) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); LdapValue[] value = this.getTenantProperty(tenantName, TenantLdapObject.PROPERTY_BRAND_NAME); return value != null ? ServerUtils.getStringValue(value) : null; } @Override public void setBrandName(String tenantName, String brandName) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); LdapValue[] value = ServerUtils.getLdapValue(brandName); this.setTenantProperty(tenantName, TenantLdapObject.PROPERTY_BRAND_NAME, value); } @Override public String getLogonBannerContent(String tenantName) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); LdapValue[] value = this.getTenantProperty(tenantName, TenantLdapObject.PROPERTY_LOGON_BANNER_CONTENT); return value != null ? ServerUtils.getStringValue(value) : null; } @Override public String getLogonBannerTitle(String tenantName) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); LdapValue[] value = this.getTenantProperty(tenantName, TenantLdapObject.PROPERTY_LOGON_BANNER_TITLE); return value != null ? ServerUtils.getStringValue(value) : null; } @Override public boolean getLogonBannerCheckboxFlag(String tenantName) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); LdapValue[] value = this.getTenantProperty(tenantName, TenantLdapObject.PROPERTY_LOGON_BANNER_ENABLE_CHECKBOX); return value != null ? ServerUtils.getBooleanValue(value) : false; } @Override public void setLogonBannerContent(String tenantName, String logonBannerContent) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); LdapValue[] value = ServerUtils.getLdapValue(logonBannerContent); this.setTenantProperty(tenantName, TenantLdapObject.PROPERTY_LOGON_BANNER_CONTENT, value); } @Override public void setAuthnTypesForProvider(String tenantName, String providerName, boolean password, boolean windows, boolean certificate, boolean rsaSecureID) throws Exception { HashSet<Integer> authnTypes = new HashSet<Integer>(); if (password) { authnTypes.add(DirectoryConfigStore.FLAG_AUTHN_TYPE_ALLOW_PASSWORD); } if (windows) { authnTypes.add(DirectoryConfigStore.FLAG_AUTHN_TYPE_ALLOW_WINDOWS); } if (certificate) { authnTypes.add(DirectoryConfigStore.FLAG_AUTHN_TYPE_ALLOW_TLS_CERTIFICATE); } if (rsaSecureID) { authnTypes.add(DirectoryConfigStore.FLAG_AUTHN_TYPE_ALLOW_RSA_SECUREID); } if (authnTypes.size() == 0) { authnTypes.add(DirectoryConfigStore.FLAG_AUTHN_TYPE_ALLOW_NONE); } int[] authTypesArray = ArrayUtils.toPrimitive(authnTypes.toArray(new Integer[authnTypes.size()])); this.setProviderProperty(tenantName, providerName, IdentityProviderLdapObject.PROPERTY_AUTHN_TYPES, ServerUtils.getLdapValue(authTypesArray)); } /** * Add/Update property for a given identity provider * * @param tenantName name of tenant * @param providerName name of identity source * @param propertyName Name of property to be added * @param propertyValue Value of property to be added * @throws Exception */ private void setProviderProperty(String tenantName, String providerName, String propertyName, LdapValue[] propertyValue) throws Exception { ILdapConnectionEx connection = this.getConnection(); try { // Fetch tenant root dn String tenantsRootDn = this.lookupTenantsRootDn(connection, tenantName); validateTenantExistence(tenantsRootDn); // Fetch identity provider container DN String identityProvidersContainerDn = DirectoryConfigStore.ensureObjectExists(connection, tenantsRootDn, ContainerLdapObject.getInstance(), ContainerLdapObject.CONTAINER_IDENTITY_PROVIDERS, true); // Lookup identity provider dn String identityProviderRootDn = IdentityProviderLdapObject.getInstance().lookupObject(connection, identityProvidersContainerDn, LdapScope.SCOPE_ONE_LEVEL, providerName); setProviderProperty(connection, identityProviderRootDn, propertyName, propertyValue); } finally { connection.close(); } } /** * Set property for an identity provider * */ private static void setProviderProperty(ILdapConnectionEx connection, String identityProvidersContainerDn, String propertyName, LdapValue[] propertyValue) throws Exception { IdentityProviderLdapObject.getInstance().setObjectPropertyValue(connection, identityProvidersContainerDn, propertyName, propertyValue); } private void validateTenantExistence(String tenant) throws NoSuchTenantException { if (ServerUtils.isNullOrEmpty(tenant)) { throw new NoSuchTenantException(String.format("Tenant '%s' does not exist.", tenant)); } } @Override public void setLogonBannerCheckboxFlag(String tenantName, boolean logonBannerEnableCheckbox) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); LdapValue[] value = ServerUtils.getLdapValue(logonBannerEnableCheckbox); this.setTenantProperty(tenantName, TenantLdapObject.PROPERTY_LOGON_BANNER_ENABLE_CHECKBOX, value); } @Override public void setLogonBannerTitle(String tenantName, String logonBannerTitle) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); LdapValue[] value = ServerUtils.getLdapValue(logonBannerTitle); this.setTenantProperty(tenantName, TenantLdapObject.PROPERTY_LOGON_BANNER_TITLE, value); } @Override public int getDelegationCount(String tenantName) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); LdapValue[] value = this.getTenantProperty(tenantName, TenantLdapObject.PROPERTY_DELEGATION_COUNT); return value != null ? ServerUtils.getIntValue(value) : IConfigStore.DEFAULT_DELEGATION_COUNT; } @Override public void setDelegationCount(String tenantName, int delegationCount) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateNonNegativeNumber(delegationCount, "delegationCount"); LdapValue[] value = ServerUtils.getLdapValue(delegationCount); this.setTenantProperty(tenantName, TenantLdapObject.PROPERTY_DELEGATION_COUNT, value); } @Override public int getRenewCount(String tenantName) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); LdapValue[] value = this.getTenantProperty(tenantName, TenantLdapObject.PROPERTY_RENEW_COUNT); return value != null ? ServerUtils.getIntValue(value) : IConfigStore.DEFAULT_RENEW_COUNT; } @Override public void setRenewCount(String tenantName, int renewCount) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateNonNegativeNumber(renewCount, "renewCount"); LdapValue[] value = ServerUtils.getLdapValue(renewCount); this.setTenantProperty(tenantName, TenantLdapObject.PROPERTY_RENEW_COUNT, value); } @Override public long getMaximumBearerTokenLifetime(String tenantName) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); LdapValue[] value = this.getTenantProperty(tenantName, TenantLdapObject.PROPERTY_MAX_BEARTOKEN_LIFETIME); return value != null ? ServerUtils.getNativeLongValue(value) : DEFAULT_MAX_BEARER_LIFETIME; } @Override public void setMaximumBearerTokenLifetime(String tenantName, long maxLifetime) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateNonNegativeNumber(maxLifetime, "maxLifetime"); LdapValue[] value = ServerUtils.getLdapValue(maxLifetime); this.setTenantProperty(tenantName, TenantLdapObject.PROPERTY_MAX_BEARTOKEN_LIFETIME, value); } @Override public long getMaximumHoKTokenLifetime(String tenantName) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); LdapValue[] value = this.getTenantProperty(tenantName, TenantLdapObject.PROPERTY_MAX_HOKTOKEN_LIFETIME); return value != null ? ServerUtils.getNativeLongValue(value) : DEFAULT_MAX_HOK_LIFETIME; } @Override public void setMaximumHoKTokenLifetime(String tenantName, long maxLifetime) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateNonNegativeNumber(maxLifetime, "maxLifetime"); LdapValue[] value = ServerUtils.getLdapValue(maxLifetime); this.setTenantProperty(tenantName, TenantLdapObject.PROPERTY_MAX_HOKTOKEN_LIFETIME, value); } @Override public long getMaximumBearerRefreshTokenLifetime(String tenantName) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); LdapValue[] value = this.getTenantProperty(tenantName, TenantAttributesLdapObject.PROPERTY_MAX_BEARER_REFRESH_TOKEN_LIFETIME); return value != null ? ServerUtils.getNativeLongValue(value) : DEFAULT_MAX_BEARER_REFRESH_TOKEN_LIFETIME; } @Override public void setMaximumBearerRefreshTokenLifetime(String tenantName, long maxLifetime) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateNonNegativeNumber(maxLifetime, "maxLifetime"); LdapValue[] value = ServerUtils.getLdapValue(maxLifetime); this.setTenantProperty(tenantName, TenantAttributesLdapObject.PROPERTY_MAX_BEARER_REFRESH_TOKEN_LIFETIME, value); } @Override public long getMaximumHoKRefreshTokenLifetime(String tenantName) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); LdapValue[] value = this.getTenantProperty(tenantName, TenantAttributesLdapObject.PROPERTY_MAX_HOK_REFRESH_TOKEN_LIFETIME); return value != null ? ServerUtils.getNativeLongValue(value) : DEFAULT_MAX_HOK_REFRESH_TOKEN_LIFETIME; } @Override public void setMaximumHoKRefreshTokenLifetime(String tenantName, long maxLifetime) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateNonNegativeNumber(maxLifetime, "maxLifetime"); LdapValue[] value = ServerUtils.getLdapValue(maxLifetime); this.setTenantProperty(tenantName, TenantAttributesLdapObject.PROPERTY_MAX_HOK_REFRESH_TOKEN_LIFETIME, value); } @Override public PasswordExpiration getPasswordExpirationConfiguration(String tenantName) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); PasswordExpiration pwdExpiration = null; ILdapConnectionEx connection = this.getConnection(); try { String tenantRootDn = this.ensureTenantExists(connection, tenantName); TenantPasswordExpirationLdapObject passwordSettings = TenantPasswordExpirationLdapObject.getInstance(); TenantPasswordExpiration obj = passwordSettings.retrieveObject(connection, tenantRootDn, LdapScope.SCOPE_BASE, null); if (obj != null) { pwdExpiration = obj.getPasswordExpiration(); } } finally { connection.close(); } if (pwdExpiration == null) { throw new RuntimeException( String.format("Tenant %s doesn't have key Configurations in Idm.", tenantName)); } return pwdExpiration; } @Override public void updatePasswordExpirationConfiguration(String tenantName, PasswordExpiration config) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateNotNull(config, "config"); ValidateUtil.validateNotEmpty(config.getEmailFrom(), "config.getEmailFrom()"); ValidateUtil.validateNotEmpty(config.getEmailSubject(), "config.getEmailSubject()"); ILdapConnectionEx connection = this.getConnection(); try { String tenantRootDn = this.ensureTenantExists(connection, tenantName); TenantPasswordExpiration tenantsPasswordExpiration = new TenantPasswordExpiration(tenantName, config); TenantPasswordExpirationLdapObject passwordSettings = TenantPasswordExpirationLdapObject.getInstance(); passwordSettings.updateObject(connection, tenantRootDn, LdapScope.SCOPE_BASE, null, tenantsPasswordExpiration); } finally { connection.close(); } } @Override public Collection<Attribute> getTenantAttributes(String tenantName) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ILdapConnectionEx connection = this.getConnection(); try { String tenantsRootDn = this.ensureTenantExists(connection, tenantName); return retrieveAttributes(connection, tenantsRootDn); } finally { connection.close(); } } @Override public void setTenantAttributes(String tenantName, Collection<Attribute> attributes) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ILdapConnectionEx connection = this.getConnection(); try { String tenantsRootDn = this.ensureTenantExists(connection, tenantName); saveAttributes(connection, tenantsRootDn, attributes); } finally { connection.close(); } } @Override public void addCertificateForSystemTenant(String tenantName, Certificate cert, CertificateType certType) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateNotNull(cert, "idmCert"); ValidateUtil.validateNotEmpty(CertificateUtil.generateFingerprint((X509Certificate) cert), "generateFingerprint for cert"); ValidateUtil.validateNotNull(cert, "idmCert"); ILdapConnectionEx connection = this.getConnection(); try { String tenantsRootDn = this.getSystemTenantCredsDn(); addCertificateForTenant(tenantsRootDn, connection, cert, certType); } finally { connection.close(); } } @Override public void addCertificateForNonSystemTenant(String tenantName, Certificate cert, CertificateType certType) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateNotNull(cert, "idmCert"); ValidateUtil.validateNotEmpty(CertificateUtil.generateFingerprint((X509Certificate) cert), "generateFingerprint for cert"); ValidateUtil.validateNotNull(cert, "idmCert"); ILdapConnectionEx connection = this.getConnection(); try { String tenantsRootDn = this.ensureTenantExists(connection, tenantName); addCertificateForTenant(tenantsRootDn, connection, cert, certType); } finally { connection.close(); } } private void addCertificateForTenant(String tenantRootDn, ILdapConnectionEx connection, Certificate cert, CertificateType certType) throws Exception { IdmCertificate idmCert = new IdmCertificate((X509Certificate) cert, certType); try { String idmCertificatesContainerDn = DirectoryConfigStore.ensureObjectExists(connection, tenantRootDn, ContainerLdapObject.getInstance(), ContainerLdapObject.CONTAINER_IDM_CERTIFICATES, true); IdmCertificateLdapObject idmCertObject = IdmCertificateLdapObject.getInstance(); idmCertObject.createObject(connection, idmCertObject.getDnFromObject(idmCertificatesContainerDn, idmCert), idmCert); } catch (AlreadyExistsLdapException e) { throw new DuplicateCertificateException(String.format( "addCertificateForTenant failed - " + "Certificate already exists in %s", tenantRootDn)); } } @Override public Collection<Certificate> getAllCertificatesForSystemTenant(String tenantName, CertificateType certType) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateCertType(certType, "certificateType"); Collection<Certificate> allTrustedCertificates = new ArrayList<Certificate>(); ILdapConnectionEx connection = this.getConnection(); try { String lduContainerDn = this.getSystemTenantLduDn(); ContainerLdapObject lduContainer = ContainerLdapObject.getInstance(); Set<String> tenantCredsRootDns = lduContainer.lookupObjects(connection, lduContainerDn, LdapScope.SCOPE_SUBTREE, null, OBJECT_CLASS_CISLDU); if (tenantCredsRootDns != null && tenantCredsRootDns.size() != 0) { for (String tenantCredsRootDn : tenantCredsRootDns) { Collection<Certificate> certsInLdu = getAllCertificatesForTenant(tenantName, tenantCredsRootDn, connection, certType); if (certsInLdu != null && certsInLdu.size() != 0) { // Add the current list of chains for (Certificate cert : certsInLdu) { allTrustedCertificates.add(cert); } } } } return allTrustedCertificates; } finally { connection.close(); } } @Override public Collection<Certificate> getAllCertificatesForNonSystemTenant(String tenantName, CertificateType certType) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateCertType(certType, "certificateType"); ILdapConnectionEx connection = this.getConnection(); try { String tenantsRootDn = this.ensureTenantExists(connection, tenantName); return getAllCertificatesForTenant(tenantName, tenantsRootDn, connection, certType); } finally { connection.close(); } } private Collection<Certificate> getAllCertificatesForTenant(String tenantName, String tenantRootDn, ILdapConnectionEx connection, CertificateType certType) throws Exception { Collection<Certificate> certSet = new ArrayList<Certificate>(); Collection<Certificate> allCertsInContainer = new ArrayList<Certificate>(); Collection<Certificate> allStsCerts = Collections.emptySet(); ; String certTypeFilter = String.format("(%s=%s)", IdmCertificateLdapObject.PROPERTY_CERT_TYPE, // attribute name LdapFilterString.encode(certType.toString())); Collection<IdmCertificate> certs = retrieveObjectsCollection(connection, tenantRootDn, ContainerLdapObject.CONTAINER_IDM_CERTIFICATES, certTypeFilter, IdmCertificateLdapObject.getInstance(), null); if (null != certs && certs.size() > 0) { for (IdmCertificate cert : certs) { allCertsInContainer.add(cert.getCertificate()); } certSet.addAll(allCertsInContainer); } if (certType == CertificateType.STS_TRUST_CERT) { allStsCerts = getAllStsCertificatesForTenant(tenantName, tenantRootDn, connection); if (allStsCerts != null && !allStsCerts.isEmpty()) certSet.addAll(allStsCerts); } return certSet; } @Override public Collection<Certificate> getTrustedCertificatesForTenant(String tenantName) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ILdapConnectionEx connection = this.getConnection(); try { String tenantsRootDn = this.ensureTenantExists(connection, tenantName); return getTrustedCertificatesForTenant(tenantName, tenantsRootDn, connection); } finally { connection.close(); } } /* retrieve all the trusted root certificates */ private Collection<Certificate> getTrustedCertificatesForTenant(String tenantName, String tenantRootDn, ILdapConnectionEx connection) throws Exception { List<Certificate> certSet = new ArrayList<Certificate>(); Collection<List<Certificate>> trustedCertChains = getTenantCertificatesForTenant(tenantName, tenantRootDn, connection); if (trustedCertChains != null && !trustedCertChains.isEmpty()) { for (List<Certificate> certChain : trustedCertChains) { if (certChain != null && !certChain.isEmpty()) { certSet.add(getRootCert(certChain)); } } } return certSet; } @Override public Collection<Certificate> getStsIssuersCertificatesForTenant(String tenantName) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ILdapConnectionEx connection = this.getConnection(); try { String tenantsRootDn = this.ensureTenantExists(connection, tenantName); return getStsIssuersCertificatesForTenant(tenantName, tenantsRootDn, connection); } finally { connection.close(); } } /* retrieve all the trusted leaf certificates */ private Collection<Certificate> getStsIssuersCertificatesForTenant(String tenantName, String tenantRootDn, ILdapConnectionEx connection) throws Exception { List<Certificate> certSet = new ArrayList<Certificate>(); Collection<List<Certificate>> trustedCertChains = getTenantCertificatesForTenant(tenantName, tenantRootDn, connection); if (trustedCertChains != null && !trustedCertChains.isEmpty()) { for (List<Certificate> certChain : trustedCertChains) { if (certChain != null && !certChain.isEmpty()) { certSet.add(getLeafCert(certChain)); } } } return certSet; } /* retrieve all sts certificates */ private Collection<Certificate> getAllStsCertificatesForTenant(String tenantName, String tenantRootDn, ILdapConnectionEx connection) throws Exception { List<Certificate> certSet = new ArrayList<Certificate>(); Collection<List<Certificate>> trustedCertChains = getTenantCertificatesForTenant(tenantName, tenantRootDn, connection); if (trustedCertChains != null && !trustedCertChains.isEmpty()) { for (List<Certificate> certChain : trustedCertChains) { if (certChain != null && !certChain.isEmpty()) { for (Certificate cert : certChain) certSet.add(cert); } } } return certSet; } private Certificate getRootCert(List<Certificate> certChain) { return certChain.get(certChain.size() - 1); } private Certificate getLeafCert(List<Certificate> certChain) { return certChain.get(0); } private boolean isIssuedByCert(List<Certificate> certChain, X509Certificate certToCheck) { if (certChain == null || certChain.isEmpty()) return false; for (Certificate cert : certChain) { X509Certificate x509Cert = (X509Certificate) cert; if (x509Cert.getSubjectDN().getName().compareToIgnoreCase(certToCheck.getIssuerDN().getName()) == 0) { return true; } } return false; } @Override public void deleteCertificateForSystemTenant(String tenantName, String fingerprint, CertificateType certType) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateNotEmpty(fingerprint, "fingerprint"); ValidateUtil.validateCertType(certType, "certificateType"); ILdapConnectionEx connection = this.getConnection(); try { String tenantsRootDn = this.getSystemTenantCredsDn(); deleteCertificateForTenant(tenantName, tenantsRootDn, connection, fingerprint, certType); } finally { connection.close(); } } @Override public void deleteCertificateForNonSystemTenant(String tenantName, String fingerprint, CertificateType certType) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateNotEmpty(fingerprint, "fingerprint"); ValidateUtil.validateCertType(certType, "certificateType"); ILdapConnectionEx connection = this.getConnection(); try { String tenantsRootDn = this.ensureTenantExists(connection, tenantName); deleteCertificateForTenant(tenantName, tenantsRootDn, connection, fingerprint, certType); } finally { connection.close(); } } private void deleteCertificateForTenant(String tenantName, String tenantsRootDn, ILdapConnectionEx connection, String fingerprint, CertificateType certType) throws Exception { if (certType == CertificateType.STS_TRUST_CERT) { deleteStsCertificateForTenant(tenantName, tenantsRootDn, connection, fingerprint); } else if (certType == CertificateType.LDAP_TRUSTED_CERT) { // for LDAP_TYPE only need delete the certificate object itself deleteSingleCertForTenant(tenantName, tenantsRootDn, connection, fingerprint, CertificateType.LDAP_TRUSTED_CERT, false); } } // Only delete the certificate itself private void deleteSingleCertForTenant(String tenantName, String tenantsRootDn, ILdapConnectionEx connection, String fingerprint, CertificateType certType, boolean isCertExistInCertChains) throws NoSuchCertificateException { String idmCertificatesContainerDn = DirectoryConfigStore.ensureObjectExists(connection, tenantsRootDn, ContainerLdapObject.getInstance(), ContainerLdapObject.CONTAINER_IDM_CERTIFICATES, false); if (ServerUtils.isNullOrEmpty(idmCertificatesContainerDn) == true) { if (!isCertExistInCertChains) { throw new NoSuchCertificateException(String.format( "deleteCertificate failed - NO such certificate of type %s" + "found in tenant %s", certType.toString(), tenantName)); } else { return; } } IdmCertificateLdapObject idmCertObject = IdmCertificateLdapObject.getInstance(); String certTypeFilter = String.format("(%s=%s)", IdmCertificateLdapObject.PROPERTY_CERT_TYPE, // attribute name LdapFilterString.encode(certType.toString())); String idmCertificateDn = idmCertObject.lookupObject(connection, idmCertificatesContainerDn, LdapScope.SCOPE_ONE_LEVEL, fingerprint, certTypeFilter); if (ServerUtils.isNullOrEmpty(idmCertificateDn) == true) { if (!isCertExistInCertChains) { throw new NoSuchCertificateException(String.format( "deleteCertificate failed - NO such certificate of type %s" + "found in tenant %s", certType.toString(), tenantName)); } } else { idmCertObject.deleteObject(connection, idmCertificateDn); } } private void deleteStsCertificateForTenant(String tenantName, String tenantsRootDn, ILdapConnectionEx connection, String fingerprint) throws Exception { String tenantsCertChainRootDn = tenantsRootDn; // Trusted Cert chains are always stored under Services Dn.So need to make sure // it always get Certchains from there for both system and non-system tenants. if (tenantsRootDn.equalsIgnoreCase(this.getSystemTenantCredsDn())) { tenantsCertChainRootDn = this.ensureTenantExists(connection, tenantName); } // (1) Check whether this certificate belongs to an active signer certChain // (root or leaf of the signing certificate chain) boolean isCertExistInCertChains = false; List<Certificate> activeCerts = this.getTenantCertificateForTenant(tenantName, tenantsCertChainRootDn, connection); if (activeCerts != null && !activeCerts.isEmpty()) { IdmCertificate idmRootCert = new IdmCertificate((X509Certificate) getRootCert(activeCerts), CertificateType.STS_TRUST_CERT); if (idmRootCert.getFingerprint().equals(fingerprint)) { throw new CertificateInUseException( String.format("deleteCertificate failed - certificate is the root of" + "the active signer Identity in tenant %s", tenantName), idmRootCert.getCertificate()); } else { IdmCertificate idmLeafCert = new IdmCertificate((X509Certificate) getLeafCert(activeCerts), CertificateType.STS_TRUST_CERT); if (idmLeafCert.getFingerprint().equals(fingerprint)) { throw new CertificateInUseException( String.format("deleteCertificate failed - certificate is the root of" + "the active signer Identity in tenant %s", tenantName), idmLeafCert.getCertificate()); } } } // (2) Walk through all the trusted certificateChains // to delete the ones whose root is this particular certificate Collection<List<Certificate>> certChains = this.getTenantCertificatesForTenant(tenantName, tenantsCertChainRootDn, connection); List<Certificate> candidateRootCerts = new ArrayList<Certificate>(); for (List<Certificate> certChain : certChains) { if (certChain == null || certChain.isEmpty()) continue; X509Certificate rootCert = (X509Certificate) getRootCert(certChain); if (CertificateUtil.generateFingerprint(rootCert).equals(fingerprint)) { isCertExistInCertChains = true; for (int i = 0; i < certChain.size() - 1; i++) { // save certs (but not the root itseft) // as potential candidateRootCerts for step (3) to consume candidateRootCerts.add(certChain.get(i)); } // remove the trustedCertificateChain and possible signer Identity if there is one // since its root will be deleted. deleteTenantTrustedCertificateChainForTenant(tenantName, tenantsCertChainRootDn, connection, certChain); deleteTenantCredentialsForTenant(tenantName, tenantsCertChainRootDn, connection, certChain); } else { X509Certificate leafCert = (X509Certificate) getLeafCert(certChain); if (CertificateUtil.generateFingerprint(leafCert).equals(fingerprint)) { isCertExistInCertChains = true; // remove the trustedCertificateChain and possible signer Identity if there is one // since its leaf will be deleted. deleteTenantTrustedCertificateChainForTenant(tenantName, tenantsCertChainRootDn, connection, certChain); deleteTenantCredentialsForTenant(tenantName, tenantsCertChainRootDn, connection, certChain); } } } // (3) Walk through the rest of trusted root STS certificates // to retrieve any certificate that is issued by this particular certificate // those certificate should be deleted since its issuer has been removed Collection<Certificate> trustedRootCerts = this.getTrustedCertificatesForTenant(tenantName, tenantsCertChainRootDn, connection); for (Certificate cert : trustedRootCerts) { // Check to see whether cert is issued by 'certificate' // (make sure 'cert' is not rootCertToDelete itself) if (cert != null && !CertificateUtil.generateFingerprint((X509Certificate) cert).equals(fingerprint) && isIssuedByCert(candidateRootCerts, (X509Certificate) cert)) { deleteCertificateForTenant(tenantName, tenantsRootDn, connection, CertificateUtil.generateFingerprint((X509Certificate) cert), CertificateType.STS_TRUST_CERT); } } // (4) remove the certificate itself if it also lives under 'IdmCertificates' container deleteSingleCertForTenant(tenantName, tenantsRootDn, connection, fingerprint, CertificateType.STS_TRUST_CERT, isCertExistInCertChains); } @Override public void addRelyingParty(String tenantName, RelyingParty rp) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateNotNull(rp, "rp"); ValidateUtil.validateNotEmpty(rp.getName(), "rp.getName()"); ILdapConnectionEx connection = this.getConnection(); try { String tenantsRootDn = this.ensureTenantExists(connection, tenantName); ContainerLdapObject relyingPartiesContainer = ContainerLdapObject.getInstance(); String relyingPartiesContainerDn = DirectoryConfigStore.ensureObjectExists(connection, tenantsRootDn, relyingPartiesContainer, ContainerLdapObject.CONTAINER_RELYING_PARTIES, true); RelyingPartyLdapObject relyingPartyConfig = RelyingPartyLdapObject.getInstance(); String relyingPartyDn = relyingPartyConfig.getDnFromObject(relyingPartiesContainerDn, rp); relyingPartyConfig.createObject(connection, relyingPartyDn, rp); DirectoryConfigStore.saveRelyingPartyAssertionConsumerServices(connection, relyingPartyDn, rp.getAssertionConsumerServices()); DirectoryConfigStore.saveRelyingPartyAttributeConsumerServices(connection, relyingPartyDn, rp.getAttributeConsumerServices()); DirectoryConfigStore.saveRelyingPartySingleLogoutServices(connection, relyingPartyDn, rp.getSingleLogoutServices()); DirectoryConfigStore.saveRelyingPartySignatureAlgorithms(connection, relyingPartyDn, rp.getSignatureAlgorithms()); } finally { connection.close(); } } @Override public void deleteRelyingParty(String tenantName, String rpName) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateNotEmpty(rpName, "rpName"); ILdapConnectionEx connection = this.getConnection(); try { String tenantsRootDn = this.ensureTenantExists(connection, tenantName); ContainerLdapObject relyingPartiesContainer = ContainerLdapObject.getInstance(); String relyingPartiesContainerDn = DirectoryConfigStore.ensureObjectExists(connection, tenantsRootDn, relyingPartiesContainer, ContainerLdapObject.CONTAINER_RELYING_PARTIES, false); if (ServerUtils.isNullOrEmpty(relyingPartiesContainerDn) == false) { RelyingPartyLdapObject relyingPartyConfig = RelyingPartyLdapObject.getInstance(); String relyingPartyDn = relyingPartyConfig.lookupObject(connection, relyingPartiesContainerDn, LdapScope.SCOPE_ONE_LEVEL, rpName); if (ServerUtils.isNullOrEmpty(relyingPartyDn) == false) { relyingPartyConfig.deleteObject(connection, relyingPartyDn); } else { throw new NoSuchRelyingPartyException( String.format("The relying party %s does not exist", rpName)); } } } finally { connection.close(); } } @Override public RelyingParty getRelyingParty(String tenantName, String rpName) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateNotEmpty(rpName, "rpName"); ILdapConnectionEx connection = this.getConnection(); try { String tenantsRootDn = this.ensureTenantExists(connection, tenantName); RelyingParty relyingParty = null; ContainerLdapObject relyingPartiesContainer = ContainerLdapObject.getInstance(); String relyingPartiesContainerDn = DirectoryConfigStore.ensureObjectExists(connection, tenantsRootDn, relyingPartiesContainer, ContainerLdapObject.CONTAINER_RELYING_PARTIES, false); if (ServerUtils.isNullOrEmpty(relyingPartiesContainerDn) == false) { RelyingPartyLdapObject relyingPartyConfig = RelyingPartyLdapObject.getInstance(); relyingParty = relyingPartyConfig.retrieveObject(connection, relyingPartiesContainerDn, LdapScope.SCOPE_ONE_LEVEL, rpName); if (relyingParty != null) { String relyingPartyDn = relyingPartyConfig.getDnFromObject(relyingPartiesContainerDn, relyingParty); relyingParty.setAssertionConsumerServices(DirectoryConfigStore .retrieveRelyingPartyAssertionConsumerServices(connection, relyingPartyDn)); relyingParty.setAttributeConsumerServices(DirectoryConfigStore .retrieveRelyingPartyAttributeConsumerServices(connection, relyingPartyDn)); relyingParty.setSingleLogoutServices(DirectoryConfigStore .retrieveRelyingPartySingleLogoutServices(connection, relyingPartyDn)); relyingParty.setSignatureAlgorithms(DirectoryConfigStore .retrieveRelyingPartySignatureAlgorithms(connection, relyingPartyDn)); } } return relyingParty; } finally { connection.close(); } } @Override public RelyingParty getRelyingPartyByUrl(String tenantName, String url) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateNotEmpty(url, "url"); ILdapConnectionEx connection = this.getConnection(); try { RelyingPartyLdapObject relyingPartyConfig = RelyingPartyLdapObject.getInstance(); String urlFilter = relyingPartyConfig.getInSetSearchFilter(RelyingPartyLdapObject.PROPERTY_URL, new String[] { url }); RelyingParty relyingParty = null; Collection<RelyingParty> relyingParties = DirectoryConfigStore.getRelyingParties(this, connection, tenantName, urlFilter); if (relyingParties.size() > 0) { // maybe we should throw when found > 1? // [current code returns 1st instance, so keeping in sync] relyingParty = relyingParties.iterator().next(); } return relyingParty; } finally { connection.close(); } } @Override public void setRelyingParty(String tenantName, RelyingParty rp) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateNotNull(rp, "rp"); ValidateUtil.validateNotEmpty(rp.getName(), "rp.getName()"); // future - consider reconciling properties instead of delete/add this.deleteRelyingParty(tenantName, rp.getName()); this.addRelyingParty(tenantName, rp); } @Override public Collection<RelyingParty> getRelyingParties(String tenantName) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ILdapConnectionEx connection = this.getConnection(); try { return DirectoryConfigStore.getRelyingParties(this, connection, tenantName, null); } finally { connection.close(); } } @Override public void addOIDCClient(String tenantName, OIDCClient oidcClient) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateNotNull(oidcClient, "oidcClient"); ILdapConnectionEx connection = this.getConnection(); try { String tenantsRootDn = this.ensureTenantExists(connection, tenantName); ContainerLdapObject oidcClientsContainer = ContainerLdapObject.getInstance(); String oidcClientsContainerDn = DirectoryConfigStore.ensureObjectExists(connection, tenantsRootDn, oidcClientsContainer, ContainerLdapObject.CONTAINER_OIDC_CLIENTS, true); OIDCClientLdapObject oidcClientLdapObject = OIDCClientLdapObject.getInstance(); List<String> uriStrings = oidcClient.getRedirectUris(); String[] uris = uriStrings.toArray(new String[uriStrings.size()]); String urisFilter = oidcClientLdapObject .getInSetSearchFilter(OIDCClientLdapObject.PROPERTY_OIDC_REDIRECT_URIS, uris); uriStrings = oidcClient.getPostLogoutRedirectUris(); if (uriStrings != null && uriStrings.size() > 0) { uris = uriStrings.toArray(new String[uriStrings.size()]); urisFilter = String.format("(|%s%s)", urisFilter, oidcClientLdapObject .getInSetSearchFilter(OIDCClientLdapObject.PROPERTY_OIDC_POST_LOGOUT_REDIRECT_URI, uris)); } Collection<OIDCClient> oidcClients = DirectoryConfigStore.getOIDCClients(this, connection, tenantName, urisFilter); if (!oidcClients.isEmpty()) { throw new DuplicatedOIDCRedirectURLException( String.format("At least one of the OIDC client redirect URI: %s is already registered.", Arrays.toString(uris))); } String oidcClientDn = oidcClientLdapObject.getDnFromObject(oidcClientsContainerDn, oidcClient); oidcClientLdapObject.createObject(connection, oidcClientDn, oidcClient); } finally { connection.close(); } } @Override public void deleteOIDCClient(String tenantName, String clientID) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateNotEmpty(clientID, "clientID"); ILdapConnectionEx connection = this.getConnection(); try { boolean found = false; String tenantsRootDn = this.ensureTenantExists(connection, tenantName); ContainerLdapObject oidcClientsContainer = ContainerLdapObject.getInstance(); String oidcClientsContainerDn = DirectoryConfigStore.ensureObjectExists(connection, tenantsRootDn, oidcClientsContainer, ContainerLdapObject.CONTAINER_OIDC_CLIENTS, false); if (ServerUtils.isNullOrEmpty(oidcClientsContainerDn) == false) { OIDCClientLdapObject oidcClientLdapObject = OIDCClientLdapObject.getInstance(); String oidcClientDn = oidcClientLdapObject.lookupObject(connection, oidcClientsContainerDn, LdapScope.SCOPE_ONE_LEVEL, clientID); if (ServerUtils.isNullOrEmpty(oidcClientDn) == false) { found = true; oidcClientLdapObject.deleteObject(connection, oidcClientDn); } } if (!found) { throw new NoSuchOIDCClientException( String.format("The OIDC client %s does not exist on tenant %s", clientID, tenantName)); } } finally { connection.close(); } } @Override public OIDCClient getOIDCClient(String tenantName, String clientID) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateNotEmpty(clientID, "clientID"); ILdapConnectionEx connection = this.getConnection(); try { String tenantsRootDn = this.ensureTenantExists(connection, tenantName); OIDCClient oidcClient = null; ContainerLdapObject oidcClientsContainer = ContainerLdapObject.getInstance(); String oidcClientsContainerDn = DirectoryConfigStore.ensureObjectExists(connection, tenantsRootDn, oidcClientsContainer, ContainerLdapObject.CONTAINER_OIDC_CLIENTS, false); if (ServerUtils.isNullOrEmpty(oidcClientsContainerDn) == false) { OIDCClientLdapObject oidcClientLdapObject = OIDCClientLdapObject.getInstance(); oidcClient = oidcClientLdapObject.retrieveObject(connection, oidcClientsContainerDn, LdapScope.SCOPE_ONE_LEVEL, clientID); } // throw NoSuchOIDCClientException if no client is found if (oidcClient == null) { throw new NoSuchOIDCClientException( String.format("The OIDC client %s does not exist on tenant %s", clientID, tenantName)); } return oidcClient; } finally { connection.close(); } } @Override public void setOIDCClient(String tenantName, OIDCClient oidcClient) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateNotNull(oidcClient, "oidcClient"); String clientId = oidcClient.getClientId(); ValidateUtil.validateNotEmpty(clientId, "clientId"); this.deleteOIDCClient(tenantName, clientId); this.addOIDCClient(tenantName, oidcClient); } @Override public Collection<OIDCClient> getOIDCClients(String tenantName) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ILdapConnectionEx connection = this.getConnection(); try { return DirectoryConfigStore.getOIDCClients(this, connection, tenantName, null); } finally { connection.close(); } } @Override public void addResourceServer(String tenantName, ResourceServer resourceServer) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateNotNull(resourceServer, "resourceServer"); try (ILdapConnectionEx connection = this.getConnection()) { String tenantsRootDn = this.ensureTenantExists(connection, tenantName); ContainerLdapObject resourceServersContainer = ContainerLdapObject.getInstance(); String resourceServersContainerDn = DirectoryConfigStore.ensureObjectExists(connection, tenantsRootDn, resourceServersContainer, ContainerLdapObject.CONTAINER_RESOURCE_SERVERS, true /* createIfNotExists */); ResourceServerLdapObject resourceServerLdapObject = ResourceServerLdapObject.getInstance(); String resourceServerDn = resourceServerLdapObject.getDnFromObject(resourceServersContainerDn, resourceServer); resourceServerLdapObject.createObject(connection, resourceServerDn, resourceServer); } } @Override public void deleteResourceServer(String tenantName, String resourceServerName) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateNotEmpty(resourceServerName, "resourceServerName"); try (ILdapConnectionEx connection = this.getConnection()) { boolean found = false; String tenantsRootDn = this.ensureTenantExists(connection, tenantName); ContainerLdapObject resourceServersContainer = ContainerLdapObject.getInstance(); String resourceServersContainerDn = DirectoryConfigStore.ensureObjectExists(connection, tenantsRootDn, resourceServersContainer, ContainerLdapObject.CONTAINER_RESOURCE_SERVERS, false /* createIfNotExists */); if (!ServerUtils.isNullOrEmpty(resourceServersContainerDn)) { ResourceServerLdapObject resourceServerLdapObject = ResourceServerLdapObject.getInstance(); String resourceServerDn = resourceServerLdapObject.lookupObject(connection, resourceServersContainerDn, LdapScope.SCOPE_ONE_LEVEL, resourceServerName); if (!ServerUtils.isNullOrEmpty(resourceServerDn)) { found = true; resourceServerLdapObject.deleteObject(connection, resourceServerDn); } } if (!found) { throw new NoSuchResourceServerException(String.format( "The resource server %s does not exist on tenant %s", resourceServerName, tenantName)); } } } @Override public ResourceServer getResourceServer(String tenantName, String resourceServerName) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateNotEmpty(resourceServerName, "resourceServerName"); try (ILdapConnectionEx connection = this.getConnection()) { String tenantsRootDn = this.ensureTenantExists(connection, tenantName); ContainerLdapObject resourceServersContainer = ContainerLdapObject.getInstance(); String resourceServersContainerDn = DirectoryConfigStore.ensureObjectExists(connection, tenantsRootDn, resourceServersContainer, ContainerLdapObject.CONTAINER_RESOURCE_SERVERS, false /* createIfNotExists */); ResourceServer resourceServer = null; if (!ServerUtils.isNullOrEmpty(resourceServersContainerDn)) { ResourceServerLdapObject resourceServerLdapObject = ResourceServerLdapObject.getInstance(); resourceServer = resourceServerLdapObject.retrieveObject(connection, resourceServersContainerDn, LdapScope.SCOPE_ONE_LEVEL, resourceServerName); } if (resourceServer == null) { throw new NoSuchResourceServerException(String.format( "The resource server %s does not exist on tenant %s", resourceServerName, tenantName)); } return resourceServer; } } @Override public void setResourceServer(String tenantName, ResourceServer resourceServer) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateNotNull(resourceServer, "resourceServer"); this.deleteResourceServer(tenantName, resourceServer.getName()); this.addResourceServer(tenantName, resourceServer); } @Override public Collection<ResourceServer> getResourceServers(String tenantName) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); try (ILdapConnectionEx connection = this.getConnection()) { Collection<ResourceServer> resourceServers; String tenantsRootDn = this.ensureTenantExists(connection, tenantName); resourceServers = DirectoryConfigStore.retrieveObjectsCollection(connection, tenantsRootDn, ContainerLdapObject.CONTAINER_RESOURCE_SERVERS, null /* additionalFilter */, ResourceServerLdapObject.getInstance(), null /* callback */); return resourceServers; } } // Helper function for getOIDCClients method private static Collection<OIDCClient> getOIDCClients(DirectoryConfigStore directoryConfigStore, ILdapConnectionEx connection, String tenantName, String propertyFilter) { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); String tenantsRootDn = directoryConfigStore.ensureTenantExists(connection, tenantName); Collection<OIDCClient> oidcClients = retrieveObjectsCollection(connection, tenantsRootDn, ContainerLdapObject.CONTAINER_OIDC_CLIENTS, propertyFilter, OIDCClientLdapObject.getInstance(), null); return oidcClients; } @Override public void addProvider(String tenantName, IIdentityStoreData idsData) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateNotNull(idsData, "idsData"); ValidateUtil.validateNotEmpty(idsData.getName(), "idsData.getName()"); ILdapConnectionEx connection = this.getConnection(); try { Tenant tenant = this.getTenant(connection, tenantName); String tenantsRootDn = this.ensureTenantExists(connection, tenantName); if (idsData.getDomainType() == DomainType.LOCAL_OS_DOMAIN) { // as of now the decision is that we only allow this for default tenant. // we still have an issue of what if default tenant is re-set, but this // needs to be covered by the general decision about the default tenant... String defaultTenant = this.getDefaultTenant(); if (tenantName.equalsIgnoreCase(defaultTenant) == false) { throw new RuntimeException("LocalOS domain type is only supported for a default tenant."); } Collection<IIdentityStoreData> providers = getProviders(tenantName, EnumSet.of(DomainType.LOCAL_OS_DOMAIN), true); if (providers.size() > 0) { throw new LocalISRegistrationException( String.format("Identity Provider '%s' with domain type LocalOSDomain, already exists.", providers.iterator().next().getName())); } idsData = getLocalOsDomainIdentityStoreData(idsData); } else if (idsData.getDomainType() == DomainType.SYSTEM_DOMAIN) { throw new RuntimeException("IdentityProvider for system domain cannot be added/modified."); } else if (idsData.getDomainType() == DomainType.EXTERNAL_DOMAIN) { ValidateUtil.validateNotNull(idsData.getExtendedIdentityStoreData(), "idsData.getExtendedIdentityStoreData()"); ValidateUtil.validateNotNull(idsData.getExtendedIdentityStoreData().getConnectionStrings(), "idsData.getExtendedIdentityStoreData().getConnectionStrings()"); // No connection string is stored for native AD if (idsData.getExtendedIdentityStoreData() .getProviderType() != IdentityStoreType.IDENTITY_STORE_TYPE_ACTIVE_DIRECTORY && idsData.getExtendedIdentityStoreData().getConnectionStrings().size() < 1) { throw new IllegalArgumentException("There must be at least 1 connection string provided."); } for (String str : idsData.getExtendedIdentityStoreData().getConnectionStrings()) { ValidateUtil.validateNotEmpty(str, "connectionString"); } if (false == validateExternalProviderNameConflict(tenantName, idsData)) { throw new DuplicateProviderException(idsData.getName(), idsData.getExtendedIdentityStoreData().getAlias()); } } else { throw new IllegalArgumentException( String.format("Unsupported domain type '%s'.", idsData.getDomainType().toString())); } enCryptPassword(tenant._tenantKey, idsData.getExtendedIdentityStoreData()); DirectoryConfigStore.SaveIdentityProviderConfig(this, connection, tenantsRootDn, idsData); } finally { connection.close(); } } @Override public void registerExternalIdpConfig(String tenantName, IDPConfig idpConfig) throws Exception { //validation has been done on IIdentityManager ILdapConnectionEx connection = getConnection(); String tenantRootDn = lookupTenantsRootDn(connection, tenantName); if (tenantRootDn == null) { throw new NoSuchTenantException(String.format("Tenant [%s] not found", tenantName)); } String externalIDPConfigsContainerDn = DirectoryConfigStore.ensureObjectExists(connection, tenantRootDn, ContainerLdapObject.getInstance(), ContainerLdapObject.CONTAINER_EXTERNAL_IDP_CONFIGS, true); IDPConfigLdapObject ldapObj = IDPConfigLdapObject.getInstance(); String ldapObjDN = ldapObj.getDnFromObject(externalIDPConfigsContainerDn, idpConfig); boolean ldapObjectExists = true; try { ldapObj.lookupObject(connection, ldapObjDN, LdapScope.SCOPE_BASE, null); } catch (NoSuchObjectLdapException nsole) { ldapObjectExists = false; } try { if (ldapObjectExists) {// delete existing object first before setting the new configuration ldapObj.deleteObject(connection, ldapObjDN); } ldapObj.createObject(connection, ldapObjDN, idpConfig); //populate all the subordinate containers saveObjectsCollection(connection, ldapObjDN, ContainerLdapObject.CONTAINER_EXTERNAL_IDP_SSO_SERVICES, SingleSignOnServiceLdapObject.getInstance(), idpConfig.getSsoServices(), null); saveObjectsCollection(connection, ldapObjDN, ContainerLdapObject.CONTAINER_EXTERNAL_IDP_SLO_SERVICES, SingleLogoutServiceLdapObject.getInstance(), idpConfig.getSloServices(), null); TenantTrustedCertificateChain certChain = new TenantTrustedCertificateChain("TrustedCertChain", new ArrayList<Certificate>(idpConfig.getSigningCertificateChain())); //For now, only one trusted certificate chain in this container. Collection<TenantTrustedCertificateChain> chains = Arrays.asList(certChain); saveObjectsCollection(connection, ldapObjDN, ContainerLdapObject.CONTAINER_EXTERNAL_IDP_CERTIFICATE_CHAINS, TenantTrustedCertChainLdapObject.getInstance(), chains, null); Collection<AttributeMapping> attributeMappings = new ArrayList<AttributeMapping>(); if (idpConfig.getSubjectFormatMappings() != null) { int i = 0; for (AttributeConfig config : idpConfig.getSubjectFormatMappings()) { attributeMappings.add( new AttributeMapping(config.getTokenSubjectFormat(), config.getStoreAttribute(), i++)); } } saveObjectsCollection(connection, ldapObjDN, ContainerLdapObject.CONTAINER_EXTERNAL_IDP_SUBJECT_FORMAT_MAPPINGS, AttributeMappingLdapObject.getInstance(), attributeMappings, null); attributeMappings = new ArrayList<AttributeMapping>(); if (idpConfig.getTokenClaimGroupMappings() != null) { int i = 0; for (TokenClaimAttribute tokenClaimAttr : idpConfig.getTokenClaimGroupMappings().keySet()) { for (String group : idpConfig.getTokenClaimGroupMappings().get(tokenClaimAttr)) { attributeMappings.add(new AttributeMapping(tokenClaimAttr.getClaimName() + CLAIM_GROUP_DELIMITER + tokenClaimAttr.getClaimValue(), group, i++)); } } } saveObjectsCollection(connection, ldapObjDN, ContainerLdapObject.CONTAINER_EXTERNAL_IDP_GROUP_ATTRIBUTE_MAPPINGS, AttributeMappingLdapObject.getInstance(), attributeMappings, null); } finally { connection.close(); } } /* (non-Javadoc) * @see com.vmware.identity.idm.server.config.IConfigStore#removeIdpConfig(java.lang.String, java.lang.String) */ @Override public void removeExternalIdpConfig(String tenantName, String configEntityId) throws Exception { //validation has been done on IIdentityManager ILdapConnectionEx connection = getConnection(); try { String tenantRootDn = lookupTenantsRootDn(connection, tenantName); if (tenantRootDn == null) { throw new NoSuchTenantException(String.format("Tenant [%s] not found", tenantName)); } String externalIDPConfigsContainerDn = DirectoryConfigStore.ensureObjectExists(connection, tenantRootDn, ContainerLdapObject.getInstance(), ContainerLdapObject.CONTAINER_EXTERNAL_IDP_CONFIGS, true); IDPConfigLdapObject ldapObj = IDPConfigLdapObject.getInstance(); String ldapObjDN = String.format("cn=%s, %s", configEntityId, externalIDPConfigsContainerDn); // check whether the configuration already exists. ldapObjDN = ldapObj.lookupObject(connection, ldapObjDN, LdapScope.SCOPE_BASE, null); ldapObj.deleteObject(connection, ldapObjDN); } catch (NoSuchObjectLdapException nsole) { throw new NoSuchExternalIdpConfigException(String.format( "External IDP config [%s] does not exist for tenant [%s]", configEntityId, tenantName), nsole); } finally { connection.close(); } } @Override public Collection<IDPConfig> getExternalIDPConfigs(String tenantName) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ILdapConnectionEx connection = getConnection(); Collection<IDPConfig> idpConfigs = null; try { String tenantConfigDN = lookupTenantsRootDn(connection, tenantName); if (StringUtils.isEmpty(tenantConfigDN)) { throw new NoSuchTenantException(String.format("tenant [%s] doesnot exist", tenantName)); } idpConfigs = retrieveObjectsCollection(connection, tenantConfigDN, ContainerLdapObject.CONTAINER_EXTERNAL_IDP_CONFIGS, null, IDPConfigLdapObject.getInstance(), new IObjectProcessedCallback<IDPConfig>() { @Override public void processObjectSaved(ILdapConnectionEx connection, String idpConfigDN, IDPConfig idpConfig) { idpConfig.setSsoServices(retrieveObjectsCollection(connection, idpConfigDN, ContainerLdapObject.CONTAINER_EXTERNAL_IDP_SSO_SERVICES, SingleSignOnServiceLdapObject.getInstance(), null)); idpConfig.setSloServices(retrieveObjectsCollection(connection, idpConfigDN, ContainerLdapObject.CONTAINER_EXTERNAL_IDP_SLO_SERVICES, SingleLogoutServiceLdapObject.getInstance(), null)); try { idpConfig.setSigningCertificateChain( retrieveExternalIDPConfigSigningCertificates(connection, idpConfigDN)); } catch (IDMException ie) { String message = "Signing certifiate chain retrieved from directory store" + "is invalid, most likely certs are out of required order" + "(user first, root cast last)"; logger.error(message); throw new IllegalStateException(message); } AttributeConfig[] subjectFormatMappings = retrieveSubjectFormatMap(connection, idpConfigDN); Map<TokenClaimAttribute, List<String>> tokenClaimGroupMappings = retrieveClaimGroupMap( connection, idpConfigDN); //imported null attributeConfig[] will be exported as empty attributeConfig[] assert (subjectFormatMappings != null); assert (tokenClaimGroupMappings != null); idpConfig.setSubjectFormatMappings(subjectFormatMappings); idpConfig.setTokenClaimGroupMappings(tokenClaimGroupMappings); LdapValue[] alias = IDPConfigLdapObject.getInstance().getObjectProperty(connection, idpConfigDN, LdapScope.SCOPE_BASE, null, IDPConfigLdapObject.PROPERTY_ALIAS); idpConfig.setAlias(ServerUtils.getStringValue(alias)); } }); } finally { connection.close(); } return idpConfigs; } private List<X509Certificate> retrieveExternalIDPConfigSigningCertificates(ILdapConnectionEx connection, String idpConfigDN) { Collection<TenantTrustedCertificateChain> chains = retrieveObjectsCollection(connection, idpConfigDN, ContainerLdapObject.CONTAINER_EXTERNAL_IDP_CERTIFICATE_CHAINS, TenantTrustedCertChainLdapObject.getInstance(), null); assert (chains.size() == 1); List<X509Certificate> x509Certs = new ArrayList<X509Certificate>(); for (Certificate cert : chains.iterator().next().getCertificateChain()) { x509Certs.add((X509Certificate) cert); } return x509Certs; } private AttributeConfig[] retrieveSubjectFormatMap(ILdapConnectionEx connection, String idpConfigDN) { Collection<AttributeMapping> mappings = retrieveObjectsCollection(connection, idpConfigDN, ContainerLdapObject.CONTAINER_EXTERNAL_IDP_SUBJECT_FORMAT_MAPPINGS, AttributeMappingLdapObject.getInstance(), null); List<AttributeConfig> configs = new ArrayList<AttributeConfig>(); for (AttributeMapping mapping : mappings) { configs.add(new AttributeConfig(mapping.getAttributeFrom(), mapping.getAttributeTo())); } return configs.toArray(new AttributeConfig[configs.size()]); } private Map<TokenClaimAttribute, List<String>> retrieveClaimGroupMap(ILdapConnectionEx connection, String idpConfigDN) { Collection<AttributeMapping> attMappings = retrieveObjectsCollection(connection, idpConfigDN, ContainerLdapObject.CONTAINER_EXTERNAL_IDP_GROUP_ATTRIBUTE_MAPPINGS, AttributeMappingLdapObject.getInstance(), null); Map<TokenClaimAttribute, List<String>> tokenClaimMappings = new HashMap<>(); for (AttributeMapping mapping : attMappings) { String claimStr = mapping.getAttributeFrom(); int pos = claimStr.indexOf("#"); if (pos < 0) { throw new IllegalStateException( "Retrieved an invaid claim from internal identity store: " + claimStr); } String claimName = claimStr.substring(0, pos); String claimValue = claimStr.substring(pos + 1); TokenClaimAttribute tokenClaim = new TokenClaimAttribute(claimName, claimValue); if (tokenClaimMappings.containsKey(tokenClaim)) { tokenClaimMappings.get(tokenClaim).add(mapping.getAttributeTo()); } else { List<String> groupList = new ArrayList<>(); groupList.add(mapping.getAttributeTo()); tokenClaimMappings.put(tokenClaim, groupList); } } return tokenClaimMappings; } private boolean validateExternalProviderNameConflict(String tenantName, IIdentityStoreData idsDataToAdd) throws Exception { Collection<IIdentityStoreData> providers = getProviders(tenantName, EnumSet.allOf(DomainType.class), true); // check with existing name/alias from existing providers for (IIdentityStoreData provider : providers) { String providerName = provider.getName(); assert (null != providerName); if (isDomainNameSame(idsDataToAdd, providerName) || isDomainAliasSame(idsDataToAdd, providerName)) { return false; } String providerAlias = provider.getExtendedIdentityStoreData().getAlias(); if (providerAlias != null && ((isDomainNameSame(idsDataToAdd, providerAlias)) || (isDomainAliasSame(idsDataToAdd, providerAlias)))) { return false; } } return true; } private boolean isDomainNameSame(IIdentityStoreData storeDataToAdd, String existingDomainName) { assert (null != existingDomainName); //specified domain name needs to fully match the real domain name return StringUtils.equalsIgnoreCase(storeDataToAdd.getName(), existingDomainName); } private boolean isDomainAliasSame(IIdentityStoreData storeDataToAdd, String existingDomainAlias) { assert (null != existingDomainAlias); return StringUtils.equalsIgnoreCase(storeDataToAdd.getExtendedIdentityStoreData().getAlias(), existingDomainAlias); } @Override public void deleteProvider(String tenantName, String providerName) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateNotEmpty(providerName, "providerName"); ILdapConnectionEx connection = this.getConnection(); try { String tenantsRootDn = this.ensureTenantExists(connection, tenantName); String identityProvidersContainerDn = DirectoryConfigStore.ensureObjectExists(connection, tenantsRootDn, ContainerLdapObject.getInstance(), ContainerLdapObject.CONTAINER_IDENTITY_PROVIDERS, false); if (ServerUtils.isNullOrEmpty(identityProvidersContainerDn) == false) { String aliasName = null; IdentityProviderLdapObject identityProviderConfigObject = IdentityProviderLdapObject.getInstance(); IdentityProviderAliasLdapObject identityProviderAliasConfigObject = IdentityProviderAliasLdapObject .getInstance(); String identityProviderDn = identityProviderConfigObject.lookupObject(connection, identityProvidersContainerDn, LdapScope.SCOPE_ONE_LEVEL, providerName); String aliasDn = null; if (ServerUtils.isNullOrEmpty(identityProviderDn) == true) { IdentityProviderAlias obj = identityProviderAliasConfigObject.retrieveObject(connection, identityProvidersContainerDn, LdapScope.SCOPE_ONE_LEVEL, providerName); if (obj != null) { aliasName = providerName; aliasDn = identityProviderAliasConfigObject.getDnFromObject(identityProvidersContainerDn, obj); identityProviderDn = obj.getProviderDn(); providerName = ServerUtils.getStringValue( identityProviderConfigObject.getObjectProperty(connection, identityProviderDn, LdapScope.SCOPE_BASE, null, IdentityProviderLdapObject.PROPERTY_NAME)); if (ServerUtils.isNullOrEmpty(providerName) == true) // not found { identityProviderDn = null; } } } else { aliasName = ServerUtils.getStringValue( identityProviderConfigObject.getObjectProperty(connection, identityProviderDn, LdapScope.SCOPE_BASE, null, IdentityProviderLdapObject.PROPERTY_ALIAS)); if (ServerUtils.isNullOrEmpty(aliasName) == false) { aliasDn = identityProviderAliasConfigObject.lookupObject(connection, identityProvidersContainerDn, LdapScope.SCOPE_ONE_LEVEL, aliasName); } } if (ServerUtils.isNullOrEmpty(aliasDn) == false) { identityProviderAliasConfigObject.deleteObject(connection, aliasDn); } if (ServerUtils.isNullOrEmpty(identityProviderDn) == false) { identityProviderConfigObject.deleteObject(connection, identityProviderDn); } // update default providers if needed String defaultProvider = ServerUtils.getStringValue(DirectoryConfigStore .getTenantProperty(connection, tenantsRootDn, TenantLdapObject.PROPERTY_DEFAULT_PROVIDER)); if (ServerUtils.isNullOrEmpty(defaultProvider) == false) { if ((defaultProvider.equalsIgnoreCase(providerName) == true) || (defaultProvider.equalsIgnoreCase(aliasName) == true)) { // remove default provider setting DirectoryConfigStore.setTenantProperty(connection, tenantsRootDn, TenantLdapObject.PROPERTY_DEFAULT_PROVIDER, null); } } } } finally { connection.close(); } } @Override public IIdentityStoreData getProvider(String tenantName, String providerName, boolean getInternalInfo) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateNotEmpty(providerName, "providerName"); ILdapConnectionEx connection = this.getConnection(); try { String tenantsRootDn = this.ensureTenantExists(connection, tenantName); Tenant tenant = this.getTenant(connection, tenantName); String identityProvidersContainerDn = DirectoryConfigStore.ensureObjectExists(connection, tenantsRootDn, ContainerLdapObject.getInstance(), ContainerLdapObject.CONTAINER_IDENTITY_PROVIDERS, false); IIdentityStoreData provider = null; if (ServerUtils.isNullOrEmpty(identityProvidersContainerDn) == false) { IdentityProviderLdapObject identityProviderConfigObject = IdentityProviderLdapObject.getInstance(); IdentityProviderAliasLdapObject identityProviderAliasConfigObject = IdentityProviderAliasLdapObject .getInstance(); String identityProviderDn = identityProviderConfigObject.lookupObject(connection, identityProvidersContainerDn, LdapScope.SCOPE_ONE_LEVEL, providerName); if (ServerUtils.isNullOrEmpty(identityProviderDn) == true) { IdentityProviderAlias identityProviderAlias = identityProviderAliasConfigObject.retrieveObject( connection, identityProvidersContainerDn, LdapScope.SCOPE_ONE_LEVEL, providerName); if (identityProviderAlias != null) { identityProviderDn = identityProviderAlias.getProviderDn(); providerName = ServerUtils.getStringValue( identityProviderConfigObject.getObjectProperty(connection, identityProviderDn, LdapScope.SCOPE_BASE, null, IdentityProviderLdapObject.PROPERTY_NAME)); } if (ServerUtils.isNullOrEmpty(providerName) == true) // not found { identityProviderDn = null; } } if (ServerUtils.isNullOrEmpty(identityProviderDn) == false) { IIdentityStoreData provObj = identityProviderConfigObject.retrieveObject(connection, identityProviderDn, LdapScope.SCOPE_BASE, null); CryptoAESE cryptoAES = new CryptoAESE(tenant._tenantKey); deCryptPassword(cryptoAES, provObj.getExtendedIdentityStoreData()); retrieveIdentityProviderAttributesMap(connection, identityProviderDn, provObj, getInternalInfo); retrieveIdentityProviderSchemaMapping(connection, identityProviderDn, provObj, getInternalInfo); provider = getIIdenttyStoreDataToReturn(provObj, getInternalInfo); } } return provider; } finally { connection.close(); } } @Override public void setProvider(String tenantName, IIdentityStoreData idsData) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateNotNull(idsData, "idsData"); ValidateUtil.validateNotEmpty(idsData.getName(), "idsData.getName()"); switch (idsData.getDomainType()) { case EXTERNAL_DOMAIN: // future - perform an update instead of add/remove Collection<String> defaultProviders = getDefaultProviders(tenantName); this.deleteProvider(tenantName, idsData.getName()); this.addProvider(tenantName, idsData); if ((defaultProviders.size() == 1) && (defaultProviders.contains(idsData.getName()))) { setDefaultProviders(tenantName, defaultProviders); } break; case SYSTEM_DOMAIN: if (!(idsData instanceof ServerIdentityStoreData)) { throw new IllegalArgumentException(String.format("Error : expected parameter %s. Found %s", ServerIdentityStoreData.class, idsData.getClass())); } updateSystemDomain(tenantName, (ServerIdentityStoreData) idsData); break; default: throw new IllegalArgumentException( String.format("Provider '%s' with Domain type '%s' cannot be updated.", idsData.getName(), idsData.getDomainType().toString())); } } @Override public Collection<IIdentityStoreData> getProviders(String tenantName, EnumSet<DomainType> domainTypes, boolean getInternalInfo) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateNotNull(domainTypes, "domainTypes"); ILdapConnectionEx connection = this.getConnection(); try { String tenantsRootDn = this.ensureTenantExists(connection, tenantName); Tenant tenant = this.getTenant(connection, tenantName); Collection<IIdentityStoreData> providers = new ArrayList<IIdentityStoreData>(); if (domainTypes.size() > 0) { IdentityProviderLdapObject identityProviderConfig = IdentityProviderLdapObject.getInstance(); String domainTypeFilter = null; if (domainTypes.size() < DomainType.values().length) { String[] domainTypesStr = null; domainTypesStr = new String[domainTypes.size()]; int i = 0; for (DomainType type : domainTypes) { domainTypesStr[i] = type.toString(); i++; } domainTypeFilter = identityProviderConfig .getInSetSearchFilter(IdentityProviderLdapObject.PROPERTY_DOMAIN_TYPE, domainTypesStr); } final boolean retrieveInternalInfo = getInternalInfo; Collection<IIdentityStoreData> providersList = retrieveObjectsCollection(connection, tenantsRootDn, ContainerLdapObject.CONTAINER_IDENTITY_PROVIDERS, domainTypeFilter, identityProviderConfig, new IObjectProcessedCallback<IIdentityStoreData>() { @Override public void processObjectSaved(ILdapConnectionEx connection, String objectDn, IIdentityStoreData object) { retrieveIdentityProviderAttributesMap(connection, objectDn, object, retrieveInternalInfo); retrieveIdentityProviderSchemaMapping(connection, objectDn, object, retrieveInternalInfo); } }); if ((providersList != null) && (providersList.size() > 0)) { if (getInternalInfo == false) { // convert to external info for (IIdentityStoreData provider : providersList) { providers.add(getIIdenttyStoreDataToReturn(provider, getInternalInfo)); } } else { providers = providersList; } } } if (providers != null) { CryptoAESE cryptoAES = new CryptoAESE(tenant._tenantKey); for (IIdentityStoreData provider : providers) { deCryptPassword(cryptoAES, provider.getExtendedIdentityStoreData()); } } return providers; } finally { connection.close(); } } @Override public Collection<String> getDefaultProviders(String tenantName) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); Collection<String> result = new ArrayList<String>(); LdapValue[] value = this.getTenantProperty(tenantName, TenantLdapObject.PROPERTY_DEFAULT_PROVIDER); String defaultProvider = ServerUtils.getStringValue(value); if (ServerUtils.isNullOrEmpty(defaultProvider) == false) { result.add(defaultProvider); } return result; } @Override public void setDefaultProviders(String tenantName, Collection<String> defaultProviders) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); if ((defaultProviders != null) && (defaultProviders.size() > 1)) { throw new DuplicateProviderException("Only a single default provider is supported."); } ILdapConnectionEx connection = this.getConnection(); try { String defaultProvider = null; String tenantsRootDn = this.ensureTenantExists(connection, tenantName); String identityProvidersContainerDn = DirectoryConfigStore.ensureObjectExists(connection, tenantsRootDn, ContainerLdapObject.getInstance(), ContainerLdapObject.CONTAINER_IDENTITY_PROVIDERS, false); IdentityProviderLdapObject identityProviderConfigObject = IdentityProviderLdapObject.getInstance(); IdentityProviderAliasLdapObject identityProviderAliasConfigObject = IdentityProviderAliasLdapObject .getInstance(); if ((defaultProviders != null) && (defaultProviders.size() > 0)) { defaultProvider = defaultProviders.iterator().next(); if (ServerUtils.isNullOrEmpty(defaultProvider) == false) { String providerDn = null; if (ServerUtils.isNullOrEmpty(identityProvidersContainerDn) == false) { providerDn = identityProviderConfigObject.lookupObject(connection, identityProvidersContainerDn, LdapScope.SCOPE_ONE_LEVEL, defaultProvider); if (ServerUtils.isNullOrEmpty(providerDn)) { providerDn = identityProviderAliasConfigObject.lookupObject(connection, identityProvidersContainerDn, LdapScope.SCOPE_ONE_LEVEL, defaultProvider); } } if (ServerUtils.isNullOrEmpty(providerDn)) { throw new NoSuchIdpException( String.format("Identity Provider '%s' does not exist.", defaultProvider)); } } } LdapValue[] value = ServerUtils.getLdapValue(defaultProvider); DirectoryConfigStore.setTenantProperty(connection, tenantsRootDn, TenantLdapObject.PROPERTY_DEFAULT_PROVIDER, value); } finally { connection.close(); } } @Override public void setEntityID(String tenantName, String entityID) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); LdapValue[] value = ServerUtils.getLdapValue(entityID); this.setTenantProperty(tenantName, TenantLdapObject.PROPERTY_ENTITY_ID, value); } @Override public String getEntityID(String tenantName) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); LdapValue[] value = this.getTenantProperty(tenantName, TenantLdapObject.PROPERTY_ENTITY_ID); return ServerUtils.getStringValue(value); } @Override public boolean registerUpnSuffixForDomain(String tenantName, String domainName, String upnSuffix) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateNotEmpty(domainName, "domainName"); boolean added = false; ILdapConnectionEx connection = getConnection(); String tenantRootDn = lookupTenantsRootDn(connection, tenantName); assert (tenantRootDn != null);//tenant existence is validated by caller String identityProvidersContainerDn = DirectoryConfigStore.ensureObjectExists(connection, tenantRootDn, ContainerLdapObject.getInstance(), ContainerLdapObject.CONTAINER_IDENTITY_PROVIDERS, false); if (identityProvidersContainerDn == null) {//Idp not found -- if container does not exist String msg = String.format("IdentityProviders container does not exist for tenant [%s]", identityProvidersContainerDn); logger.error(msg); throw new NoSuchIdpException(msg); } String identityProviderDn = IdentityProviderLdapObject.getInstance().lookupObject(connection, identityProvidersContainerDn, LdapScope.SCOPE_ONE_LEVEL, domainName); if (identityProviderDn == null) { String msg = String.format("Idp [%s] does not exist under [%s]", domainName, identityProvidersContainerDn); logger.error(msg); throw new NoSuchIdpException(msg); } try { LdapMod mod[] = { new LdapMod(LdapModOperation.ADD, IdentityProviderLdapObject.PROPERTY_UPN_SUFFIXES, LdapValue.fromString(ValidateUtil.getCanonicalUpnSuffix(upnSuffix))) }; connection.modifyObject(identityProviderDn, mod); added = true; } catch (AttributeOrValueExistsLdapException e) { logger.info(String.format("upnSuffix [%s] is already registered for provider [%s]", upnSuffix, identityProviderDn)); added = false; } finally { connection.close(); } return added; } @Override public boolean unregisterUpnSuffixForDomain(String tenantName, String domainName, String upnSuffix) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateNotEmpty(domainName, "domainName"); boolean removed = false; ILdapConnectionEx connection = getConnection(); String tenantRootDn = lookupTenantsRootDn(connection, tenantName); assert (tenantRootDn != null);//tenant existence is validated by caller String identityProvidersContainerDn = DirectoryConfigStore.ensureObjectExists(connection, tenantRootDn, ContainerLdapObject.getInstance(), ContainerLdapObject.CONTAINER_IDENTITY_PROVIDERS, false); if (identityProvidersContainerDn == null) {//Idp not found -- if container does not exist String msg = String.format("IdentityProviders container does not exist for tenant [%s]", identityProvidersContainerDn); logger.error(msg); throw new NoSuchIdpException(msg); } String identityProviderDn = IdentityProviderLdapObject.getInstance().lookupObject(connection, identityProvidersContainerDn, LdapScope.SCOPE_ONE_LEVEL, domainName); if (identityProviderDn == null) { String msg = String.format("Idp [%s] does not exist under [%s]", domainName, identityProvidersContainerDn); logger.error(msg); throw new NoSuchIdpException(msg); } try { LdapMod[] mod = { new LdapMod(LdapModOperation.DELETE, IdentityProviderLdapObject.PROPERTY_UPN_SUFFIXES, ValidateUtil.getCanonicalUpnSuffix(upnSuffix)) }; connection.modifyObject(identityProviderDn, mod); removed = true; } catch (NoSuchAttributeLdapException e) { logger.info( String.format("upnSuffix [%s] is not found from provider [%s]", upnSuffix, identityProviderDn)); removed = false; } finally { connection.close(); } return removed; } @Override public ClientCertPolicy getClientCertPolicy(String tenantName) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ILdapConnectionEx connection = this.getConnection(); try { String tenantRootDn = this.ensureTenantExists(connection, tenantName); // get ClientCertPolicy String filter = String.format("(cn=%s)", ClientCertPolicyLdapObject.ClientCertificatePolicyDefaultName); Collection<TenantClientCertPolicy> certPolicies = retrieveObjectsCollection(connection, tenantRootDn, ContainerLdapObject.CONTAINER_CLIENT_CERT_POLICIES, filter, ClientCertPolicyLdapObject.getInstance(), new IObjectProcessedCallback<TenantClientCertPolicy>() { @Override public void processObjectSaved(ILdapConnectionEx connection, String certPolicyDn, TenantClientCertPolicy policy) { policy.getClientCertPolicy() .set_siteOCSPMap(retrieveSiteOCSPMap(connection, certPolicyDn)); } }); ClientCertPolicy certPolicy = null; if (certPolicies != null && certPolicies.size() > 0) { // retrieve the certPolicy TenantClientCertPolicy tenantClientCertPolicy = certPolicies.iterator().next(); certPolicy = tenantClientCertPolicy.getClientCertPolicy(); // retrieve the trustedCAs String clientCertPolicyContainerDn = String.format("cn=%s,%s", ContainerLdapObject.CONTAINER_CLIENT_CERT_POLICIES, tenantRootDn); Collection<TenantTrustedCertificateChain> chains = retrieveObjectsCollection(connection, ClientCertPolicyLdapObject.getInstance().getDnFromObject(clientCertPolicyContainerDn, tenantClientCertPolicy), ClientCertPolicyLdapObject.CONTAINER_CLIENT_CERT_TRUSTED_CA_CERTIFICATES, TenantTrustedCertChainLdapObject.getInstance(), null); for (TenantTrustedCertificateChain chain : chains) { if (chain.getTenantTrustedCertChainName() .equals(ClientCertPolicyLdapObject.CLIENT_CERT_TRUSTED_CA_CERTIFICATES_DEFAULT_NAME) && chain.getCertificateChain().size() > 0) { // set trusted CAs to certPolicy certPolicy.setTrustedCAs(chain.getCertificateChain() .toArray(new Certificate[chain.getCertificateChain().size()])); } } } else { certPolicy = new ClientCertPolicy(); } return certPolicy; } finally { connection.close(); } } private static HashMap<String, AlternativeOCSPList> retrieveSiteOCSPMap(ILdapConnectionEx connection, String certPolicyDn) { ValidateUtil.validateNotEmpty(certPolicyDn, "certPolicyDn"); AlternativeOCSPListLdapObject ocspListLdapObj = AlternativeOCSPListLdapObject.getInstance(); Collection<AlternativeOCSPList> altOCSPListColection = retrieveObjectsCollection(connection, certPolicyDn, ContainerLdapObject.CONTAINER_CLIENT_CERT_OCSP_LISTS, ocspListLdapObj, new IObjectProcessedCallback<AlternativeOCSPList>() { @Override public void processObjectSaved(ILdapConnectionEx connection, String altOcspListDn, AlternativeOCSPList altOCSPList) { //retrieve OCSP responders for AlternativeOCSPList object. altOCSPList.set_ocspList(retrieveAlternativeOCSPsForSite(connection, altOcspListDn)); } }); //Create HashMap to be returned. HashMap<String, AlternativeOCSPList> retMap = new HashMap<String, AlternativeOCSPList>(); if (altOCSPListColection != null && !altOCSPListColection.isEmpty()) { for (AlternativeOCSPList altOcspList : altOCSPListColection) { retMap.put(altOcspList.get_siteID(), altOcspList); } } return retMap; } /** * retrieve ordered AlternativeOCSP list * @param connection * @param altOcspListDn * @return */ protected static List<AlternativeOCSP> retrieveAlternativeOCSPsForSite(ILdapConnectionEx connection, String altOcspListDn) { Collection<TenantAlternativeOCSP> tOcspCollection = retrieveObjectsCollection(connection, altOcspListDn, ContainerLdapObject.CONTAINER_OCSPs, TenantAlternativeOCSPLdapObject.getInstance(), null); ArrayList<AlternativeOCSP> ocspArray = new ArrayList<AlternativeOCSP>(tOcspCollection.size()); for (TenantAlternativeOCSP tAlternativeOCSP : tOcspCollection) { ocspArray.add(tAlternativeOCSP.getAlternativeOCSP()); } //verify the order by cn int index = 0; for (TenantAlternativeOCSP tAlternativeOCSP : tOcspCollection) { int cn = Integer.parseInt(tAlternativeOCSP.getCn()); if (cn < tOcspCollection.size()) { if (cn != index) { ocspArray.set(cn, tAlternativeOCSP.getAlternativeOCSP()); } } else { throw new IllegalArgumentException( "Unexpected TenantAlternativeOCSP object has cn value out of index range of the collection."); } index++; } return ocspArray; } @Override public void setClientCertPolicy(String tenantName, ClientCertPolicy policy) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ILdapConnectionEx connection = this.getConnection(); try { String tenantRootDn = this.ensureTenantExists(connection, tenantName); String authnPoliciesContainerDn = DirectoryConfigStore.ensureObjectExists(connection, tenantRootDn, ContainerLdapObject.getInstance(), ContainerLdapObject.CONTAINER_CLIENT_CERT_POLICIES, true); String filter = String.format("(cn=%s)", ClientCertPolicyLdapObject.ClientCertificatePolicyDefaultName); Collection<TenantClientCertPolicy> certPolicies = retrieveObjectsCollection(connection, tenantRootDn, ContainerLdapObject.CONTAINER_CLIENT_CERT_POLICIES, filter, ClientCertPolicyLdapObject.getInstance(), new IObjectProcessedCallback<TenantClientCertPolicy>() { @Override public void processObjectSaved(ILdapConnectionEx connection, String objectDn, TenantClientCertPolicy certPolicy) { } }); // Set ClientCertificatePolicy String certPolicyDn = ClientCertPolicyLdapObject.getInstance().getDnFromCn(authnPoliciesContainerDn, ClientCertPolicyLdapObject.ClientCertificatePolicyDefaultName); if (policy != null) { if (certPolicies != null && certPolicies.size() > 0) { ClientCertPolicyLdapObject.getInstance().updateObject(connection, certPolicyDn, new TenantClientCertPolicy(tenantName, policy)); } else { ClientCertPolicyLdapObject.getInstance().createObject(connection, certPolicyDn, new TenantClientCertPolicy(tenantName, policy)); } // Ensure trustedCA container exist String trustedCAContainerDn = DirectoryConfigStore.ensureObjectExists(connection, certPolicyDn, ContainerLdapObject.getInstance(), ClientCertPolicyLdapObject.CONTAINER_CLIENT_CERT_TRUSTED_CA_CERTIFICATES, true); // Retrieve the existing trustedCAs Set<String> trustedCADns = TenantTrustedCertChainLdapObject.getInstance().lookupObjects(connection, trustedCAContainerDn, LdapScope.SCOPE_ONE_LEVEL, ClientCertPolicyLdapObject.CLIENT_CERT_TRUSTED_CA_CERTIFICATES_DEFAULT_NAME, TenantTrustedCertChainLdapObject.OBJECT_CLASS); String trustedCAsDn = String.format("cn=%s,%s", ClientCertPolicyLdapObject.CLIENT_CERT_TRUSTED_CA_CERTIFICATES_DEFAULT_NAME, trustedCAContainerDn); // Set the trustedCAs if (policy.getTrustedCAs() != null && policy.getTrustedCAs().length > 0) { Certificate[] certs = policy.getTrustedCAs(); TenantTrustedCertificateChain trustedCAs = new TenantTrustedCertificateChain( ClientCertPolicyLdapObject.CLIENT_CERT_TRUSTED_CA_CERTIFICATES_DEFAULT_NAME, new ArrayList<Certificate>(Arrays.asList(certs))); if (trustedCADns != null && trustedCADns.size() > 0) { // Update existing trusted CAs TenantTrustedCertChainLdapObject.getInstance().updateObject(connection, trustedCAsDn, trustedCAs); } else { // Create trusted CAs TenantTrustedCertChainLdapObject.getInstance().createObject(connection, trustedCAsDn, trustedCAs); } } else if (trustedCADns != null && trustedCADns.size() > 0) { // Delete current trusted CAs TenantTrustedCertChainLdapObject.getInstance().deleteObject(connection, trustedCAsDn); } //set OCSP list setOCSPLists(certPolicyDn, connection, policy.get_siteOCSPList()); } else if (certPolicies != null && certPolicies.size() > 0) { // Delete the current certPolicy ClientCertPolicyLdapObject.getInstance().deleteObject(connection, certPolicyDn); } } finally { connection.close(); } } /** * Save a hashmap <site,AlternativeOCSPList> * if the provided instance is not empty, this function does update and add entries. * * Note: we ignore null siteOcspMap (i.e. do not clean the corresponding directory objects) for API backward compatibility. * * @param certPolicyDn * @param connection * @param siteOcspMap */ private void setOCSPLists(String certPolicyDn, ILdapConnectionEx connection, HashMap<String, AlternativeOCSPList> siteOcspMap) { ValidateUtil.validateNotEmpty(certPolicyDn, "certPolicyDn"); ContainerLdapObject instContainer = ContainerLdapObject.getInstance(); String ocspListContainerDn = DirectoryConfigStore.ensureObjectExists(connection, certPolicyDn, instContainer, ContainerLdapObject.CONTAINER_CLIENT_CERT_OCSP_LISTS, true); if (siteOcspMap != null && siteOcspMap.size() > 0) { AlternativeOCSPListLdapObject altOcspListLdap = AlternativeOCSPListLdapObject.getInstance(); Collection<AlternativeOCSPList> existingOcspLists = retrieveObjectsCollection(connection, certPolicyDn, ContainerLdapObject.CONTAINER_CLIENT_CERT_OCSP_LISTS, null, altOcspListLdap, new IObjectProcessedCallback<AlternativeOCSPList>() { @Override public void processObjectSaved(ILdapConnectionEx connection, String objectDn, AlternativeOCSPList instInfo) { } }); if (siteOcspMap.size() != existingOcspLists.size()) { AlternativeOCSPListLdapObject.getInstance().deleteObject(connection, ocspListContainerDn); //recreate empty DN ocspListContainerDn = DirectoryConfigStore.ensureObjectExists(connection, certPolicyDn, instContainer, ContainerLdapObject.CONTAINER_CLIENT_CERT_OCSP_LISTS, true); existingOcspLists = null; } //Note: this does not guarantee remove old site config if site ID is changed. But this is okay. CLI is capable to clean all sites for (String siteID : siteOcspMap.keySet()) { AlternativeOCSPList ocspList = siteOcspMap.get(siteID); updateOCSPList(ocspListContainerDn, connection, existingOcspLists, ocspList); } } else { if (siteOcspMap != null) { AlternativeOCSPListLdapObject.getInstance().deleteObject(connection, ocspListContainerDn); } //else null siteOcspMap. Ignore for API backward compatibility. } } /** * Add/update a list of alternative OCSP responders for a site * @param ocspListContainerDn * @param connection * @param ocspLists * @param ocspList */ private void updateOCSPList(String ocspListContainerDn, ILdapConnectionEx connection, Collection<AlternativeOCSPList> existingOcspLists, AlternativeOCSPList ocspList) { AlternativeOCSPListLdapObject ocspListObj = AlternativeOCSPListLdapObject.getInstance(); String listDn = ocspListObj.getDnFromCn(ocspListContainerDn, ocspList.get_siteID()); if (existingOcspLists == null || !existingOcspLists.contains(ocspList)) { //go ahead update if (ocspList != null) { if (isOCSPListSiteExist(existingOcspLists, ocspList.get_siteID())) { AlternativeOCSPListLdapObject.getInstance().deleteObject(connection, listDn); } ocspListObj.createObject(connection, listDn, ocspList); //save AlternativeOCSP objects ContainerLdapObject ocspContainer = ContainerLdapObject.getInstance(); String ocspContainerDn = DirectoryConfigStore.ensureObjectExists(connection, listDn, ocspContainer, ContainerLdapObject.CONTAINER_OCSPs, true); List<AlternativeOCSP> altOCSPs = ocspList.get_ocspList(); int ind = 0; for (AlternativeOCSP altOCSP : altOCSPs) { String indStr = String.valueOf(ind++); String ocspDn = ocspListObj.getDnFromCn(ocspContainerDn, indStr); TenantAlternativeOCSP tenantAltOCSP = new TenantAlternativeOCSP(indStr, altOCSP); addOCSP(ocspDn, connection, tenantAltOCSP); } } } // else exact same object exist } private void addOCSP(String ocspDn, ILdapConnectionEx connection, TenantAlternativeOCSP altOCSP) { TenantAlternativeOCSPLdapObject ocspLdapObj = TenantAlternativeOCSPLdapObject.getInstance(); ocspLdapObj.createObject(connection, ocspDn, altOCSP); } /** * Check if a site was already created for the given site-id. * @param existingOcspLists * @param siteID * @return */ private boolean isOCSPListSiteExist(Collection<AlternativeOCSPList> existingOcspLists, String siteID) { boolean retVal = false; ValidateUtil.validateNotNull(siteID, "siteID"); if (existingOcspLists == null || existingOcspLists.isEmpty()) { retVal = false; } else { for (AlternativeOCSPList list : existingOcspLists) { if (list.get_siteID().equals(siteID)) { retVal = true; } } } return retVal; } @Override public void setAuthnTypes(String tenantName, boolean password, boolean windows, boolean certificate, boolean rsaSecureID) throws Exception { // Set AuthnTypes HashSet<Integer> authnTypes = new HashSet<Integer>(); if (password) authnTypes.add(DirectoryConfigStore.FLAG_AUTHN_TYPE_ALLOW_PASSWORD); if (windows) authnTypes.add(DirectoryConfigStore.FLAG_AUTHN_TYPE_ALLOW_WINDOWS); if (certificate) authnTypes.add(DirectoryConfigStore.FLAG_AUTHN_TYPE_ALLOW_TLS_CERTIFICATE); if (rsaSecureID) authnTypes.add(DirectoryConfigStore.FLAG_AUTHN_TYPE_ALLOW_RSA_SECUREID); if (authnTypes.size() == 0) // This is to distinguish the case that // none of the AuthnTypes is set and // the case of migrating from old schema // where AuthnTypes is not there. authnTypes.add(DirectoryConfigStore.FLAG_AUTHN_TYPE_ALLOW_NONE); int[] authnTypesArray = ArrayUtils.toPrimitive(authnTypes.toArray(new Integer[authnTypes.size()])); this.setTenantProperty(tenantName, TenantLdapObject.PROPERTY_AUTHN_TYPES, ServerUtils.getLdapValue(authnTypesArray)); } @Override public RSAAgentConfig getRSAAgentConfig(String tenantName) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ILdapConnectionEx connection = this.getConnection(); RSAAgentConfig rsaConfig = null; try { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); String tenantsRootDn = this.ensureTenantExists(connection, tenantName); Collection<RSAAgentConfig> configs = retrieveObjectsCollection(connection, tenantsRootDn, ContainerLdapObject.CONTAINER_RSA_CONFIGURATIONS, null, RSAAgentConfigLdapObject.getInstance(), new IObjectProcessedCallback<RSAAgentConfig>() { @Override public void processObjectSaved(ILdapConnectionEx connection, String rsaConfigDn, RSAAgentConfig rsaConfig) { rsaConfig.set_instMap(retrieveRSAAMInstancesMap(connection, rsaConfigDn)); rsaConfig.set_idsUserIDAttributeMaps( retrieveRSAConfigIdsUserIDAttributeMaps(connection, rsaConfigDn)); } }); if (configs == null || configs.size() == 0) { rsaConfig = null; } else { rsaConfig = configs.iterator().next(); } } finally { connection.close(); } return rsaConfig; } private static HashMap<String, RSAAMInstanceInfo> retrieveRSAAMInstancesMap(ILdapConnectionEx connection, String rsaAgentConfigDn) { ValidateUtil.validateNotEmpty(rsaAgentConfigDn, "rsaAgentConfigDn"); Collection<RSAAMInstanceInfo> instColection = retrieveObjectsCollection(connection, rsaAgentConfigDn, ContainerLdapObject.CONTAINER_RSA_INSTANCES, RSAInstanceLdapObject.getInstance(), null); HashMap<String, RSAAMInstanceInfo> retMap = new HashMap<String, RSAAMInstanceInfo>(); if (instColection != null && !instColection.isEmpty()) { for (RSAAMInstanceInfo inst : instColection) { retMap.put(inst.get_siteID(), inst); } } return retMap; } private static HashMap<String, String> retrieveRSAConfigIdsUserIDAttributeMaps(ILdapConnectionEx connection, String rsaAgentConfigDn) { ValidateUtil.validateNotEmpty(rsaAgentConfigDn, "rsaAgentConfigDn"); HashMap<String, String> attrMaps = null; Collection<AttributeMapping> mapCollection = retrieveObjectsCollection(connection, rsaAgentConfigDn, ContainerLdapObject.CONTAINER_RSA_IDS_USERID_ATTRIBUTE_MAPS, AttributeMappingLdapObject.getInstance(), null); if (mapCollection != null && !mapCollection.isEmpty()) { attrMaps = new HashMap<String, String>(); } for (AttributeMapping pair : mapCollection) { attrMaps.put(pair.getAttributeFrom(), pair.getAttributeTo()); } return attrMaps; } @Override public void setRsaAgentConfig(String tenantName, RSAAgentConfig rsaConfig) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); if (rsaConfig == null) { return; } ILdapConnectionEx connection = this.getConnection(); try { String tenantsRootDn = this.ensureTenantExists(connection, tenantName); ContainerLdapObject rsaConfigsContainer = ContainerLdapObject.getInstance(); String rsaConfigsContainerDn = DirectoryConfigStore.ensureObjectExists(connection, tenantsRootDn, rsaConfigsContainer, ContainerLdapObject.CONTAINER_RSA_CONFIGURATIONS, true); Collection<RSAAgentConfig> rsaConfigs = retrieveObjectsCollection(connection, tenantsRootDn, ContainerLdapObject.CONTAINER_RSA_CONFIGURATIONS, null, RSAAgentConfigLdapObject.getInstance(), new IObjectProcessedCallback<RSAAgentConfig>() { @Override public void processObjectSaved(ILdapConnectionEx connection, String objectDn, RSAAgentConfig rsaConfig) { } }); // Set rsaConfigurations RSAAgentConfigLdapObject rsaConfigLdap = RSAAgentConfigLdapObject.getInstance(); String rsaConfigDn = rsaConfigLdap.getDnFromCn(rsaConfigsContainerDn, RSAAgentConfigLdapObject.PROPERTY_DEFAULT_NAME); if (rsaConfig != null) { if (rsaConfigs.size() == 1) { RSAAgentConfigLdapObject.getInstance().updateObject(connection, rsaConfigDn, rsaConfig); } else { rsaConfigLdap.createObject(connection, rsaConfigDn, rsaConfig); } setRsaInstances(rsaConfigDn, connection, rsaConfig.get_instMap()); //First delete old IDSUserIDAttribute map. Then add the new one. deleteRSAConfigUserIDAttributeMap(tenantName, connection, rsaConfigDn, rsaConfig); DirectoryConfigStore.saveRSAConfigUserIDAttributeMap(connection, rsaConfigDn, rsaConfig.get_idsUserIDAttributeMap()); } } finally { connection.close(); } } private void deleteRSAConfigUserIDAttributeMap(String tenantName, ILdapConnectionEx connection, String rsaConfigDn, RSAAgentConfig config) { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateNotEmpty(rsaConfigDn, "rsaConfigDn"); try { AttributeMappingLdapObject attrMapsLdapObject = AttributeMappingLdapObject.getInstance(); if (ServerUtils.isNullOrEmpty(rsaConfigDn) == false) { String idsUserIDAttributeMapsDn = attrMapsLdapObject.lookupObject(connection, rsaConfigDn, LdapScope.SCOPE_ONE_LEVEL, ContainerLdapObject.CONTAINER_RSA_IDS_USERID_ATTRIBUTE_MAPS); if (ServerUtils.isNullOrEmpty(idsUserIDAttributeMapsDn) == false) { attrMapsLdapObject.deleteObject(connection, idsUserIDAttributeMapsDn); } } } catch (Exception e) { logger.error("Unable to delete old RSAAgentIDSAtributeMaps"); } } private static void saveRSAConfigUserIDAttributeMap(ILdapConnectionEx connection, String rsaConfigDn, HashMap<String, String> idsUserIDAttributeMap) { Collection<AttributeMapping> attributeMappingArray = new ArrayList<AttributeMapping>(); if (idsUserIDAttributeMap != null) { int i = 0; Set<String> keySet = idsUserIDAttributeMap.keySet(); for (String key : keySet) { attributeMappingArray.add(new AttributeMapping(key, idsUserIDAttributeMap.get(key), i++)); } } saveObjectsCollection(connection, rsaConfigDn, ContainerLdapObject.CONTAINER_RSA_IDS_USERID_ATTRIBUTE_MAPS, AttributeMappingLdapObject.getInstance(), attributeMappingArray, null); } /** * if the provided instance is not empty, this function does update and add entries but not remove existing entries. * It clears the container if the updating map is empty. * * * @param rsaConfigDn non-null * @param connection * @param instMap could be null or empty */ private void setRsaInstances(String rsaConfigDn, ILdapConnectionEx connection, HashMap<String, RSAAMInstanceInfo> instMap) { ValidateUtil.validateNotEmpty(rsaConfigDn, "rsaConfigDn"); ContainerLdapObject instContainer = ContainerLdapObject.getInstance(); String instContainerDn = DirectoryConfigStore.ensureObjectExists(connection, rsaConfigDn, instContainer, ContainerLdapObject.CONTAINER_RSA_INSTANCES, true); if (instMap != null && instMap.size() > 0) { RSAInstanceLdapObject rsaInstanceLdap = RSAInstanceLdapObject.getInstance(); Collection<RSAAMInstanceInfo> instances = retrieveObjectsCollection(connection, rsaConfigDn, ContainerLdapObject.CONTAINER_RSA_INSTANCES, null, rsaInstanceLdap, new IObjectProcessedCallback<RSAAMInstanceInfo>() { @Override public void processObjectSaved(ILdapConnectionEx connection, String objectDn, RSAAMInstanceInfo instInfo) { } }); for (String siteID : instMap.keySet()) { RSAAMInstanceInfo inst = instMap.get(siteID); // Set RSAAMInstanceInfo addRSAInstanceInfo(instContainerDn, connection, instances, inst); } } else { // Delete the container since it is not set in the new data RSAAgentConfigLdapObject.getInstance().deleteObject(connection, instContainerDn); } } @Override public void deleteRSAInstanceInfo(String tenantName, String siteID) throws Exception { ValidateUtil.validateNotNull(siteID, "siteID"); ILdapConnectionEx connection = this.getConnection(); try { String tenantsRootDn = this.ensureTenantExists(connection, tenantName); ContainerLdapObject instContainer = ContainerLdapObject.getInstance(); String rsaConfigsContainerDn = DirectoryConfigStore.ensureObjectExists(connection, tenantsRootDn, instContainer, ContainerLdapObject.CONTAINER_RSA_CONFIGURATIONS, true); String rsaConfigDn = instContainer.getDnFromCn(rsaConfigsContainerDn, RSAAgentConfigLdapObject.PROPERTY_DEFAULT_NAME); String instContainerDn = DirectoryConfigStore.ensureObjectExists(connection, rsaConfigDn, instContainer, ContainerLdapObject.CONTAINER_RSA_INSTANCES, true); //test Set<String> rsaInstanceDns = instContainer.lookupObjects(connection, instContainerDn, LdapScope.SCOPE_ONE_LEVEL, siteID, RSAInstanceLdapObject.OBJECT_CLASS); for (String instDn : rsaInstanceDns) { instContainer.deleteObject(connection, instDn); } } finally { connection.close(); } } private void addRSAInstanceInfo(String instContainerDn, ILdapConnectionEx connection, Collection<RSAAMInstanceInfo> instances, RSAAMInstanceInfo inst) { RSAInstanceLdapObject rsaInstanceLdap = RSAInstanceLdapObject.getInstance(); String instDn = rsaInstanceLdap.getDnFromCn(instContainerDn, inst.get_siteID()); if (inst != null) { if (isInstAlreadyCreated(instances, inst.get_siteID())) { RSAInstanceLdapObject.getInstance().updateObject(connection, instDn, inst); } else { rsaInstanceLdap.createObject(connection, instDn, inst); } } } /** * Check if RSAAMInstanceInfo is already defined for a site. * * @param instances set of RSAAMInstanceInfo defined for the tenant * @param siteID the siteID to search for * @return true if the set contains the given site */ private boolean isInstAlreadyCreated(Collection<RSAAMInstanceInfo> instances, String siteID) { boolean retVal = false; ValidateUtil.validateNotNull(siteID, "siteID"); if (instances == null || instances.isEmpty()) { retVal = false; } else { for (RSAAMInstanceInfo instInfo : instances) { if (instInfo.get_siteID().equals(siteID)) { retVal = true; } } } return retVal; } @Override public void addRSAInstanceInfo(String tenantName, RSAAMInstanceInfo instInfo) throws Exception { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); ValidateUtil.validateNotNull(instInfo, "instInfo"); ILdapConnectionEx connection = this.getConnection(); try { String tenantsRootDn = this.ensureTenantExists(connection, tenantName); ContainerLdapObject ldapContainer = ContainerLdapObject.getInstance(); String rsaConfigsContainerDn = DirectoryConfigStore.ensureObjectExists(connection, tenantsRootDn, ldapContainer, ContainerLdapObject.CONTAINER_RSA_CONFIGURATIONS, true); Collection<RSAAgentConfig> rsaConfigs = retrieveObjectsCollection(connection, tenantsRootDn, ContainerLdapObject.CONTAINER_RSA_CONFIGURATIONS, null, RSAAgentConfigLdapObject.getInstance(), new IObjectProcessedCallback<RSAAgentConfig>() { @Override public void processObjectSaved(ILdapConnectionEx connection, String objectDn, RSAAgentConfig rsaConfig) { } }); //intialize a default RSAAgentCofig if needed if (rsaConfigs == null || rsaConfigs.isEmpty()) { RSAAgentConfig agentConfig = new RSAAgentConfig(); setRsaAgentConfig(tenantName, agentConfig); } RSAAgentConfigLdapObject rsaConfigLdap = RSAAgentConfigLdapObject.getInstance(); String rsaConfigDn = rsaConfigLdap.getDnFromCn(rsaConfigsContainerDn, RSAAgentConfigLdapObject.PROPERTY_DEFAULT_NAME); String instContainerDn = DirectoryConfigStore.ensureObjectExists(connection, rsaConfigDn, ldapContainer, ContainerLdapObject.CONTAINER_RSA_INSTANCES, true); RSAInstanceLdapObject rsaInstanceLdap = RSAInstanceLdapObject.getInstance(); Collection<RSAAMInstanceInfo> instances = retrieveObjectsCollection(connection, rsaConfigDn, ContainerLdapObject.CONTAINER_RSA_INSTANCES, null, rsaInstanceLdap, new IObjectProcessedCallback<RSAAMInstanceInfo>() { @Override public void processObjectSaved(ILdapConnectionEx connection, String objectDn, RSAAMInstanceInfo instInfo) { } }); addRSAInstanceInfo(instContainerDn, connection, instances, instInfo); } catch (Exception e) { logger.error(String.format("Fail to add RSAAMInstance for site %s", instInfo.get_siteID()), e); } finally { connection.close(); } } private Tenant getTenant(ILdapConnectionEx connection, String name) throws Exception { Tenant tenant = null; String tenantsRootDn = this.lookupTenantsRootDn(connection, name); if (ServerUtils.isNullOrEmpty(tenantsRootDn) == false) { TenantLdapObject tenantConfigObject = TenantLdapObject.getInstance(); tenant = tenantConfigObject.retrieveObject(connection, tenantsRootDn, LdapScope.SCOPE_BASE, null); } return tenant; } private String getDefaultTenant(ILdapConnectionEx connection) { String defaultTenant = null; String rootSystemConfigDn = this.getRootSystemConfigDn(connection, false); if (ServerUtils.isNullOrEmpty(rootSystemConfigDn) == false) { TenantsContainerLdapObject tenantsContainer = TenantsContainerLdapObject.getInstance(); defaultTenant = ServerUtils.getStringValue( tenantsContainer.getObjectProperty(connection, rootSystemConfigDn, LdapScope.SCOPE_ONE_LEVEL, tenantsContainer.getCn(TenantsContainerLdapObject.CONTAINER_TENANTS), TenantsContainerLdapObject.PROPERTY_DEFAULT_TENANT)); } return defaultTenant; } private void setDefaultTenant(ILdapConnectionEx connection, String defaultTenant) { String rootSystemConfigDn = this.getRootSystemConfigDn(connection, false); TenantsContainerLdapObject tenantsContainer = TenantsContainerLdapObject.getInstance(); tenantsContainer.setObjectPropertyValue(connection, tenantsContainer.getDnFromCn(rootSystemConfigDn, tenantsContainer.getCn(TenantsContainerLdapObject.CONTAINER_TENANTS)), TenantsContainerLdapObject.PROPERTY_DEFAULT_TENANT, ServerUtils.getLdapValue(defaultTenant)); } private String getSystemTenant(ILdapConnectionEx connection) { String defaultTenant = null; String rootSystemConfigDn = this.getRootSystemConfigDn(connection, false); if (ServerUtils.isNullOrEmpty(rootSystemConfigDn) == false) { TenantsContainerLdapObject tenantsContainer = TenantsContainerLdapObject.getInstance(); defaultTenant = ServerUtils.getStringValue( tenantsContainer.getObjectProperty(connection, rootSystemConfigDn, LdapScope.SCOPE_ONE_LEVEL, tenantsContainer.getCn(TenantsContainerLdapObject.CONTAINER_TENANTS), TenantsContainerLdapObject.PROPERTY_SYSTEM_TENANT)); } return defaultTenant; } private void setSystemTenant(ILdapConnectionEx connection, String systemTenant) { String rootSystemConfigDn = this.getRootSystemConfigDn(connection, false); TenantsContainerLdapObject tenantsContainer = TenantsContainerLdapObject.getInstance(); tenantsContainer.setObjectPropertyValue(connection, tenantsContainer.getDnFromCn(rootSystemConfigDn, tenantsContainer.getCn(TenantsContainerLdapObject.CONTAINER_TENANTS)), TenantsContainerLdapObject.PROPERTY_SYSTEM_TENANT, ServerUtils.getLdapValue(systemTenant)); } private static Collection<RelyingParty> getRelyingParties(DirectoryConfigStore directoryConfigStore, ILdapConnectionEx connection, String tenantName, String propertyFilter) { ValidateUtil.validateNotEmpty(tenantName, "tenantName"); String tenantsRootDn = directoryConfigStore.ensureTenantExists(connection, tenantName); Collection<RelyingParty> relyingParties = retrieveObjectsCollection(connection, tenantsRootDn, ContainerLdapObject.CONTAINER_RELYING_PARTIES, propertyFilter, RelyingPartyLdapObject.getInstance(), new IObjectProcessedCallback<RelyingParty>() { @Override public void processObjectSaved(ILdapConnectionEx connection, String objectDn, RelyingParty relyingParty) { relyingParty.setAssertionConsumerServices( retrieveRelyingPartyAssertionConsumerServices(connection, objectDn)); relyingParty.setAttributeConsumerServices( retrieveRelyingPartyAttributeConsumerServices(connection, objectDn)); relyingParty.setSingleLogoutServices( retrieveRelyingPartySingleLogoutServices(connection, objectDn)); relyingParty.setSignatureAlgorithms( retrieveRelyingPartySignatureAlgorithms(connection, objectDn)); } }); return relyingParties; } private IIdentityStoreData getLocalOsDomainIdentityStoreData(IIdentityStoreData idsData) { ServerIdentityStoreData serverIdentityStoreData = new ServerIdentityStoreData(idsData.getDomainType(), idsData.getName()); serverIdentityStoreData.setProviderType(IdentityStoreType.IDENTITY_STORE_TYPE_LOCAL_OS); HashMap<String, String> map = new HashMap<String, String>(); map.put(IdmServerConfig.ATTRIBUTE_GROUPS, LocalOsIdentityProvider.GROUPS_ATTRIBUTE); map.put(IdmServerConfig.ATTRIBUTE_FIRST_NAME, LocalOsIdentityProvider.FIRST_NAME_ATTRIBUTE); map.put(IdmServerConfig.ATTRIBUTE_LAST_NAME, LocalOsIdentityProvider.LAST_NAME_ATTRIBUTE); map.put(IdmServerConfig.ATTRIBUTE_SUBJECT_TYPE, LocalOsIdentityProvider.SUBJECT_TYPE_ATTRIBUTE); map.put(IdmServerConfig.ATTRIBUTE_USER_PRINCIPAL_NAME, LocalOsIdentityProvider.USER_PRINCIPAL_NAME_ATTRIBUTE); map.put(IdmServerConfig.ATTRIBUTE_EMAIL, LocalOsIdentityProvider.EMAIL_ATTRIBUTE); serverIdentityStoreData.setAttributeMap(map); if (idsData.getExtendedIdentityStoreData() != null) { if (ServerUtils.isNullOrEmpty(idsData.getExtendedIdentityStoreData().getAlias()) == false) { serverIdentityStoreData.setAlias(idsData.getExtendedIdentityStoreData().getAlias()); } } return serverIdentityStoreData; } private void updateSystemDomain(String tenantName, ServerIdentityStoreData configData) throws Exception { ILdapConnectionEx connection = this.getConnection(); try { Tenant tenant = this.getTenant(connection, tenantName); String identityManagerDn = this.getRootSystemConfigDn(connection, true); String tenantsContainerDn = DirectoryConfigStore.ensureObjectExists(connection, identityManagerDn, TenantsContainerLdapObject.getInstance(), TenantsContainerLdapObject.CONTAINER_TENANTS, false); ValidateUtil.validateNotEmpty(tenantsContainerDn, "Tenant container DN"); TenantLdapObject tenantObject = TenantLdapObject.getInstance(); String tenantDn = tenantObject.getDnFromObject(tenantsContainerDn, tenant); IdentityProviderLdapObject identityProviderConfigObject = IdentityProviderLdapObject.getInstance(); String identityProvidersContainerDn = DirectoryConfigStore.ensureObjectExists(connection, tenantDn, ContainerLdapObject.getInstance(), ContainerLdapObject.CONTAINER_IDENTITY_PROVIDERS, false); ValidateUtil.validateNotEmpty(identityProvidersContainerDn, "Identity provider container DN"); String identityProviderDn = identityProviderConfigObject.getDnFromObject(identityProvidersContainerDn, configData); enCryptPassword(tenant._tenantKey, configData.getExtendedIdentityStoreData()); identityProviderConfigObject.updateObject(connection, identityProviderDn, configData); } finally { connection.close(); } } private static void SaveIdentityProviderConfig(DirectoryConfigStore directoryConfigStore, ILdapConnectionEx connection, String tenantsRootDn, IIdentityStoreData idsData) throws Exception { IdentityProviderLdapObject identityProviderConfigObject = IdentityProviderLdapObject.getInstance(); IdentityProviderAliasLdapObject identityProviderAliasConfigObject = IdentityProviderAliasLdapObject .getInstance(); String identityProvidersContainerDn = DirectoryConfigStore.ensureObjectExists(connection, tenantsRootDn, ContainerLdapObject.getInstance(), ContainerLdapObject.CONTAINER_IDENTITY_PROVIDERS, true); IIdentityStoreDataEx storeDataEx = idsData.getExtendedIdentityStoreData(); String aliasName = null; if ((storeDataEx != null) && (ServerUtils.isNullOrEmpty(storeDataEx.getAlias()) == false)) { aliasName = storeDataEx.getAlias(); } if (ServerUtils.isNullOrEmpty(aliasName) == false) { // validate alias will not clash with anything String existingObject = null; try { existingObject = identityProviderConfigObject.lookupObject(connection, identityProvidersContainerDn, LdapScope.SCOPE_ONE_LEVEL, aliasName); if (ServerUtils.isNullOrEmpty(existingObject) == false) { throw new DuplicateProviderException(null, aliasName); } existingObject = identityProviderAliasConfigObject.lookupObject(connection, identityProvidersContainerDn, LdapScope.SCOPE_ONE_LEVEL, aliasName); if (ServerUtils.isNullOrEmpty(existingObject) == false) { throw new DuplicateProviderException( String.format("Identity Store Provider '%s' is already in use.", aliasName)); } } catch (NoSuchObjectLdapException ex) { // Do nothing continue; } } String identityProviderDn = identityProviderConfigObject.getDnFromObject(identityProvidersContainerDn, idsData); identityProviderConfigObject.createObject(connection, identityProviderDn, idsData); DirectoryConfigStore.saveIdentityProviderAttributesMap(connection, identityProviderDn, (storeDataEx != null) ? storeDataEx.getAttributeMap() : null); DirectoryConfigStore.saveIdentityProviderSchemaMapping(connection, identityProviderDn, (storeDataEx != null) ? storeDataEx.getIdentityStoreSchemaMapping() : null); if (ServerUtils.isNullOrEmpty(aliasName) == false && !aliasName.equalsIgnoreCase(idsData.getName())) { IdentityProviderAlias alias = new IdentityProviderAlias(identityProviderDn, aliasName); // create alias identityProviderAliasConfigObject.createObject(connection, identityProviderAliasConfigObject.getDnFromObject(identityProvidersContainerDn, alias), alias); } } private static void saveIdentityProviderAttributesMap(ILdapConnectionEx connection, String identityProviderDn, Map<String, String> attributesMap) { Collection<AttributeMapping> mappings = Collections.emptyList(); if ((attributesMap != null) && (attributesMap.size() > 0)) { mappings = new ArrayList<AttributeMapping>(attributesMap.size()); int i = 0; for (Map.Entry<String, String> pair : attributesMap.entrySet()) { mappings.add(new AttributeMapping(pair.getKey(), pair.getValue(), i++)); } } saveObjectsCollection(connection, identityProviderDn, ContainerLdapObject.CONTAINER_ATRIBUTE_MAP, AttributeMappingLdapObject.getInstance(), mappings, null); } private static Map<String, String> retrieveIdentityProviderAttributesMap(ILdapConnectionEx connection, String identityProviderDn) { Collection<AttributeMapping> mappings = retrieveObjectsCollection(connection, identityProviderDn, ContainerLdapObject.CONTAINER_ATRIBUTE_MAP, AttributeMappingLdapObject.getInstance(), null); Map<String, String> map = Collections.emptyMap(); if ((mappings != null) && (mappings.size() > 0)) { map = new HashMap<String, String>(mappings.size()); for (AttributeMapping attrMapping : mappings) { map.put(attrMapping.getAttributeFrom(), attrMapping.getAttributeTo()); } } return map; } private static void saveIdentityProviderSchemaMapping(ILdapConnectionEx connection, String identityProviderDn, IdentityStoreSchemaMapping schemaMapping) { Collection<IdentityStoreObjectMapping> objectMappings = (schemaMapping != null) ? schemaMapping.getObjectMappings() : null; Collection<AttributeMapping> attrsMapping = Collections.emptyList(); if ((objectMappings != null) && (objectMappings.size() > 0)) { attrsMapping = new ArrayList<AttributeMapping>(objectMappings.size()); int i = 0; for (IdentityStoreObjectMapping objectMapping : objectMappings) { String storeObjectClass = objectMapping.getObjectClass(); if (ServerUtils.isNullOrEmpty(storeObjectClass) == false) { attrsMapping.add(new AttributeMapping(objectMapping.getObjectId(), storeObjectClass, i++)); } for (IdentityStoreAttributeMapping attributeMapping : objectMapping.getAttributeMappings()) { attrsMapping.add(new AttributeMapping( objectMapping.getObjectId() + ":" + attributeMapping.getAttributeId(), attributeMapping.getAttributeName(), i++)); } } } saveObjectsCollection(connection, identityProviderDn, ContainerLdapObject.CONTAINER_IDENTITY_STORE_SCHEMA_MAPPING, AttributeMappingLdapObject.getInstance(), attrsMapping, null); } private static IdentityStoreSchemaMapping retrieveIdentityStoreSchemaMapping(ILdapConnectionEx connection, String identityProviderDn) { Collection<AttributeMapping> mappings = retrieveObjectsCollection(connection, identityProviderDn, ContainerLdapObject.CONTAINER_IDENTITY_STORE_SCHEMA_MAPPING, AttributeMappingLdapObject.getInstance(), null); IdentityStoreSchemaMapping schemaMapping = null; if ((mappings != null) && (mappings.size() > 0)) { IdentityStoreSchemaMapping.Builder schemaMappingBuilder = new IdentityStoreSchemaMapping.Builder(); Map<String, IdentityStoreObjectMapping.Builder> objectMappingBuilderMap = new HashMap<String, IdentityStoreObjectMapping.Builder>(); for (AttributeMapping attrMapping : mappings) { if (attrMapping != null) { String attrFrom = attrMapping.getAttributeFrom(); if (ServerUtils.isNullOrEmpty(attrFrom) != true) { String[] parts = attrFrom.split(":"); IdentityStoreObjectMapping.Builder objectMappingBuilder = objectMappingBuilderMap .get(parts[0]); if (objectMappingBuilder == null) { objectMappingBuilder = new IdentityStoreObjectMapping.Builder(parts[0]); objectMappingBuilderMap.put(parts[0], objectMappingBuilder); } if (parts.length == 1) { objectMappingBuilder.setObjectClass(attrMapping.getAttributeTo()); } else { IdentityStoreAttributeMapping attr = new IdentityStoreAttributeMapping(parts[1], attrMapping.getAttributeTo()); objectMappingBuilder.addAttributeMapping(attr); } } } } for (IdentityStoreObjectMapping.Builder objectMappingBuilder : objectMappingBuilderMap.values()) { schemaMappingBuilder.addObjectMappings(objectMappingBuilder.buildObjectMapping()); } schemaMapping = schemaMappingBuilder.buildSchemaMapping(); } return schemaMapping; } private static IIdentityStoreData getIIdenttyStoreDataToReturn(IIdentityStoreData provider, boolean getInternalInfo) { IIdentityStoreData iIdentityStoreData = null; if (provider instanceof ServerIdentityStoreData) { ServerIdentityStoreData storeData = (ServerIdentityStoreData) provider; if (getInternalInfo == false) { iIdentityStoreData = storeData.getExternalIdentityStoreData(); } else { iIdentityStoreData = storeData; } } return iIdentityStoreData; } private static void retrieveIdentityProviderAttributesMap(ILdapConnectionEx connection, String identityProviderDn, IIdentityStoreData provider, boolean getInternalInfo) { if (provider instanceof ServerIdentityStoreData) { ServerIdentityStoreData storeData = (ServerIdentityStoreData) provider; if ((storeData.getDomainType() == DomainType.EXTERNAL_DOMAIN) || (getInternalInfo == true)) { Map<String, String> map = retrieveIdentityProviderAttributesMap(connection, identityProviderDn); if (map != null) { storeData.setAttributeMap(map); } } } } private static void retrieveIdentityProviderSchemaMapping(ILdapConnectionEx connection, String identityProviderDn, IIdentityStoreData provider, boolean getInternalInfo) { if (provider instanceof ServerIdentityStoreData) { ServerIdentityStoreData storeData = (ServerIdentityStoreData) provider; if ((storeData.getDomainType() == DomainType.EXTERNAL_DOMAIN) || (getInternalInfo == true)) { IdentityStoreSchemaMapping schemaMapping = retrieveIdentityStoreSchemaMapping(connection, identityProviderDn); if (schemaMapping != null) { storeData.setSchemaMapping(schemaMapping); } } } } private static void saveRelyingPartyAssertionConsumerServices(ILdapConnectionEx connection, String relyingPartyDn, Collection<AssertionConsumerService> services) { saveObjectsCollection(connection, relyingPartyDn, ContainerLdapObject.CONTAINER_ASSERTION_COMSUMER_SERVICES, AssertionConsumerServiceLdapObject.getInstance(), services, null); } private static Collection<AssertionConsumerService> retrieveRelyingPartyAssertionConsumerServices( ILdapConnectionEx connection, String relyingPartyDn) { return retrieveObjectsCollection(connection, relyingPartyDn, ContainerLdapObject.CONTAINER_ASSERTION_COMSUMER_SERVICES, AssertionConsumerServiceLdapObject.getInstance(), null); } private static void saveRelyingPartyAttributeConsumerServices(ILdapConnectionEx connection, String relyingPartyDn, Collection<AttributeConsumerService> services) { saveObjectsCollection(connection, relyingPartyDn, ContainerLdapObject.CONTAINER_ATTRIBUTE_COMSUMER_SERVICES, AttributeConsumerServiceLdapObject.getInstance(), services, new IObjectProcessedCallback<AttributeConsumerService>() { @Override public void processObjectSaved(ILdapConnectionEx connection, String objectDn, AttributeConsumerService service) { saveAttributes(connection, objectDn, service.getAttributes()); } }); } private static Collection<AttributeConsumerService> retrieveRelyingPartyAttributeConsumerServices( ILdapConnectionEx connection, String relyingPartyDn) { return retrieveObjectsCollection(connection, relyingPartyDn, ContainerLdapObject.CONTAINER_ATTRIBUTE_COMSUMER_SERVICES, AttributeConsumerServiceLdapObject.getInstance(), new IObjectProcessedCallback<AttributeConsumerService>() { @Override public void processObjectSaved(ILdapConnectionEx connection, String objectDn, AttributeConsumerService service) { service.setAttributes(retrieveAttributes(connection, objectDn)); } }); } private static void saveRelyingPartySingleLogoutServices(ILdapConnectionEx connection, String relyingPartyDn, Collection<ServiceEndpoint> services) { saveObjectsCollection(connection, relyingPartyDn, ContainerLdapObject.CONTAINER_SINGLE_LOGOUT_SERVICES, SingleLogoutServiceLdapObject.getInstance(), services, null); } private static Collection<ServiceEndpoint> retrieveRelyingPartySingleLogoutServices( ILdapConnectionEx connection, String relyingPartyDn) { return retrieveObjectsCollection(connection, relyingPartyDn, ContainerLdapObject.CONTAINER_SINGLE_LOGOUT_SERVICES, SingleLogoutServiceLdapObject.getInstance(), null); } private static void saveRelyingPartySignatureAlgorithms(ILdapConnectionEx connection, String relyingPartyDn, Collection<SignatureAlgorithm> algorithms) { saveIndexWrappedObjectsCollecton(connection, relyingPartyDn, ContainerLdapObject.CONTAINER_SIGNATURE_ALGORITHMS_SERVICES, SignatureAlgorithmsLdapObject.getInstance(), algorithms, null); } private static Collection<SignatureAlgorithm> retrieveRelyingPartySignatureAlgorithms( ILdapConnectionEx connection, String relyingPartyDn) { return retrieveIndexWrappedObjectsCollection(connection, relyingPartyDn, ContainerLdapObject.CONTAINER_SIGNATURE_ALGORITHMS_SERVICES, SignatureAlgorithmsLdapObject.getInstance(), null, false); } private static void saveAttributes(ILdapConnectionEx connection, String parentDn, Collection<Attribute> attributes) { saveIndexWrappedObjectsCollecton(connection, parentDn, ContainerLdapObject.CONTAINER_ATTRIBUTES, TenantAttributeLdapObject.getInstance(), attributes, null); } private static Collection<Attribute> retrieveAttributes(ILdapConnectionEx connection, String parentDn) { return retrieveIndexWrappedObjectsCollection(connection, parentDn, ContainerLdapObject.CONTAINER_ATTRIBUTES, TenantAttributeLdapObject.getInstance(), null, false); } private interface IObjectProcessedCallback<T> { void processObjectSaved(ILdapConnectionEx connection, String objectDn, T object); } private static <T> void saveIndexWrappedObjectsCollecton(ILdapConnectionEx connection, String parentDn, String containerCn, ILdapObject<IndexedObjectWrapper<T>> iLdapObject, Collection<T> objects, IObjectProcessedCallback<T> callback) { ContainerLdapObject containerConfigObject = ContainerLdapObject.getInstance(); String containerDn = containerConfigObject.lookupObject(connection, parentDn, LdapScope.SCOPE_ONE_LEVEL, containerCn); if (ServerUtils.isNullOrEmpty(containerDn) == false) { // remove all existing objects containerConfigObject.deleteObject(connection, containerDn); } if ((objects != null) && (objects.size() > 0)) { containerDn = containerConfigObject.getDnFromObject(parentDn, containerCn); containerConfigObject.createObject(connection, containerDn, containerCn); int i = 0; IndexedObjectWrapper<T> theObject = null; for (T object : objects) { theObject = new IndexedObjectWrapper<T>(object, i); String objectsDn = iLdapObject.getDnFromObject(containerDn, theObject); iLdapObject.createObject(connection, objectsDn, theObject); if (callback != null) { callback.processObjectSaved(connection, objectsDn, object); } i++; } } } private static <T> void saveObjectsCollection(ILdapConnectionEx connection, String parentDn, String containerCn, ILdapObject<T> iLdapObject, Collection<T> objects, IObjectProcessedCallback<T> callback) { ContainerLdapObject containerConfigObject = ContainerLdapObject.getInstance(); String containerDn = containerConfigObject.lookupObject(connection, parentDn, LdapScope.SCOPE_ONE_LEVEL, containerCn); if (ServerUtils.isNullOrEmpty(containerDn) == false) { // remove all existing objects containerConfigObject.deleteObject(connection, containerDn); } if ((objects != null) && (objects.size() > 0)) { containerDn = containerConfigObject.getDnFromObject(parentDn, containerCn); containerConfigObject.createObject(connection, containerDn, containerCn); for (T object : objects) { String objectsDn = iLdapObject.getDnFromObject(containerDn, object); iLdapObject.createObject(connection, objectsDn, object); if (callback != null) { callback.processObjectSaved(connection, objectsDn, object); } } } } private static <T> Collection<T> retrieveIndexWrappedObjectsCollection(ILdapConnectionEx connection, String parentDn, String containerCn, ILdapObject<IndexedObjectWrapper<T>> iLdapObject, IObjectProcessedCallback<T> callback, boolean needsSort) { return retrieveIndexWrappedObjectsCollection(connection, parentDn, containerCn, null, iLdapObject, callback, needsSort); } private static <T> Collection<T> retrieveIndexWrappedObjectsCollection(ILdapConnectionEx connection, String parentDn, String containerCn, String additionalFilter, ILdapObject<IndexedObjectWrapper<T>> iLdapObject, IObjectProcessedCallback<T> callback, boolean needsSort) { ContainerLdapObject containerConfig = ContainerLdapObject.getInstance(); String containerDn = containerConfig.lookupObject(connection, parentDn, LdapScope.SCOPE_ONE_LEVEL, containerCn); Collection<T> objects = new ArrayList<T>(); if (ServerUtils.isNullOrEmpty(containerDn) == false) { List<IndexedObjectWrapper<T>> objectsCollection = iLdapObject.searchObjects(connection, containerDn, LdapScope.SCOPE_ONE_LEVEL, additionalFilter); if ((objectsCollection != null) && (objectsCollection.size() > 0)) { if (needsSort == true) { Collections.sort(objectsCollection, new Comparator<IndexedObjectWrapper<T>>() { @Override public int compare(IndexedObjectWrapper<T> o1, IndexedObjectWrapper<T> o2) { return o1.getIndex() - o2.getIndex(); } }); } for (IndexedObjectWrapper<T> object : objectsCollection) { T candidate = object.getWrappedObject(); if (callback != null) { callback.processObjectSaved(connection, iLdapObject.getDnFromObject(containerDn, object), candidate); } objects.add(candidate); } } } return objects; } private static <T> Collection<T> retrieveObjectsCollection(ILdapConnectionEx connection, String parentDn, String containerCn, ILdapObject<T> iLdapObject, IObjectProcessedCallback<T> callback) { return retrieveObjectsCollection(connection, parentDn, containerCn, null, iLdapObject, callback); } private static <T> Collection<T> retrieveObjectsCollection(ILdapConnectionEx connection, String parentDn, String containerCn, String additionalFilter, ILdapObject<T> iLdapObject, IObjectProcessedCallback<T> callback) { ContainerLdapObject containerConfig = ContainerLdapObject.getInstance(); String containerDn = containerConfig.lookupObject(connection, parentDn, LdapScope.SCOPE_ONE_LEVEL, containerCn); Collection<T> objects = new ArrayList<T>(); if (ServerUtils.isNullOrEmpty(containerDn) == false) { List<T> objectsCollection = iLdapObject.searchObjects(connection, containerDn, LdapScope.SCOPE_ONE_LEVEL, additionalFilter); if ((objectsCollection != null) && (objectsCollection.size() > 0)) { for (T object : objectsCollection) { if (callback != null) { callback.processObjectSaved(connection, iLdapObject.getDnFromObject(containerDn, object), object); } objects.add(object); } } } return objects; } private void createSystemDomainIdentityProviderForTenant(ILdapConnectionEx connection, String tenantName, String tenantsRootDn, String adminAccountName, char[] adminPwd) throws Exception { IdmServerConfig settings = IdmServerConfig.getInstance(); String systemDomainName = settings.getTenantsSystemDomainName(tenantName); ServerIdentityStoreData serverIdentityStoreData = new ServerIdentityStoreData(DomainType.SYSTEM_DOMAIN, systemDomainName); Tenant tenant = this.getTenant(connection, tenantName); serverIdentityStoreData.setProviderType(settings.getSystemDomainIdentityStoreType()); serverIdentityStoreData.setAuthenticationType(settings.getSystemDomainAuthenticationType()); serverIdentityStoreData.setSearchTimeoutSeconds(settings.getSystemDomainSearchTimeout()); serverIdentityStoreData.setUserBaseDn(ServerUtils.getDomainDN(systemDomainName)); serverIdentityStoreData.setGroupBaseDn(ServerUtils.getDomainDN(systemDomainName)); serverIdentityStoreData.setUserName(settings.getTenantAdminUserName(tenantName, adminAccountName)); serverIdentityStoreData.setPassword(String.valueOf(adminPwd)); serverIdentityStoreData.setConnectionStrings( ServerUtils.getConnectionStringFromUris(settings.getSystemDomainConnectionInfo())); serverIdentityStoreData.setAttributeMap(settings.getSystemDomainAttributesMap()); // if it is a service provider system domain if (tenantName.equalsIgnoreCase(settings.getDirectoryConfigStoreDomain())) { if (settings.isServiceProviderSystemDomainInBackCompatMode() == true) { serverIdentityStoreData.setAlias(settings.getServiceProviderSystemDomianAlias()); serverIdentityStoreData.setUpnSuffixes( Collections.<String>singletonList(settings.getServiceProviderSystemDomianAlias())); } } try { enCryptPassword(tenant._tenantKey, serverIdentityStoreData.getExtendedIdentityStoreData()); DirectoryConfigStore.SaveIdentityProviderConfig(this, connection, tenantsRootDn, serverIdentityStoreData); } catch (AlreadyExistsLdapException ex) { throw new DuplicateProviderException(serverIdentityStoreData.getName(), (String) null); } } private LdapValue[] getTenantProperty(String tenantName, String propertyName) throws Exception { ILdapConnectionEx connection = this.getConnection(); try { String tenantsRootDn = this.lookupTenantsRootDn(connection, tenantName); if (ServerUtils.isNullOrEmpty(tenantsRootDn)) { throw new RuntimeException(String.format("Tenant '%s' does not exist.", tenantName)); } return DirectoryConfigStore.getTenantProperty(connection, tenantsRootDn, propertyName); } finally { connection.close(); } } private static LdapValue[] getTenantProperty(ILdapConnectionEx connection, String tenantsRootDn, String propertyName) throws Exception { return TenantLdapObject.getInstance().getObjectProperty(connection, tenantsRootDn, LdapScope.SCOPE_BASE, null, propertyName); } private void setTenantProperty(String tenantName, String propertyName, LdapValue[] value) throws Exception { ILdapConnectionEx connection = this.getConnection(); try { String tenantsRootDn = this.lookupTenantsRootDn(connection, tenantName); if (ServerUtils.isNullOrEmpty(tenantsRootDn)) { throw new NoSuchTenantException(String.format("Tenant '%s' does not exist.", tenantName)); } logger.info( "tenantsRootDn: " + tenantsRootDn + ", property name: " + propertyName + ", value: " + value); setTenantProperty(connection, tenantsRootDn, propertyName, value); } finally { connection.close(); } } private static void setTenantProperty(ILdapConnectionEx connection, String tenantsRootDn, String propertyName, LdapValue[] value) throws Exception { TenantLdapObject.getInstance().setObjectPropertyValue(connection, tenantsRootDn, propertyName, value); } // returns tenant's root dn if exists... private String ensureTenantExists(ILdapConnectionEx connection, String tenantName) { String tenantsRootDn = this.lookupTenantsRootDn(connection, tenantName); if (ServerUtils.isNullOrEmpty(tenantsRootDn)) { throw new IllegalArgumentException(String.format("Tenant '%s' does not exist.", tenantName)); } return tenantsRootDn; } private String getSystemTenantCredsDn() { String lduGuid = Directory.GetLocalLduGuid(); ValidateUtil.validateNotEmpty(lduGuid, "LduGuid"); return String.format("CN=%s,CN=Ldus,CN=ComponentManager,%s", lduGuid, this.getRootDn()); } private String getSystemTenantLduDn() { return String.format("CN=Ldus,CN=ComponentManager,%s", this.getRootDn()); } private String getTenantCredentialCn(int index) { return String.format("%s-%d", this.tenantCredNamePrefix, index); } private String getTenantCredentialDn(int index, String tenantRootDn) { return String.format("CN=%s,%s", getTenantCredentialCn(index), tenantRootDn); } private String getTenantTrustedCertChainCn(int index) { return String.format("%s-%d", this.tenantTrustedCertChainPrefix, index); } private String lookupTenantsRootDn(ILdapConnectionEx connection, String tenantName) { String tenantsRootDn = null; String rootSystemConfigDn = this.getRootSystemConfigDn(connection, false); if (ServerUtils.isNullOrEmpty(rootSystemConfigDn) == false) { TenantsContainerLdapObject tenantsConfigObject = TenantsContainerLdapObject.getInstance(); String tenantsContainerDn = tenantsConfigObject.lookupObject(connection, rootSystemConfigDn, LdapScope.SCOPE_ONE_LEVEL, tenantsConfigObject.getCn(TenantsContainerLdapObject.CONTAINER_TENANTS)); if (ServerUtils.isNullOrEmpty(tenantsContainerDn) == false) { TenantLdapObject tenantConfig = TenantLdapObject.getInstance(); tenantsRootDn = tenantConfig.lookupObject(connection, tenantsContainerDn, LdapScope.SCOPE_ONE_LEVEL, tenantName); } } return tenantsRootDn; } private Collection<String> lookupAllTenantsDn(ILdapConnectionEx connection) { String rootSystemConfigDn = this.getRootSystemConfigDn(connection, false); Collection<String> result = new ArrayList<String>(); if (ServerUtils.isNullOrEmpty(rootSystemConfigDn) == false) { TenantsContainerLdapObject tenantsConfigObject = TenantsContainerLdapObject.getInstance(); // get tenant container dn: // "cn=Tenants,cn=IdentityManager,cn=services,dc=vsphere,dc=local" String tenantsContainerDn = tenantsConfigObject.lookupObject(connection, rootSystemConfigDn, LdapScope.SCOPE_ONE_LEVEL, tenantsConfigObject.getCn(TenantsContainerLdapObject.CONTAINER_TENANTS)); if (ServerUtils.isNullOrEmpty(tenantsContainerDn) == false) { List<Tenant> allTenants = TenantLdapObject.getInstance().searchObjects(connection, tenantsContainerDn, LdapScope.SCOPE_ONE_LEVEL); if ((allTenants != null) && (allTenants.size() > 0)) { for (Tenant tenant : allTenants) { result.add(tenant.getName()); } } } } return result; } private ILdapConnectionEx getConnection() throws Exception { IdmServerConfig config = IdmServerConfig.getInstance(); return ServerUtils.getLdapConnectionByURIs(this._uris, config.getDirectoryConfigStoreUserName(), config.getDirectoryConfigStorePassword(), config.getDirectoryConfigStoreAuthType(), false); } private String getRootSystemConfigDn(ILdapConnectionEx connection, boolean createIfNotExists) { // services->IdentityManager ContainerLdapObject containerConfigObject = ContainerLdapObject.getInstance(); String identityManagerDn = null; String servicesDn = DirectoryConfigStore.ensureObjectExists(connection, this.getRootDn(), containerConfigObject, ContainerLdapObject.CONTAINER_SERVICES, createIfNotExists); if (ServerUtils.isNullOrEmpty(servicesDn) == false) { identityManagerDn = DirectoryConfigStore.ensureObjectExists(connection, servicesDn, containerConfigObject, ContainerLdapObject.CONTAINER_IDENTITY_MANAGER, createIfNotExists); } return identityManagerDn; } private static <T> String ensureObjectExists(ILdapConnectionEx connection, String parentDn, ILdapObject<T> iLdapObject, T object, boolean createIfNotExists) { String objectDn = iLdapObject.lookupObject(connection, parentDn, LdapScope.SCOPE_ONE_LEVEL, iLdapObject.getCn(object)); if ((ServerUtils.isNullOrEmpty(objectDn) == true) && (createIfNotExists == true)) { objectDn = iLdapObject.getDnFromObject(parentDn, object); iLdapObject.createObject(connection, objectDn, object); } return objectDn; } private String getRootDn() { return this._configRootDn; } private void enCryptPassword(String tenantKey, IIdentityStoreDataEx idsDataEx) throws Exception { if (idsDataEx != null) { CryptoAESE cryptoAES = new CryptoAESE(tenantKey); String secret = idsDataEx.getPassword(); if (secret != null) { idsDataEx.setPassword(new BASE64Encoder().encode(cryptoAES.encrypt(secret))); } } } private void deCryptPassword(CryptoAESE cryptoAES, IIdentityStoreDataEx idsDataEx) throws Exception { if (idsDataEx != null) { String secret = idsDataEx.getPassword(); if (secret != null) { idsDataEx.setPassword(cryptoAES.decrypt(new BASE64Decoder().decodeBuffer(secret))); } } } }