/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2009 Sun Microsystems Inc. All Rights Reserved
*
* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (the License). You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* https://opensso.dev.java.net/public/CDDLv1.0.html or
* opensso/legal/CDDLv1.0.txt
* See the License for the specific language governing
* permission and limitations under the License.
*
* When distributing Covered Code, include this CDDL
* Header Notice in each file and include the License file
* at opensso/legal/CDDLv1.0.txt.
* If applicable, add the following below the CDDL Header,
* with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* $Id: ConfigFedMonitoring.java,v 1.2 2009/10/29 00:03:51 exu Exp $
*
* Portions Copyrighted 2011-2015 ForgeRock AS.
*/
package com.sun.identity.configuration;
import com.iplanet.sso.SSOException;
import com.iplanet.sso.SSOToken;
import com.sun.identity.cot.CircleOfTrustManager;
import com.sun.identity.cot.COTConstants;
import com.sun.identity.cot.COTException;
import com.sun.identity.federation.meta.IDFFMetaManager;
import com.sun.identity.federation.meta.IDFFMetaException;
import com.sun.identity.monitoring.Agent;
import com.sun.identity.monitoring.MonitoringUtil;
import com.sun.identity.monitoring.SSOServerRealmFedInfo;
import com.sun.identity.saml2.meta.SAML2MetaException;
import com.sun.identity.saml2.meta.SAML2MetaManager;
import com.sun.identity.saml2.meta.SAML2MetaUtils;
import com.sun.identity.saml2.jaxb.metadata.EntityDescriptorElement;
import com.sun.identity.security.AdminTokenAction;
import com.sun.identity.shared.debug.Debug;
import com.sun.identity.sm.AttributeSchema;
import com.sun.identity.sm.OrganizationConfigManager;
import com.sun.identity.sm.SchemaType;
import com.sun.identity.sm.ServiceSchema;
import com.sun.identity.sm.ServiceSchemaManager;
import com.sun.identity.sm.SMSException;
import com.sun.identity.wsfederation.meta.WSFederationMetaManager;
import com.sun.identity.wsfederation.meta.WSFederationMetaException;
import com.sun.identity.wsfederation.jaxb.wsfederation.FederationElement;
import com.sun.identity.wsfederation.jaxb.wsfederation.UriNamedClaimTypesOfferedElement;
import com.sun.identity.wsfederation.jaxb.wsfederation.TokenIssuerEndpointElement;
import java.security.AccessController;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
/**
* This class gathers the configuration information for the
* monitoring service, which is initially started in WebtopNaming.java
* Configuration information can be gathered after Session services
* have started up.
*/
public class ConfigFedMonitoring {
Debug debug;
SSOToken ssoToken;
private ArrayList realmList;
public static final String IDENTITY_PROVIDER = "IDP";
public static final String SERVICE_PROVIDER = "SP";
public static final String POLICY_DECISION_POINT_DESCRIPTOR = "PDP";
public static final String POLICY_ENFORCEMENT_POINT_DESCRIPTOR = "PEP";
public static final String SAML_ATTRAUTHORITY = "AttrAuthority";
public static final String SAML_AUTHNAUTHORITY = "AuthnAuthority";
public static final String SAML_ATTRQUERY = "AttrQuery";
public static final String AFFILIATE = "Affiliate";
public ConfigFedMonitoring() {
}
/*
* this method is called by AMSetupServlet, when it's done
* configuring the OpenAM server after deployment. it's also
* called by the MonitoringConfiguration load-on-startup servlet
* when the OpenAM server is restarted any time after being
* configured. it completes the configuring of the monitoring
* agent with the config information that requires an SSOToken
* to retrieve. there is another part of the configuration supplied
* to the agent by WebtopNaming.
*/
public void configureFedMonitoring() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date1 = new Date();
String startDate = sdf.format(date1);
debug = Debug.getInstance("amMonitoring");
String classMethod = "ConfigFedMonitoring.configureMonitoring: ";
if (!MonitoringUtil.isRunning()) {
if (debug.warningEnabled()) {
debug.warning(classMethod + "monitoring is disabled");
}
return;
}
try {
ssoToken = getSSOToken();
} catch (SSOException ssoe) {
debug.error(classMethod + "Could not get proper SSOToken", ssoe);
return;
}
/*
* get the SAML1.x trusted partners and sent to the Agent.
* these are global
*/
getSAML1TPs();
// now all the realms' federation configs
getAllRealms("/");
date1 = new Date();
if (debug.messageEnabled()) {
debug.message(classMethod + "\n" +
" Start time " + startDate + "\n" +
" End time = " + sdf.format(date1));
}
return;
}
private SSOToken getSSOToken() throws SSOException {
return (SSOToken) AccessController.doPrivileged(
AdminTokenAction.getInstance());
}
private void getSAML1TPs() {
String classMethod = "ConfigFedMonitoring.getSAML1TPs: ";
try {
// get SAML service attributes
Map attributeSchemas = new HashMap();
ServiceSchemaManager svcSchMgr =
new ServiceSchemaManager("iPlanetAMSAMLService", ssoToken);
Set schemaTypes = svcSchMgr.getSchemaTypes();
for (Iterator it = schemaTypes.iterator(); it.hasNext(); ) {
SchemaType type = (SchemaType)it.next();
ServiceSchema schema = svcSchMgr.getSchema(type);
if (schema != null) {
String curSchemaType = type.getType();
Set asch = schema.getAttributeSchemas();
for (Iterator iu = asch.iterator(); iu.hasNext(); ) {
AttributeSchema as = (AttributeSchema)iu.next();
String i18n = as.getI18NKey();
if ((i18n != null) && (i18n.trim().length() > 0)) {
attributeSchemas.put(as.getName(), as);
}
}
}
}
// get the trusted partners
StringBuffer cotsb =
new StringBuffer(classMethod + "SAML1.x Trusted Partners:\n");
AttributeSchema as =
(AttributeSchema)attributeSchemas.get(
"iplanet-am-saml-partner-urls");
Set orgValues = (Set)as.getDefaultValues();
int ovsize = orgValues.size();
if (debug.messageEnabled()) {
cotsb.append(" has ").append(ovsize).append(" entries:\n");
}
List s1List = new ArrayList(ovsize);
if (ovsize > 0) {
for (Iterator iu = orgValues.iterator(); iu.hasNext(); ) {
String prtn = (String)iu.next();
StringTokenizer st = new StringTokenizer(prtn, "|");
int numtoks = st.countTokens();
if (debug.messageEnabled()) {
cotsb.append(" #tokens = ").append(numtoks).
append("\n");
}
String xx = null;
while (st.hasMoreTokens()) {
prtn = st.nextToken();
StringTokenizer st2 = new StringTokenizer(prtn, "=");
if (st2.countTokens() == 2) {
String st3 = st2.nextToken();
xx = st2.nextToken();
if (st3.equalsIgnoreCase("PARTNERNAME")) {
if (debug.messageEnabled()) {
cotsb.append(" **got PARTNERNAME**\n");
}
s1List.add(xx);
}
}
}
if (debug.messageEnabled()) {
cotsb.append(" ").append(xx).append("\n");
}
}
}
if (debug.messageEnabled()) {
debug.message(cotsb.toString());
}
// send SAML1.x trusted partners list, s1List, to the Agent
Agent.saml1TPConfig (s1List);
} catch (SSOException e) {
debug.error(classMethod + "sso ex getting saml1.x: " +
e.getMessage());
} catch (SMSException e) {
debug.error(classMethod + "sms ex getting saml1.x: " +
e.getMessage());
}
}
/*
* get the list of realms, starting from "startRealm", usu. "/".
* return List with realms, with leading "/".
*/
private List getRealmsList(String startRealm) {
String classMethod = "ConfigFedMonitoring.getRealmsList: ";
try {
int rlmCnt = 1; // for startRealm
OrganizationConfigManager orgMgr =
new OrganizationConfigManager(ssoToken, startRealm);
Set orgs = orgMgr.getSubOrganizationNames("*", true);
rlmCnt += orgs.size();
realmList = new ArrayList(rlmCnt);
realmList.add(startRealm);
for (Iterator it = orgs.iterator(); it.hasNext(); ) {
String ss = "/" + (String)it.next();
realmList.add(ss);
}
return(realmList);
} catch (SMSException e) {
debug.error(classMethod +
"SMSException getting OrgConfigMgr: " + e.getMessage());
}
return (new ArrayList());
}
private void getAllRealms(String startRealm) {
String classMethod = "ConfigFedMonitoring.getAllRealms: ";
boolean skipSAML2Entities = true; // until IDPs/SPs per realm instrum
StringBuffer sb = new StringBuffer(classMethod);
sb.append("orgnames starting from ").append(startRealm).append(":\n");
sb.append(" ").append(startRealm).append("\n");
List rList = getRealmsList(startRealm);
try {
CircleOfTrustManager cotmgr = new CircleOfTrustManager();
SAML2MetaManager saml2Mgr = new SAML2MetaManager();
IDFFMetaManager idffmgr = new IDFFMetaManager(ssoToken);
for (Iterator it = rList.iterator(); it.hasNext(); ) {
String thisRealm = (String)it.next();
Set cots = getCOTs(thisRealm, cotmgr);
Map s2Ents = null;
if (!skipSAML2Entities) {
s2Ents = getSAML2Entities(thisRealm, saml2Mgr);
}
Map wsEnts = getWSFedEntities(thisRealm);
Map idffentMap = getIDFFEntities(thisRealm, idffmgr);
/*
* getCOTMembers(thisRealm, cot, cotmgr, cotsb)
* can get the members of the COT, but there isn't
* a (MIB) entry that right now.
*/
Map membMap = getCOTMembers(thisRealm, cots, cotmgr);
SSOServerRealmFedInfo srfi =
new SSOServerRealmFedInfo.
SSOServerRealmFedInfoBuilder(thisRealm).
cots(cots).
samlv2Entities(s2Ents).
wsEntities(wsEnts).
idffEntities(idffentMap).
membEntities(membMap).build();
Agent.federationConfig(srfi);
}
} catch (SAML2MetaException e) {
debug.error(classMethod + "SAML2 ex: " + e.getMessage());
} catch (COTException e) {
debug.error(classMethod + "COT ex: " + e.getMessage());
} catch (IDFFMetaException e) {
debug.error(classMethod + "IDFF ex: " + e.getMessage());
}
}
public List getWSFedRoles(String entity, String realm) {
List roles = new ArrayList(4);
boolean isSP = true;
int cnt = 0;
try {
WSFederationMetaManager metaManager = new WSFederationMetaManager();
if (metaManager.getIDPSSOConfig(realm,entity) != null) {
roles.add(IDENTITY_PROVIDER);
}
if (metaManager.getSPSSOConfig(realm, entity) != null) {
roles.add(SERVICE_PROVIDER);
}
//to handle dual roles specifically for WSFED
if (roles.isEmpty()) {
FederationElement fedElem =
metaManager.getEntityDescriptor(realm, entity);
if (fedElem != null) {
for (Iterator iter = fedElem.getAny().iterator();
iter.hasNext(); )
{
Object o = iter.next();
if (o instanceof UriNamedClaimTypesOfferedElement) {
roles.add(IDENTITY_PROVIDER);
isSP = false;
} else if (o instanceof TokenIssuerEndpointElement) {
cnt++;
}
}
if ((isSP) || (cnt >1)) {
roles.add(SERVICE_PROVIDER);
}
}
}
} catch (WSFederationMetaException e) {
debug.warning("ConfigFedMonitoring.getWSFedRoles", e);
}
return (roles != null) ? roles : Collections.EMPTY_LIST;
}
/*
* This is used to determine what 'roles' a particular entity is
* acting as. It will producs a list of role names which can then
* be used by the calling routine for whatever purpose it needs.
*/
private List getSAMLv2Roles(String entity, String realm) {
List roles = new ArrayList();
try {
SAML2MetaManager samlManager = new SAML2MetaManager();
EntityDescriptorElement d =
samlManager.getEntityDescriptor(realm, entity);
if (d != null) {
// find out what role this dude is playing
if (SAML2MetaUtils.getSPSSODescriptor(d) != null) {
roles.add(SERVICE_PROVIDER);
}
if (SAML2MetaUtils.getIDPSSODescriptor(d) != null) {
roles.add(IDENTITY_PROVIDER);
}
if (SAML2MetaUtils.getPolicyDecisionPointDescriptor(d) != null)
{
roles.add(POLICY_DECISION_POINT_DESCRIPTOR);
}
if (SAML2MetaUtils.getPolicyEnforcementPointDescriptor(d) !=
null)
{
roles.add(POLICY_ENFORCEMENT_POINT_DESCRIPTOR);
}
if (SAML2MetaUtils.
getAttributeAuthorityDescriptor(d) != null) {
roles.add(SAML_ATTRAUTHORITY);
}
if (SAML2MetaUtils.getAuthnAuthorityDescriptor(d) != null) {
roles.add(SAML_AUTHNAUTHORITY);
}
if (SAML2MetaUtils.getAttributeQueryDescriptor(d) != null) {
roles.add(SAML_ATTRQUERY);
}
if (samlManager.getAffiliationDescriptor(realm, entity) !=
null)
{
roles.add(AFFILIATE);
}
}
} catch (SAML2MetaException s) {
if (debug.warningEnabled()) {
debug.warning("ConfigFedMonitoring.getSAMLv2Roles() - " +
"Couldn't get SAMLMetaManager");
}
}
return (roles != null) ? roles : Collections.EMPTY_LIST;
}
/*
* This is used to determine what 'roles' a particular entity is
* acting as. It will producs a list of role names which can then
* be used by the calling routine for whatever purpose it needs.
*/
private List getIDFFRoles(String entity, String realm) {
List roles = new ArrayList(6);
try {
IDFFMetaManager idffManager = new IDFFMetaManager(ssoToken);
// find out what role this dude is playing
if (idffManager.getIDPDescriptor(realm, entity) != null) {
roles.add(IDENTITY_PROVIDER);
}
if (idffManager.getSPDescriptor(realm, entity) != null) {
roles.add(SERVICE_PROVIDER);
}
if(idffManager.getAffiliationDescriptor(realm, entity) != null) {
roles.add(AFFILIATE);
}
} catch (IDFFMetaException s) {
if (debug.warningEnabled()) {
debug.warning("ConfigFedMonitoring.getIDFFRoles() - " +
"Couldn't get SAMLMetaManager");
}
}
return roles;
}
/**
* This is a convenience routine that can be used
* to convert a List of String objects to a single String in the format of
* "one; two; three"
*/
private String listToString(List roleNames) {
StringBuffer sb = new StringBuffer();
for (Iterator i = roleNames.iterator(); i.hasNext(); ) {
String role = (String)i.next();
if (sb.length() > 0) {
sb.append("; ");
}
sb.append(getLocalizedString(role));
}
return sb.toString();
}
private String getLocalizedString(String key) {
return key;
}
private Set getCOTs(String realm, CircleOfTrustManager cotmgr) {
String classMethod = "ConfigFedMonitoring.getCOTs: ";
Set cotSet = null;
try {
cotSet = cotmgr.getAllCirclesOfTrust(realm);
} catch (COTException e) {
debug.error(classMethod + "COTMgr error: " + e.getMessage());
}
return cotSet;
}
private Map getCOTMembers(String realm, Set cotNames,
CircleOfTrustManager cotmgr)
{
String classMethod = "ConfigFedMonitoring.getCOTMembers: ";
StringBuffer sb = new StringBuffer(classMethod);
Map cotMap = new HashMap();
for (Iterator it1 = cotNames.iterator(); it1.hasNext(); ) {
String cotName = (String)it1.next();
if (debug.messageEnabled()) {
sb.append(" cotName = ").append(cotName).append("\n");
}
Map memMap = new HashMap();
try {
Set cotSAML =
cotmgr.listCircleOfTrustMember(realm, cotName,
COTConstants.SAML2);
Set cotIDFF =
cotmgr.listCircleOfTrustMember(realm, cotName,
COTConstants.IDFF);
Set cotWSFed =
cotmgr.listCircleOfTrustMember(realm, cotName,
COTConstants.WS_FED);
memMap.put("SAML", cotSAML);
memMap.put("IDFF", cotIDFF);
memMap.put("WSFed", cotWSFed);
cotMap.put(cotName, memMap);
if (debug.messageEnabled()) {
sb.append(" SAMLv2 members: ");
if ((cotSAML != null) && (cotSAML.size() > 0)) {
for (Iterator it = cotSAML.iterator(); it.hasNext(); ) {
sb.append(" ").append((String)it.next()).
append("\n");
}
} else {
sb.append("none\n");
}
sb.append(" IDFF members: ");
if ((cotIDFF != null) && (cotIDFF.size() > 0)) {
for (Iterator it = cotIDFF.iterator(); it.hasNext(); ) {
sb.append(" ").append((String)it.next()).
append("\n");
}
} else {
sb.append("none\n");
}
sb.append(" WSFed members: ");
if ((cotWSFed != null) && (cotWSFed.size() > 0)) {
for (Iterator it = cotWSFed.iterator(); it.hasNext(); ){
sb.append(" ").append((String)it.next()).
append("\n");
}
} else {
sb.append("none\n");
}
}
} catch (COTException cx) {
debug.error(classMethod + "COTException: " + cx.getMessage());
}
}
if (debug.messageEnabled()) {
debug.error(sb.toString());
}
return cotMap;
}
private Map getSAML2Entities (String realm, SAML2MetaManager saml2Mgr) {
String classMethod = "ConfigFedMonitoring.getSAML2Entities:";
Set s2Ents = null;
// s2entMap: entity name => Map of ("location", "roles") -> values
Map s2entMap = new HashMap(); // for the SAML2 entities
try {
s2Ents = saml2Mgr.getAllEntities(realm);
List hosted = saml2Mgr.getAllHostedEntities(realm);
for (Iterator it = s2Ents.iterator(); it.hasNext(); ) {
Map wse = new HashMap();
String entId = (String)it.next();
if ((hosted != null) && hosted.contains(entId)) {
wse.put("location", "hosted");
} else {
wse.put("location", "remote");
}
wse.put("roles", listToString(getSAMLv2Roles(entId, realm)));
s2entMap.put(entId, wse);
}
} catch (SAML2MetaException e) {
debug.error(classMethod +
"getting SAML2 entity providers for realm " + realm + ": " +
e.getMessage());
}
return s2entMap;
}
private Map getWSFedEntities (String realm) {
String classMethod = "ConfigFedMonitoring.getWSFedEntities:";
Set wsEnts = null;
// wsentMap: entity name => Map of ("location", "roles") -> values
Map wsentMap = new HashMap();
try {
WSFederationMetaManager metaManager = new WSFederationMetaManager();
wsEnts = metaManager.getAllEntities(realm);
List hosted = metaManager.getAllHostedEntities(realm);
for (Iterator it = wsEnts.iterator(); it.hasNext(); ) {
Map wse = new HashMap();
String entId = (String)it.next();
if ((hosted != null) && hosted.contains(entId)) {
wse.put("location", "hosted");
} else {
wse.put("location", "remote");
}
wse.put("roles", listToString(getWSFedRoles(entId, realm)));
wsentMap.put(entId, wse);
}
} catch (WSFederationMetaException e) {
debug.error(classMethod + "getting WSFed entities for realm " +
realm + ": " + e.getMessage());
}
return wsentMap;
}
private Map getIDFFEntities (String realm, IDFFMetaManager idffMgr) {
String classMethod = "ConfigFedMonitoring.getIDFFEntities:";
Set idffEnts = null;
// idffentMap: entity name => Map of ("location", "roles") -> values
Map idffentMap = new HashMap(); // for the IDFF entities
try {
idffEnts = idffMgr.getAllEntities(realm);
List hosted = idffMgr.getAllHostedEntities(realm);
for (Iterator it = idffEnts.iterator(); it.hasNext(); ) {
Map wse = new HashMap();
String entId = (String)it.next();
if ((hosted != null) && hosted.contains(entId)) {
wse.put("location", "hosted");
} else {
wse.put("location", "remote");
}
wse.put("roles", listToString(getIDFFRoles(entId, realm)));
idffentMap.put(entId, wse);
}
} catch (IDFFMetaException e) {
debug.error(classMethod +
"getting IDFF entity providers for realm " + realm + ": " +
e.getMessage());
}
return idffentMap;
}
}