Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Integrate IdentityKeyStoreResolver #160

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,20 @@
*/
package org.wso2.carbon.identity.sts.passive.custom.provider;

import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.util.Properties;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.wss4j.common.crypto.Merlin;
import org.apache.wss4j.common.crypto.PasswordEncryptor;
import org.apache.wss4j.common.ext.WSSecurityException;
import org.wso2.carbon.base.MultitenantConstants;
import org.wso2.carbon.core.util.KeyStoreManager;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.identity.core.IdentityKeyStoreResolver;
import org.wso2.carbon.identity.core.util.IdentityKeyStoreResolverConstants;
import org.wso2.carbon.identity.core.util.IdentityKeyStoreResolverException;

import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.util.Properties;

public class CustomCryptoProvider extends Merlin {

Expand Down Expand Up @@ -58,7 +60,7 @@ public CustomCryptoProvider(Properties properties, ClassLoader loader,
}

/**
* Loads the keystore from an InputStream or from the KeyStoreManager if it is a tenant.
* Loads the keystore from IdentityKeyStoreResolver.
*
* @param input InputStream which the key store should be read from.
* @param storepass Password of the key store.
Expand All @@ -70,31 +72,16 @@ public CustomCryptoProvider(Properties properties, ClassLoader loader,
protected KeyStore load(InputStream input, String storepass, String provider, String type)
throws WSSecurityException {

KeyStore keyStore;

String tenantId = this.properties.getProperty(TENANT_ID_PROP);
String keyStoreName = this.properties.getProperty(KEY_STORE_NAME_PROP);

log.debug("Loading keystore...");
if (!String.valueOf(MultitenantConstants.SUPER_TENANT_ID).equals(tenantId)
&& keyStoreName != null) {
// Loads the keystore in a custom way since the tenant keystore does not have a location.
if (log.isDebugEnabled()) {
log.debug("Loading keystore for tenant with id: " + tenantId + ".");
}
KeyStoreManager keyStoreManager = KeyStoreManager.getInstance(Integer.parseInt(tenantId));
try {
keyStore = keyStoreManager.getKeyStore(keyStoreName);
} catch (Exception exception) {
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, exception, "failedCredentialLoad");
}
} else {
// Loads the keystore in the default way since the keystore has a location.
if (log.isDebugEnabled()) {
log.debug("Loading keystore for super tenant.");
}
keyStore = super.load(input, storepass, provider, type);
try {
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
KeyStore keyStore = IdentityKeyStoreResolver.getInstance().getKeyStore(
tenantDomain, IdentityKeyStoreResolverConstants.InboundProtocol.WS_FEDERATION);
log.debug("Successfully retrieved the keystore.");
return keyStore;
} catch (IdentityKeyStoreResolverException e) {
log.debug("Error occurred when loading keystore.", e);
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e);
}
return keyStore;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,23 +50,24 @@
import org.wso2.carbon.base.ServerConfiguration;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.core.RegistryResources;
import org.wso2.carbon.core.util.KeyStoreManager;
import org.wso2.carbon.identity.application.authentication.framework.util.FrameworkConstants;
import org.wso2.carbon.identity.application.common.model.FederatedAuthenticatorConfig;
import org.wso2.carbon.identity.application.common.model.IdentityProvider;
import org.wso2.carbon.identity.application.common.model.Property;
import org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants;
import org.wso2.carbon.identity.application.common.util.IdentityApplicationManagementUtil;
import org.wso2.carbon.identity.base.IdentityConstants;
import org.wso2.carbon.identity.core.util.IdentityTenantUtil;
import org.wso2.carbon.identity.core.IdentityKeyStoreResolver;
import org.wso2.carbon.identity.core.util.IdentityKeyStoreResolverConstants;
import org.wso2.carbon.identity.core.util.IdentityKeyStoreResolverException;
import org.wso2.carbon.identity.core.util.IdentityKeyStoreResolverUtil;
import org.wso2.carbon.identity.core.util.IdentityUtil;
import org.wso2.carbon.identity.sts.passive.RequestToken;
import org.wso2.carbon.identity.sts.passive.custom.handler.CustomClaimsHandler;
import org.wso2.carbon.identity.sts.passive.custom.handler.PasswordCallbackHandler;
import org.wso2.carbon.identity.sts.passive.custom.provider.CustomAttributeProvider;
import org.wso2.carbon.identity.sts.passive.custom.provider.CustomAuthenticationProvider;
import org.wso2.carbon.idp.mgt.IdentityProviderManager;
import org.wso2.carbon.utils.security.KeystoreUtils;

import java.net.URI;
import java.security.Principal;
Expand All @@ -77,8 +78,6 @@
import java.util.Map;
import java.util.Properties;

import static org.wso2.carbon.identity.sts.passive.PassiveRequestorConstants.KEY_ALIAS_KEY;
import static org.wso2.carbon.identity.sts.passive.PassiveRequestorConstants.KEY_STORE_PASSWORD_KEY;
import static org.wso2.carbon.identity.sts.passive.PassiveRequestorConstants.STS_DIGEST_ALGORITHM_KEY;
import static org.wso2.carbon.identity.sts.passive.PassiveRequestorConstants.STS_SIGNATURE_ALGORITHM_KEY;
import static org.wso2.carbon.identity.sts.passive.PassiveRequestorConstants.STS_TIME_TO_LIVE_KEY;
Expand Down Expand Up @@ -196,34 +195,21 @@ public static void addService(TokenIssueOperation issueOperation, String applies
*/
public static void addSTSProperties(TokenIssueOperation issueOperation) throws Exception {

ServerConfiguration serverConfig = ServerConfiguration.getInstance();
Crypto crypto = CryptoFactory.getInstance(getEncryptionProperties());

String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();

String[] aliasAndPassword = getKeyStoreAliasAndKeyStorePassword(serverConfig, tenantId, tenantDomain);
String keyAlias = aliasAndPassword[0];
String keyStorePassword = aliasAndPassword[1];
String keyStoreFileLocation = serverConfig
.getFirstProperty(RegistryResources.SecurityManagement.SERVER_PRIMARY_KEYSTORE_FILE);
String keyStoreName = null;

String signatureAlgorithm = serverConfig.getFirstProperty(STS_SIGNATURE_ALGORITHM_KEY);
String digestAlgorithm = serverConfig.getFirstProperty(STS_DIGEST_ALGORITHM_KEY);

String keyAlias = IdentityKeyStoreResolver.getInstance().getKeyStoreConfig(
tenantDomain,
IdentityKeyStoreResolverConstants.InboundProtocol.WS_FEDERATION,
RegistryResources.SecurityManagement.CustomKeyStore.PROP_KEY_ALIAS);

if (keyAlias == null) {
throw new STSException("Private key alias cannot be null.");
}

if (MultitenantConstants.SUPER_TENANT_ID != tenantId) {
keyStoreName = generateKSNameFromDomainName(tenantDomain);
tenantId = IdentityTenantUtil.getTenantId(tenantDomain);
}

Crypto crypto = CryptoFactory
.getInstance(getEncryptionProperties(keyStoreFileLocation,
keyStorePassword, tenantId, keyStoreName));
ServerConfiguration serverConfig = ServerConfiguration.getInstance();
String signatureAlgorithm = serverConfig.getFirstProperty(STS_SIGNATURE_ALGORITHM_KEY);
String digestAlgorithm = serverConfig.getFirstProperty(STS_DIGEST_ALGORITHM_KEY);

STSPropertiesMBean stsProperties = new StaticSTSProperties();
stsProperties.setEncryptionCrypto(crypto);
Expand Down Expand Up @@ -260,61 +246,57 @@ public static String[] getKeyStoreAliasAndKeyStorePassword(

String[] aliasAndPassword = new String[2];

String keyStorePassword;
String keyAlias;

boolean isSuperTenantDomain = (MultitenantConstants.SUPER_TENANT_ID == tenantId);
if (isSuperTenantDomain) {
keyAlias = serverConfig.getFirstProperty(KEY_ALIAS_KEY);
keyStorePassword = serverConfig.getFirstProperty(KEY_STORE_PASSWORD_KEY);
} else {
String keyStoreName = generateKSNameFromDomainName(tenantDomain);
keyAlias = tenantDomain;
keyStorePassword = KeyStoreManager.getInstance(tenantId).getKeyStorePassword(keyStoreName);
}

aliasAndPassword[0] = keyAlias;
aliasAndPassword[1] = keyStorePassword;
aliasAndPassword[0] = IdentityKeyStoreResolver.getInstance().getKeyStoreConfig(
tenantDomain,
IdentityKeyStoreResolverConstants.InboundProtocol.WS_FEDERATION,
RegistryResources.SecurityManagement.CustomKeyStore.PROP_KEY_ALIAS);
aliasAndPassword[1] = IdentityKeyStoreResolver.getInstance().getKeyStoreConfig(
tenantDomain,
IdentityKeyStoreResolverConstants.InboundProtocol.WS_FEDERATION,
RegistryResources.SecurityManagement.CustomKeyStore.PROP_PASSWORD);

return aliasAndPassword;
}

/**
* Generate a key store name from the given domain name.
*
* @param tenantDomain The tenant domain.
* @return The name of the key store.
*/
private static String generateKSNameFromDomainName(String tenantDomain) {

return KeystoreUtils.getKeyStoreFileLocation(tenantDomain);
}

/**
* Set the encryption properties to a properties object and return it.
*
* @param keyStoreFileLocation Location of the key store file.
* @param keyStorePassword Password of the key store.
* @param tenantId Id of the tenant(Needed for the tenant flow).
* @param keyStoreName Name of the key store(Needed for the tenant flow).
* @return Properties object containing the encryption properties.
*/
private static Properties getEncryptionProperties(String keyStoreFileLocation,
String keyStorePassword,
int tenantId, String keyStoreName) {
private static Properties getEncryptionProperties() throws IdentityKeyStoreResolverException {

String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();

String keyStoreFileLocation = IdentityKeyStoreResolver.getInstance().getKeyStoreConfig(
tenantDomain,
IdentityKeyStoreResolverConstants.InboundProtocol.WS_FEDERATION,
RegistryResources.SecurityManagement.CustomKeyStore.PROP_LOCATION);
String keyStorePassword = IdentityKeyStoreResolver.getInstance().getKeyStoreConfig(
tenantDomain,
IdentityKeyStoreResolverConstants.InboundProtocol.WS_FEDERATION,
RegistryResources.SecurityManagement.CustomKeyStore.PROP_PASSWORD);

String tenantKeyStoreName = IdentityKeyStoreResolverUtil.buildTenantKeyStoreName(tenantDomain);

if (StringUtils.isEmpty(keyStoreFileLocation) || StringUtils.isEmpty(keyStorePassword)) {
throw new STSException("Error occoured when building encryption properties." +
" One or more keystore properties are null or empty.");
}

Properties properties = new Properties();
properties.put(
"org.apache.wss4j.crypto.provider", "org.wso2.carbon.identity.sts.passive.custom.provider.CustomCryptoProvider"
);
properties.put("org.apache.wss4j.crypto.merlin.keystore.password", keyStorePassword);

properties.put("org.apache.wss4j.crypto.provider",
"org.wso2.carbon.identity.sts.passive.custom.provider.CustomCryptoProvider");
properties.put("org.apache.wss4j.crypto.merlin.keystore.file", keyStoreFileLocation);
properties.put("org.apache.wss4j.crypto.merlin.keystore.password", keyStorePassword);

/* This if block will execute in a tenant scenario and the purpose is to set the key store
manually since it does not have a specific location. Refer CustomCryptoProvider class. */
if (keyStoreName != null) {
// If the keystore is a tenant keystore, it cannot be loaded from the file location.
// Passing tenant id and keystore name for the keystore to be loaded using the CustomCryptoProvider class.
if (MultitenantConstants.SUPER_TENANT_ID != tenantId && keyStoreFileLocation.equals(tenantKeyStoreName)) {
properties.put("org.apache.wss4j.crypto.merlin.keystore.tenant.id", String.valueOf(tenantId));
properties.put("org.apache.wss4j.crypto.merlin.keystore.name", keyStoreName);
properties.put("org.apache.wss4j.crypto.merlin.keystore.name", tenantKeyStoreName);
properties.put("org.apache.wss4j.crypto.merlin.keystore.file", "");
}

return properties;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,12 @@
import org.apache.rahas.impl.AbstractIssuerConfig;
import org.apache.rahas.impl.SAMLTokenIssuerConfig;
import org.apache.rahas.impl.TokenIssuerUtil;
import org.wso2.carbon.base.MultitenantConstants;
import org.wso2.carbon.base.ServerConfiguration;
import org.wso2.carbon.context.CarbonContext;
import org.wso2.carbon.core.RegistryResources;
import org.wso2.carbon.core.deployment.DeploymentInterceptor;
import org.wso2.carbon.core.util.KeyStoreManager;
import org.wso2.carbon.core.util.KeyStoreUtil;
import org.wso2.carbon.identity.core.IdentityKeyStoreResolver;
import org.wso2.carbon.identity.core.util.IdentityKeyStoreResolverConstants;
import org.wso2.carbon.registry.core.Registry;
import org.wso2.carbon.registry.core.Resource;
import org.wso2.carbon.registry.core.utils.RegistryUtils;
Expand All @@ -49,9 +48,7 @@
import org.wso2.carbon.identity.sts.common.util.ServerCrypto;
import org.wso2.carbon.sts.internal.STSServiceDataHolder;
import org.wso2.carbon.utils.ServerConstants;
import org.wso2.carbon.utils.security.KeystoreUtils;

import java.security.KeyStore;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
Expand Down Expand Up @@ -104,6 +101,7 @@ public static void updateSTSService(AxisConfiguration config) throws Exception {
ServerConfiguration serverConfig = null;

int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId();
String tenantDomain = CarbonContext.getThreadLocalCarbonContext().getTenantDomain();

configRegistry = STSServiceDataHolder.getInstance().getRegistryService().getConfigSystemRegistry(tenantId);
governRegistry = STSServiceDataHolder.getInstance().getRegistryService().getGovernanceSystemRegistry(tenantId);
Expand All @@ -115,47 +113,16 @@ public static void updateSTSService(AxisConfiguration config) throws Exception {
return;
}

serverConfig = ServerConfiguration.getInstance();
admin = new KeyStoreAdmin(tenantId, governRegistry);

if (MultitenantConstants.SUPER_TENANT_ID == tenantId) {
keyPassword = serverConfig.getFirstProperty(SECURITY_KEY_STORE_KEY_PASSWORD);
keystores = admin.getKeyStores(true);

for (int i = 0; i < keystores.length; i++) {
if (KeyStoreUtil.isPrimaryStore(keystores[i].getKeyStoreName())) {
keyStoreName = keystores[i].getKeyStoreName();
privateKeyAlias = KeyStoreUtil.getPrivateKeyAlias(KeyStoreManager.getInstance(
MultitenantConstants.SUPER_TENANT_ID)
.getKeyStore(keyStoreName));
break;
}
}
} else {
// this is not the proper way to find out the primary key store of the tenant. We need
// check a better way TODO
String tenantDomain = CarbonContext.getThreadLocalCarbonContext().getTenantDomain();
if (tenantDomain == null) {
tenantDomain = STSServiceDataHolder.getInstance().getRealmService().
getTenantManager().getDomain(tenantId);
}

if (tenantDomain != null) {
// assuming domain always in this format -> example.com
keyStoreName = KeystoreUtils.getKeyStoreFileLocation(tenantDomain);
KeyStore keyStore = KeyStoreManager.getInstance(tenantId).getKeyStore(keyStoreName);
if (keyStore != null) {
privateKeyAlias = KeyStoreUtil.getPrivateKeyAlias(keyStore);
keyPassword = KeyStoreManager.getInstance(tenantId).getKeyStorePassword(keyStoreName);
} else {
log.warn("No key store is exist as " + keyStoreName + ". STS would be fail");
}
} else {
throw new Exception("Tenant Domain can not be null");
}

}
keyStoreName = IdentityKeyStoreResolver.getInstance()
.getKeyStoreName(tenantDomain, IdentityKeyStoreResolverConstants.InboundProtocol.WS_TRUST);
privateKeyAlias = IdentityKeyStoreResolver.getInstance().getKeyStoreConfig(tenantDomain,
IdentityKeyStoreResolverConstants.InboundProtocol.WS_TRUST,
RegistryResources.SecurityManagement.CustomKeyStore.PROP_KEY_ALIAS);
keyPassword = IdentityKeyStoreResolver.getInstance().getKeyStoreConfig(tenantDomain,
IdentityKeyStoreResolverConstants.InboundProtocol.WS_TRUST,
RegistryResources.SecurityManagement.CustomKeyStore.PROP_PASSWORD);

serverConfig = ServerConfiguration.getInstance();
issuerName = serverConfig.getFirstProperty(STS_HOST_NAME);

if (StringUtils.isBlank(issuerName)) {
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@
</identity.inbound.auth.sts.package.export.version>
<inbound.auth.openid.version>5.6.0</inbound.auth.openid.version>

<carbon.kernel.version>4.9.23</carbon.kernel.version>
<carbon.kernel.version>4.10.19</carbon.kernel.version>
<carbon.kernel.feature.version>4.7.0</carbon.kernel.feature.version>
<carbon.xfer.package.version>4.2.0</carbon.xfer.package.version>
<xmlsec.version>2.3.4</xmlsec.version>
Expand Down
Loading