/** * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright (c) 2006 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: DiscoveryClient.java,v 1.5 2008/12/16 01:48:31 exu Exp $ * */ package com.sun.identity.liberty.ws.disco; import java.util.List; import java.util.ArrayList; import java.util.Iterator; import org.w3c.dom.Element; import com.sun.identity.liberty.ws.common.wsse.BinarySecurityToken; import com.sun.identity.liberty.ws.soapbinding.Message; import com.sun.identity.liberty.ws.soapbinding.ProviderHeader; import com.sun.identity.liberty.ws.soapbinding.Client; import com.sun.identity.liberty.ws.soapbinding.SOAPBindingConstants; import com.sun.identity.liberty.ws.soapbinding.SOAPBindingException; import com.sun.identity.liberty.ws.soapbinding.Utils; import com.sun.identity.liberty.ws.disco.common.*; import com.sun.identity.liberty.ws.security.*; import com.sun.identity.shared.configuration.SystemPropertiesManager; /** * The class DiscoveryClient provides methods to send * Discovery Service query and modify. * Note: Current implementation uses JAXB objects and no wrapper * classes are used. * @supported.all.api */ public class DiscoveryClient { private String connectTo = null; private int clientMech = Message.ANONYMOUS; private ResourceID resID = null; private EncryptedResourceID encResID = null; private String certAlias = null; private String providerID = null; private boolean clientAuth = false; private SecurityAssertion assertion = null; private List assertions = null; private BinarySecurityToken token = null; private ResourceOffering offering = null; private boolean processed = true; private String soapAction = null; private Object session = null; private String wsfVersion = Utils.getDefaultWSFVersion(); /** * Constructor, connects to Discovery Service without web service security * token. * * @param soapURI URI of the SOAP end point for this discovery * service instance * @param providerID ID of the web service client. */ public DiscoveryClient (String soapURI, String providerID) { connectTo = soapURI; this.providerID = providerID; } /** * Constructor, connects to Discovery Service using WSS SAML * Token. * * @param assertion WSS SAML Token * @param soapURI URI of the SOAP end point for this discovery * service instance * @param providerID ID of the web service client. */ public DiscoveryClient (SecurityAssertion assertion, String soapURI, String providerID) { connectTo = soapURI; if ((assertion != null) && (assertion.isBearer())) { clientMech = Message.BEARER_TOKEN; } else { clientMech = Message.SAML_TOKEN; } this.assertion = assertion; this.providerID = providerID; } /** * Constructor, connects to Discovery Service using WSS X509 * Token. * @param token WSS X.509 Certificate Token * @param soapURI URI of the SOAP end point for this discovery * service instance. * @param providerID ID of the web service client. */ public DiscoveryClient (BinarySecurityToken token, String soapURI, String providerID) { connectTo = soapURI; clientMech = Message.X509_TOKEN; this.token = token; this.providerID = providerID; } /** * Constructor, connects to Discovery Service specified by the resource * offering, security mechanism/SOAP endpoint defined in the * ResourceOffering will be used. * * @param resourceOffering resource offering for this * discovery service instance * @param session session of the WSC * @param providerID ID of the web service client. */ public DiscoveryClient(ResourceOffering resourceOffering, Object session, String providerID) { offering = resourceOffering; processed = false; this.session = session; this.providerID = providerID; } /** * Constructor, connects to Discovery Service specified by the resource * offering, security mechanism/SOAP endpoint defined in the * ResourceOffering will be used. * * @param resourceOffering resource offering for this * discovery service instance * @param session session of the WSC * @param providerID ID of the web service client. * @param assertions List of assertions. */ public DiscoveryClient(ResourceOffering resourceOffering, Object session, String providerID, List assertions) { offering = resourceOffering; processed = false; this.session = session; this.providerID = providerID; this.assertions = assertions; } private void processResourceOffering() throws DiscoveryException { ServiceInstance instance = offering.getServiceInstance(); if (!(instance.getServiceType().equals(DiscoConstants.DISCO_NS))) { DiscoSDKUtils.debug.error("DiscoveryClient.processResourceOffering: " + "ServiceType in ResourceOffering is not discovery service type."); throw new DiscoveryException( DiscoSDKUtils.bundle.getString("notDiscoServiceType")); } resID = offering.getResourceID(); encResID = offering.getEncryptedResourceID(); List descriptions = instance.getDescription(); /* * Iterate through supported security profiles until we find one * that we support (and we should always do so if the spec is * being complied with). They should be in decreasing order of * preference... */ // TODO: support wsdl form Iterator i = descriptions.iterator(); while (i.hasNext()) { Description desc = (Description) i.next(); connectTo = desc.getEndpoint(); soapAction = desc.getSoapAction(); Iterator j = desc.getSecurityMechID().iterator(); while (j.hasNext()) { String mech = (String) j.next(); if ((mech.equals(Message.NULL_NULL)) || (mech.equals(Message.TLS_NULL)) || (mech.equals(Message.CLIENT_TLS_NULL))) { clientMech = Message.ANONYMOUS; DiscoSDKUtils.debug.message("DiscoClient: null"); if (mech.equals(Message.CLIENT_TLS_NULL)) { clientAuth = true; DiscoSDKUtils.debug.message("DiscoClient: clientAuth on"); } return; } else if ((mech.equals(Message.NULL_X509)) || (mech.equals(Message.TLS_X509)) || (mech.equals(Message.CLIENT_TLS_X509)) || (mech.equals(Message.NULL_X509_WSF11)) || (mech.equals(Message.TLS_X509_WSF11)) || (mech.equals(Message.CLIENT_TLS_X509_WSF11))) { clientMech = Message.X509_TOKEN; if (mech.equals(Message.NULL_X509) || mech.equals(Message.TLS_X509) || mech.equals(Message.CLIENT_TLS_X509)) { wsfVersion = SOAPBindingConstants.WSF_10_VERSION; } else { wsfVersion = SOAPBindingConstants.WSF_11_VERSION; } DiscoSDKUtils.debug.message("DiscoClient: x509"); try { SecurityTokenManagerClient stm = new SecurityTokenManagerClient(session); if (certAlias == null) { certAlias = SystemPropertiesManager.get( "com.sun.identity.liberty.ws.wsc.certalias"); } stm.setCertAlias(certAlias); token = stm.getX509CertificateToken(); token.setWSFVersion(wsfVersion); } catch (Exception e) { DiscoSDKUtils.debug.error("DiscoveryClient.processResource" + "Offering: couldn't generate X509 token: ", e); throw new DiscoveryException(e.getMessage()); } if (mech.equals(Message.CLIENT_TLS_X509) || mech.equals(Message.CLIENT_TLS_X509_WSF11)) { clientAuth = true; DiscoSDKUtils.debug.message("DiscoClient: clientAuth on"); } return; } else if ((mech.equals(Message.NULL_SAML)) || (mech.equals(Message.TLS_SAML)) || (mech.equals(Message.CLIENT_TLS_SAML)) || (mech.equals(Message.NULL_SAML_WSF11)) || (mech.equals(Message.TLS_SAML_WSF11)) || (mech.equals(Message.CLIENT_TLS_SAML_WSF11))) { clientMech = Message.SAML_TOKEN; if (mech.equals(Message.NULL_SAML) || mech.equals(Message.TLS_SAML) || mech.equals(Message.CLIENT_TLS_SAML)) { wsfVersion = SOAPBindingConstants.WSF_10_VERSION; } else { wsfVersion = SOAPBindingConstants.WSF_11_VERSION; } DiscoSDKUtils.debug.message("DiscoClient: saml token"); List credRefs = desc.getCredentialRef(); if ((credRefs == null) || (credRefs.size() == 0)) { throw new DiscoveryException( DiscoSDKUtils.bundle.getString("noCredential")); } else { String credID = (String) credRefs.get(0); if (assertions == null) { throw new DiscoveryException( DiscoSDKUtils.bundle.getString("noCredential")); } else { Iterator iter1 = assertions.iterator(); while (iter1.hasNext()) { SecurityAssertion sassert = (SecurityAssertion) iter1.next(); if (credID.equals(sassert.getAssertionID())) { assertion = sassert; break; } } if (assertion == null) { throw new DiscoveryException( DiscoSDKUtils.bundle.getString("noCredential")); } } } if (mech.equals(Message.CLIENT_TLS_SAML) || mech.equals(Message.CLIENT_TLS_SAML_WSF11)) { clientAuth = true; DiscoSDKUtils.debug.message("DiscoClient: clientAuth on"); } return; } else if ((mech.equals(Message.NULL_BEARER)) || (mech.equals(Message.TLS_BEARER)) || (mech.equals(Message.CLIENT_TLS_BEARER)) || (mech.equals(Message.NULL_BEARER_WSF11)) || (mech.equals(Message.TLS_BEARER_WSF11)) || (mech.equals(Message.CLIENT_TLS_BEARER_WSF11))) { clientMech = Message.BEARER_TOKEN; if (mech.equals(Message.NULL_BEARER) || mech.equals(Message.TLS_BEARER) || mech.equals(Message.CLIENT_TLS_BEARER)) { wsfVersion = SOAPBindingConstants.WSF_10_VERSION; } else { wsfVersion = SOAPBindingConstants.WSF_11_VERSION; } DiscoSDKUtils.debug.message("DiscoClient: bearer token"); List credRefs = desc.getCredentialRef(); if ((credRefs == null) || (credRefs.size() == 0)) { throw new DiscoveryException( DiscoSDKUtils.bundle.getString("noCredential")); } else { String credID = (String) credRefs.get(0); if (credID == null || assertions == null) { throw new DiscoveryException( DiscoSDKUtils.bundle.getString("noCredential")); } else { Iterator iter2 = assertions.iterator(); while (iter2.hasNext()) { SecurityAssertion sassert = (SecurityAssertion) iter2.next(); if (credID.equals(sassert.getAssertionID())) { assertion = sassert; break; } } if (assertion == null) { throw new DiscoveryException( DiscoSDKUtils.bundle.getString("noCredential")); } } } if (mech.equals(Message.CLIENT_TLS_BEARER) || mech.equals(Message.CLIENT_TLS_BEARER_WSF11)) { clientAuth = true; DiscoSDKUtils.debug.message("DiscoClient: clientAuth on"); } return; } } } // still here? couldn't find supported mech id DiscoSDKUtils.debug.error("DiscoveryClient.processResourceOffering: " + "Couldn't find supported SecurityMechID from ResourceOffering."); throw new DiscoveryException( DiscoSDKUtils.bundle.getString("noSupportedSecuMechID")); } /** * Sets the alias for the client certificate. If none is set, a default * client certificate will be used. * @param certAlias certificate alias name */ public void setClientCert(String certAlias) { this.certAlias = certAlias; } /** * Sets flag to indicate whether the connection is SSL/TLS with client * authentication. When this flag is set to true, the message will not be * signed according to the spec. If you want to sign the message always, * do not set this flag to true, even when the connection is SSL/TLS with * client authentication. * * @param value The flag value to be set */ public void setClientAuthentication(boolean value) { clientAuth = value; } /** * Sets the resource ID to be accessed. * @param resourceID resource ID */ public void setResourceID(String resourceID) { resID = new ResourceID(resourceID); } /** * Sets the encrypted resource ID to be accessed. * * @param resourceID encrypted resource ID. */ public void setResourceID(EncryptedResourceID resourceID) { encResID = resourceID; } /** * Sets the provider ID. * * @param providerID ID of the web service client. */ public void setProviderID(String providerID) { this.providerID = providerID; } /** * Queries discovery service for ResourceOffering given list of * service types. * * @param serviceTypes List of serviceTypes as * java.lang.String to be queried * @return Query response Element corresponding to the query * @exception DiscoveryException if error occurs */ public QueryResponse getResourceOffering(java.util.List serviceTypes) throws DiscoveryException { if (!processed) { processResourceOffering(); processed = true; } Query query = null; Iterator i = serviceTypes.iterator(); List serviceList = new ArrayList(); while (i.hasNext()) { serviceList.add(new RequestedService(null, (String) i.next())); } if (resID != null) { query = new Query(resID, serviceList); } else { query = new Query(encResID, serviceList); } return getResourceOffering(query); } /** * Queries discovery service for resource offering. * @param query discovery query object * @return Query response Element corresponding to the query * @exception DiscoveryException if error occurs */ public QueryResponse getResourceOffering(Query query) throws DiscoveryException { Message req = createRequest(); req.setSOAPBody(DiscoSDKUtils.parseXML(query.toString())); return new QueryResponse(getResponse(req)); } private Message createRequest() throws DiscoveryException { if (!processed) { processResourceOffering(); processed = true; } // create new Message according to different secuMechID Message req = null; ProviderHeader provH = null; if (providerID != null) { try { provH = new ProviderHeader(providerID); } catch (SOAPBindingException sbe) { throw new DiscoveryException(sbe.getMessage()); } } if (clientMech == Message.X509_TOKEN) { DiscoSDKUtils.debug.message( "DiscoveryClient.createRequest: mech=x509"); try { req = new Message(provH, token); } catch (SOAPBindingException sbe) { throw new DiscoveryException(sbe.getMessage()); } } else if ((clientMech == Message.SAML_TOKEN) || (clientMech == Message.BEARER_TOKEN)) { if (DiscoSDKUtils.debug.messageEnabled()) { DiscoSDKUtils.debug.message("DiscoveryClient.createRequest: " + "mech=saml or bearer"); } try { req = new Message(provH, assertion); } catch (SOAPBindingException sbe) { throw new DiscoveryException(sbe.getMessage()); } } else { if (DiscoSDKUtils.debug.messageEnabled()) { DiscoSDKUtils.debug.message("DiscoveryClient.createRequest: " + "mech=anon"); } try { req = new Message(provH); } catch (SOAPBindingException sbe) { throw new DiscoveryException(sbe.getMessage()); } } if (clientAuth) { req.setClientAuthentication(clientAuth); } req.setWSFVersion(wsfVersion); return req; } private Element getResponse(Message req) throws DiscoveryException { Message resp = null; try { resp = Client.sendRequest(req, connectTo, certAlias, soapAction); } catch (Exception e) { DiscoSDKUtils.debug.error("DiscoveryClient.getResponse:", e); throw new DiscoveryException(e.getMessage()); } List bodies = resp.getBodies(); if (!(bodies.size() == 1)) { DiscoSDKUtils.debug.error("DiscoveryClient.getResponse: SOAP Response " + "didn't contain one SOAPBody."); throw new DiscoveryException( DiscoSDKUtils.bundle.getString("oneBody")); } return ((Element) bodies.iterator().next()); } /** * Modifies discovery resource offering. * @param modify List of Modify object * @return List of ModifyResponse object * @exception DiscoveryException if error occurs */ public ModifyResponse modify(Modify modify) throws DiscoveryException { Message req = createRequest(); req.setSOAPBody(DiscoSDKUtils.parseXML(modify.toString())); return new ModifyResponse(getResponse(req)); } /** * Sets the web services version. * * @param wsfVersion the web services version that should be used. */ public void setWSFVersion(String wsfVersion) { this.wsfVersion = wsfVersion; } }