Made changes to allow us to fail-over to a different identity store if

a communication error is encountered.

Lowered the log level of a couple of logs that were littering the log
files.
This commit is contained in:
Juan Carlos Luciani 2007-03-21 17:51:54 +00:00
parent 3836edc9d7
commit 67485b5388
6 changed files with 345 additions and 190 deletions

View File

@ -31,6 +31,7 @@ import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.ServiceUnavailableException;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
@ -715,65 +716,97 @@ public final class CasaIdentityToken implements IdentityToken
env.put(Realm.REALM_CONFIG_LOCATION, svcConfig.getSetting(SvcConfig.IdentityAbstractionConfigFile));
env.put(Realm.REALM_SELECTOR, sourceName);
DirContext ctx = new InitialDirContext(env);
// Setup a string buffer for building the IdentityToken, notice for now
// we are not going to wrap the identity token.
StringBuffer sb = new StringBuffer();
sb.append(ProtoDefs.xmlDeclaration); sb.append("\r\n");
sb.append("<"); sb.append(casaIdentTokElementName); sb.append(">"); sb.append("\r\n");
sb.append("<"); sb.append(idElementName); sb.append(">"); sb.append(identityId); sb.append("</"); sb.append(idElementName); sb.append(">\r\n");
sb.append("<"); sb.append(sourceNameElementName); sb.append(">"); sb.append(sourceName); sb.append("</"); sb.append(sourceNameElementName); sb.append(">\r\n");
sb.append("<"); sb.append(sourceUrlElementName); sb.append(">"); sb.append(m_sourceUrl); sb.append("</"); sb.append(sourceUrlElementName); sb.append(">\r\n");
sb.append("<"); sb.append(targetServiceElementName); sb.append(">"); sb.append(m_service); sb.append("</"); sb.append(targetServiceElementName); sb.append(">\r\n");
sb.append("<"); sb.append(targetHostElementName); sb.append(">"); sb.append(m_host); sb.append("</"); sb.append(targetHostElementName); sb.append(">\r\n");
sb.append("<"); sb.append(attributesElementName); sb.append(">\r\n");
// Get the necessary attributes of the specified services in the identity token
String[] attributesNeeded = m_idenTokenConfig.getAttributes();
boolean encryptAttributes = "true".equalsIgnoreCase(m_idenTokenConfig.getSetting(IdenTokenConfig.EncryptAttributes));
Attributes attrs = ctx.getAttributes(identityId, attributesNeeded);
// Now append the attributes to the token
for (NamingEnumeration ae = attrs.getAll(); ae.hasMore();)
while (true)
{
javax.naming.directory.Attribute attr = (javax.naming.directory.Attribute) ae.next();
NamingEnumeration<?> enumeration = attr.getAll();
while (enumeration.hasMore())
// Instantiate DirContext watching for an exception since it
// would be an indication that we should not retry the
// operation.
DirContext ctx;
try
{
Object attrValue = enumeration.next();
m_attributes.put(attr.getID(), attrValue);
m_log.debug("initialize()- Including attribute " + attr.getID());
// Encrypt the attribute if necessary
if (encryptAttributes)
{
// tbd - Encrypt the attributes using the services public key, let the mechanism
// be configurable. The service's certificate should be Base64 encoded as a setting
// of the identoken.settings file.
}
else
{
// Proceed based on the attribute value type
if (attrValue instanceof byte[])
{
// The attribute value is of type byte[], we need to encode it.
sb.append("<"); sb.append(attr.getID()); sb.append(" type=\"binary\" encoding=\"base64\">"); sb.append(new String(Base64Coder.encode((byte[]) attrValue))); sb.append("</"); sb.append(attr.getID()); sb.append(">\r\n");
m_log.debug("initialize()- Attribute " + attr.getID() + "included as " + new String(Base64Coder.encode((byte[]) attrValue)));
}
else
{
// Assume the attribute value is of type String
sb.append("<"); sb.append(attr.getID()); sb.append(">"); sb.append(attrValue); sb.append("</"); sb.append(attr.getID()); sb.append(">\r\n");
}
}
ctx = new InitialDirContext(env);
}
}
sb.append("</" + attributesElementName + ">" + "\r\n");
sb.append("</" + casaIdentTokElementName + ">" + "\r\n");
catch (Exception e)
{
m_log.warn("initialize(): Exception caught instantiating DirContext, msg = " + e.getMessage());
m_token = sb.toString();
// Stop retrying
break;
}
// Setup a string buffer for building the IdentityToken, notice for now
// we are not going to wrap the identity token.
StringBuffer sb = new StringBuffer();
sb.append(ProtoDefs.xmlDeclaration); sb.append("\r\n");
sb.append("<"); sb.append(casaIdentTokElementName); sb.append(">"); sb.append("\r\n");
sb.append("<"); sb.append(idElementName); sb.append(">"); sb.append(identityId); sb.append("</"); sb.append(idElementName); sb.append(">\r\n");
sb.append("<"); sb.append(sourceNameElementName); sb.append(">"); sb.append(sourceName); sb.append("</"); sb.append(sourceNameElementName); sb.append(">\r\n");
sb.append("<"); sb.append(sourceUrlElementName); sb.append(">"); sb.append(m_sourceUrl); sb.append("</"); sb.append(sourceUrlElementName); sb.append(">\r\n");
sb.append("<"); sb.append(targetServiceElementName); sb.append(">"); sb.append(m_service); sb.append("</"); sb.append(targetServiceElementName); sb.append(">\r\n");
sb.append("<"); sb.append(targetHostElementName); sb.append(">"); sb.append(m_host); sb.append("</"); sb.append(targetHostElementName); sb.append(">\r\n");
sb.append("<"); sb.append(attributesElementName); sb.append(">\r\n");
// Get the necessary attributes of the specified services in the identity token
// watching for a service unavailable exception as an indication that we should
// retry the operation.
try
{
String[] attributesNeeded = m_idenTokenConfig.getAttributes();
boolean encryptAttributes = "true".equalsIgnoreCase(m_idenTokenConfig.getSetting(IdenTokenConfig.EncryptAttributes));
Attributes attrs = ctx.getAttributes(identityId, attributesNeeded);
// Now append the attributes to the token
for (NamingEnumeration ae = attrs.getAll(); ae.hasMore();)
{
javax.naming.directory.Attribute attr = (javax.naming.directory.Attribute) ae.next();
NamingEnumeration<?> enumeration = attr.getAll();
while (enumeration.hasMore())
{
Object attrValue = enumeration.next();
m_attributes.put(attr.getID(), attrValue);
m_log.debug("initialize()- Including attribute " + attr.getID());
// Encrypt the attribute if necessary
if (encryptAttributes)
{
// tbd - Encrypt the attributes using the services public key, let the mechanism
// be configurable. The service's certificate should be Base64 encoded as a setting
// of the identoken.settings file.
}
else
{
// Proceed based on the attribute value type
if (attrValue instanceof byte[])
{
// The attribute value is of type byte[], we need to encode it.
sb.append("<"); sb.append(attr.getID()); sb.append(" type=\"binary\" encoding=\"base64\">"); sb.append(new String(Base64Coder.encode((byte[]) attrValue))); sb.append("</"); sb.append(attr.getID()); sb.append(">\r\n");
m_log.debug("initialize()- Attribute " + attr.getID() + "included as " + new String(Base64Coder.encode((byte[]) attrValue)));
}
else
{
// Assume the attribute value is of type String
sb.append("<"); sb.append(attr.getID()); sb.append(">"); sb.append(attrValue); sb.append("</"); sb.append(attr.getID()); sb.append(">\r\n");
}
}
}
}
sb.append("</" + attributesElementName + ">" + "\r\n");
sb.append("</" + casaIdentTokElementName + ">" + "\r\n");
m_token = sb.toString();
}
catch (ServiceUnavailableException e)
{
m_log.warn("initialize()- ServiceUnavailable exception caught looking up attributes, msg = " + e.getMessage());
// Retry the operation
continue;
}
// No need to retry
break;
}
}
catch (NamingException e)
{

View File

@ -263,7 +263,7 @@ public final class EnabledSvcsConfig
}
catch (Exception e)
{
m_log.warn("Constructor()- Exception accessing " + serviceFolder + File.separator + m_authTokenSettingsFileName + " Exception=" + e.toString());
m_log.debug("Constructor()- Exception accessing " + serviceFolder + File.separator + m_authTokenSettingsFileName + " Exception=" + e.toString());
}
try
@ -272,7 +272,7 @@ public final class EnabledSvcsConfig
}
catch (Exception e)
{
m_log.warn("Constructor()- Exception accessing " + serviceFolder + File.separator + m_idenTokenSettingsFileName + " Exception=" + e.toString());
m_log.debug("Constructor()- Exception accessing " + serviceFolder + File.separator + m_idenTokenSettingsFileName + " Exception=" + e.toString());
}
// Make sure that we have a policy file

View File

@ -30,6 +30,7 @@ import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.ServiceUnavailableException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchResult;
@ -212,71 +213,103 @@ public final class Krb5Authenticate implements AuthMechanism, Serializable
env.put(Realm.REALM_CONFIG_LOCATION, m_svcConfig.getSetting(SvcConfig.IdentityAbstractionConfigFile));
env.put(Realm.REALM_SELECTOR, authReqMsg.getRealm());
DirContext ctx = new InitialDirContext(env);
// Now search for a user with a matching kerberos principal name.
//
// Set up a search control so that the search is scoped to the sub-tree
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
// Obtain the search roots
String[] searchRoots = m_svcConfig.m_realmsInfo.getSearchRoots(authReqMsg.getRealm());
if (searchRoots == null)
while (true)
{
// No configured search roots
searchRoots = new String[] {""};
}
// Determine the search string to be utilized based on the type of directory
// associated with the realm.
String searchString;
String realmType = m_svcConfig.m_realmsInfo.getType(authReqMsg.getRealm());
if (realmType != null)
{
if (realmType.equalsIgnoreCase(RealmsInfo.eDirectoryRealm))
searchString = "(krbPrincipalName={0})";
else if (realmType.equalsIgnoreCase(RealmsInfo.ActiveDirectoryRealm))
searchString = "(userPrincipalName={0})";
else
// Instantiate DirContext watching for an exception since it
// would be an indication that we should not retry the
// operation.
DirContext ctx;
try
{
m_log.warn("invoke()- Unsupported realm type " + realmType);
throw new Exception("Realm configuration error");
ctx = new InitialDirContext(env);
}
}
else
{
m_log.warn("invoke()- Failed to obtain realm type for realm " + authReqMsg.getRealm());
throw new Exception("Realm configuration error");
}
// Go through the search roots stopping if the identity is resolved.
for (int i = 0; i < searchRoots.length && identId == null; i++)
{
// Perform search for this root
NamingEnumeration<SearchResult> answer = ctx.search(searchRoots[i],
searchString,
new String[] {krb5Token.getPrincipalName()},
controls);
// Proceed based on the result of the search
if (answer.hasMore())
catch (Exception e)
{
// The search succeeded, set the identity id.
SearchResult sr = answer.next();
if (searchRoots[i].equals(""))
m_log.warn("invoke(): Exception caught instantiating DirContext, msg = " + e.getMessage());
// Stop retrying
break;
}
// Now search for a user with a matching kerberos principal name
// watching for a service unavailable exception as an indication that we
// should retry the operation.
//
// Set up a search control so that the search is scoped to the sub-tree
try
{
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
// Obtain the search roots
String[] searchRoots = m_svcConfig.m_realmsInfo.getSearchRoots(authReqMsg.getRealm());
if (searchRoots == null)
{
identId = sr.getNameInNamespace();
// No configured search roots
searchRoots = new String[] {""};
}
// Determine the search string to be utilized based on the type of directory
// associated with the realm.
String searchString;
String realmType = m_svcConfig.m_realmsInfo.getType(authReqMsg.getRealm());
if (realmType != null)
{
if (realmType.equalsIgnoreCase(RealmsInfo.eDirectoryRealm))
searchString = "(krbPrincipalName={0})";
else if (realmType.equalsIgnoreCase(RealmsInfo.ActiveDirectoryRealm))
searchString = "(userPrincipalName={0})";
else
{
m_log.warn("invoke()- Unsupported realm type " + realmType);
throw new Exception("Realm configuration error");
}
}
else
{
identId = sr.getName() + "," + searchRoots[i];
m_log.warn("invoke()- Failed to obtain realm type for realm " + authReqMsg.getRealm());
throw new Exception("Realm configuration error");
}
// Go through the search roots stopping if the identity is resolved.
for (int i = 0; i < searchRoots.length && identId == null; i++)
{
// Perform search for this root
NamingEnumeration<SearchResult> answer = ctx.search(searchRoots[i],
searchString,
new String[] {krb5Token.getPrincipalName()},
controls);
// Proceed based on the result of the search
if (answer.hasMore())
{
// The search succeeded, set the identity id.
SearchResult sr = answer.next();
if (searchRoots[i].equals(""))
{
identId = sr.getNameInNamespace();
}
else
{
identId = sr.getName() + "," + searchRoots[i];
}
}
else
{
m_log.info("invoke()- No matching identity entities found");
}
}
}
else
catch (ServiceUnavailableException e)
{
m_log.info("invoke()- No matching identity entities found");
m_log.warn("invoke()- ServiceUnavailable exception caught looking up attributes, msg = " + e.getMessage());
// Retry the operation
continue;
}
// No need to retry
break;
}
}
catch (NamingException e)

View File

@ -37,6 +37,7 @@ import javax.naming.directory.DirContext;
import javax.naming.directory.SearchResult;
import javax.naming.directory.SearchControls;
import javax.naming.NamingException;
import javax.naming.ServiceUnavailableException;
import org.bandit.ia.IAContext;
import org.bandit.util.config.Realm;
@ -187,92 +188,123 @@ public final class PwdAuthenticate implements AuthMechanism, Serializable
env.put(Realm.REALM_CONFIG_LOCATION, m_svcConfig.getSetting(SvcConfig.IdentityAbstractionConfigFile));
env.put(Realm.REALM_SELECTOR, authReqMsg.getRealm());
DirContext ctx = new InitialDirContext(env);
// Now search for a user with a matching surname.
//
// Set up a search control so that the search is scoped to the sub-tree
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
// Obtain the search roots
String[] searchRoots = m_svcConfig.m_realmsInfo.getSearchRoots(authReqMsg.getRealm());
if (searchRoots == null)
while (true)
{
// No configured search roots
searchRoots = new String[] {""};
}
// Check if a search string has been configured
String searchString = m_svcConfig.m_realmsInfo.getCntxtlessSearchString(authReqMsg.getRealm());
if (searchString == null)
{
// Determine the search string to be utilized based on the type of directory
// associated with the realm.
String realmType = m_svcConfig.m_realmsInfo.getType(authReqMsg.getRealm());
if (realmType != null)
// Instantiate DirContext watching for an exception since it
// would be an indication that we should not retry the
// operation.
DirContext ctx;
try
{
if (realmType.equalsIgnoreCase(RealmsInfo.eDirectoryRealm))
searchString = "(cn={0})";
else if (realmType.equalsIgnoreCase(RealmsInfo.ActiveDirectoryRealm))
searchString = "(sAMAccountName={0})";
ctx = new InitialDirContext(env);
}
catch (Exception e)
{
m_log.warn("invoke(): Exception caught instantiating DirContext, msg = " + e.getMessage());
// Stop retrying
break;
}
// Now search for a user with a matching surname watching for a service
// unavailable exception as an indication that we should retry the operation.
//
// Set up a search control so that the search is scoped to the sub-tree
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
// Obtain the search roots
String[] searchRoots = m_svcConfig.m_realmsInfo.getSearchRoots(authReqMsg.getRealm());
if (searchRoots == null)
{
// No configured search roots
searchRoots = new String[] {""};
}
// Check if a search string has been configured
String searchString = m_svcConfig.m_realmsInfo.getCntxtlessSearchString(authReqMsg.getRealm());
if (searchString == null)
{
// Determine the search string to be utilized based on the type of directory
// associated with the realm.
String realmType = m_svcConfig.m_realmsInfo.getType(authReqMsg.getRealm());
if (realmType != null)
{
if (realmType.equalsIgnoreCase(RealmsInfo.eDirectoryRealm))
searchString = "(cn={0})";
else if (realmType.equalsIgnoreCase(RealmsInfo.ActiveDirectoryRealm))
searchString = "(sAMAccountName={0})";
else
{
m_log.warn("invoke()- Unsupported realm type " + realmType);
throw new Exception("Realm configuration error");
}
}
else
{
m_log.warn("invoke()- Unsupported realm type " + realmType);
m_log.warn("invoke()- Failed to obtain realm type for realm " + authReqMsg.getRealm());
throw new Exception("Realm configuration error");
}
}
else
try
{
m_log.warn("invoke()- Failed to obtain realm type for realm " + authReqMsg.getRealm());
throw new Exception("Realm configuration error");
}
}
// Go through the search roots stopping if the identity is resolved.
for (int i = 0; i < searchRoots.length && identId == null; i++)
{
// Perform search for this root
NamingEnumeration<SearchResult> answer = ctx.search(searchRoots[i],
searchString,
new String[] {pwToken.getUsername()},
controls);
// Enumerate through the users returned checking the password
while (answer.hasMore())
{
SearchResult sr = answer.next();
// Open a directory context for the user as a way of verifying its password
try
// Go through the search roots stopping if the identity is resolved.
for (int i = 0; i < searchRoots.length && identId == null; i++)
{
Hashtable env2 = new Hashtable();
env2.put(Context.INITIAL_CONTEXT_FACTORY, "org.bandit.ia.IAInitialCtxFactory");
env2.put(Realm.REALM_CONFIG_LOCATION, m_svcConfig.getSetting(SvcConfig.IdentityAbstractionConfigFile));
env2.put(Realm.REALM_SELECTOR, authReqMsg.getRealm());
env2.put(Context.SECURITY_AUTHENTICATION, "simple");
env2.put(Context.SECURITY_PRINCIPAL, sr.getNameInNamespace());
env2.put(Context.SECURITY_CREDENTIALS, pwToken.getPassword());
// Perform search for this root
NamingEnumeration<SearchResult> answer = ctx.search(searchRoots[i],
searchString,
new String[] {pwToken.getUsername()},
controls);
if ((new InitialDirContext(env2)) != null)
// Enumerate through the users returned checking the password
while (answer.hasMore())
{
// The password must be valid, set the identity Id.
if (searchRoots[i].equals(""))
SearchResult sr = answer.next();
// Open a directory context for the user as a way of verifying its password
try
{
identId = sr.getName();
Hashtable env2 = new Hashtable();
env2.put(Context.INITIAL_CONTEXT_FACTORY, "org.bandit.ia.IAInitialCtxFactory");
env2.put(Realm.REALM_CONFIG_LOCATION, m_svcConfig.getSetting(SvcConfig.IdentityAbstractionConfigFile));
env2.put(Realm.REALM_SELECTOR, authReqMsg.getRealm());
env2.put(Context.SECURITY_AUTHENTICATION, "simple");
env2.put(Context.SECURITY_PRINCIPAL, sr.getNameInNamespace());
env2.put(Context.SECURITY_CREDENTIALS, pwToken.getPassword());
if ((new InitialDirContext(env2)) != null)
{
// The password must be valid, set the identity Id.
if (searchRoots[i].equals(""))
{
identId = sr.getName();
}
else
{
identId = sr.getName() + "," + searchRoots[i];
}
break;
}
}
else
catch (NamingException e)
{
identId = sr.getName() + "," + searchRoots[i];
m_log.warn("invoke()- NamingException: " + e.getExplanation());
}
break;
}
}
catch (NamingException e)
{
m_log.warn("invoke()- NamingException: " + e.getExplanation());
}
}
catch (ServiceUnavailableException e)
{
m_log.warn("invoke()- ServiceUnavailable exception caught looking up attributes, msg = " + e.getMessage());
// Retry the operation
continue;
}
// No need to retry
break;
}
// Check if we did not resolve the identity

View File

@ -28,6 +28,8 @@ import org.bandit.util.config.gen.*;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.CommunicationException;
import javax.naming.ServiceUnavailableException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.Attributes;
@ -147,7 +149,7 @@ public class RealmsInfo
else
{
// Ignore parameter
m_log.debug("Constructor(): Unknown directory type");
m_log.debug("Constructor()- Unknown directory type");
}
}
else if (env[iii].getProp().equalsIgnoreCase("com.novell.casa.authtoksvc.contextless_search_string"))
@ -182,18 +184,55 @@ public class RealmsInfo
env.put(Realm.REALM_CONFIG_LOCATION, realmConfigFilePath);
env.put(Realm.REALM_SELECTOR, realm.getId());
DirContext ctx = new InitialDirContext(env);
String[] attributesNeeded = new String[1];
attributesNeeded[0] = "sAMAccountName";
Attributes attributes = ctx.getAttributes(principalName, attributesNeeded);
NamingEnumeration ae = attributes.getAll();
if (ae != null && ae.hasMore())
while (true)
{
realmInfo.m_keyValueMap.put(RealmType, ActiveDirectoryRealm);
}
else
{
realmInfo.m_keyValueMap.put(RealmType, eDirectoryRealm);
// Instantiate DirContext watching for an exception since it
// would be an indication that we should not retry the
// operation.
DirContext ctx;
try
{
ctx = new InitialDirContext(env);
}
catch (Exception e)
{
m_log.warn("Constructor()- Exception caught instantiating DirContext, msg = " + e.getMessage());
// Stop retrying
break;
}
// Now do the attribute lookup watching for a service unavailable
// exception as an indication that we should retry the operation.
try
{
String[] attributesNeeded = new String[1];
attributesNeeded[0] = "sAMAccountName";
Attributes attributes = ctx.getAttributes(principalName, attributesNeeded);
NamingEnumeration ae = attributes.getAll();
if (ae != null && ae.hasMore())
{
realmInfo.m_keyValueMap.put(RealmType, ActiveDirectoryRealm);
}
else
{
realmInfo.m_keyValueMap.put(RealmType, eDirectoryRealm);
}
}
catch (ServiceUnavailableException e)
{
m_log.warn("Constructor()- ServiceUnavailable exception caught looking up attributes, msg = " + e.getMessage());
// Retry the operation
continue;
}
catch (Exception e)
{
m_log.warn("Constructor()- Exception caught looking up attributes, msg = " + e.getMessage());
}
// No need to retry
break;
}
}
else

View File

@ -1,3 +1,21 @@
-------------------------------------------------------------------
Mon Mar 19 10:41:50 MDT 2007 - jluciani@novell.com
- Fixed BUG242969 by removing the log files that get created by
the Windows install of the ATS.
- Fixed BUG251942 by updating the Windows install file responsible
for setting up the log4j.properties file so that it properly
escapes the path characters.
- Fixed BUG250413 by lowering the priority of the messages being
logged and by increasing the log level priority to "warn" in
the log4j.properties file.
- Fixed BUG243339 by codding directly to the classes provided by
xmlsec and taking care of building SOAP messages with the
necessary WS-Security headers.
-------------------------------------------------------------------
Mon Mar 5 11:32:37 MST 2007 - jluciani@novell.com