View Javadoc

1   ///////////////////////////////////////////////////////////////////////
2   //
3   // (c) University of Southampton IT Innovation Centre, 2008
4   //
5   // Copyright in this software belongs to the IT Innovation Centre of
6   // 2 Venture Road, Chilworth Science Park, Southampton SO16 7NP, UK.
7   //
8   // This software may not be used, sold, licensed, transferred, copied
9   // or reproduced in whole or in part in any manner or form or in or
10  // on any media by any person other than in accordance with the terms
11  // of the Licence Agreement supplied with the software, or otherwise
12  // without the prior written consent of the copyright owners.
13  //
14  // This software is distributed WITHOUT ANY WARRANTY, without even the
15  // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16  // PURPOSE, except where stated in the Licence Agreement supplied with
17  // the software.
18  //
19  //  Created By :          Nikolaos Matskanis
20  //  Created Date :        17/01/2008
21  //  Created for Project : NextGRID
22  //
23  /////////////////////////////////////////////////////////////////////////
24  //
25  //  Dependencies : none
26  //
27  /////////////////////////////////////////////////////////////////////////
28  
29  package uk.ac.soton.itinnovation.components.security;
30  
31  import java.io.StringReader;
32  import java.util.HashMap;
33  
34  import javax.xml.namespace.QName;
35  import javax.xml.parsers.DocumentBuilder;
36  import javax.xml.parsers.DocumentBuilderFactory;
37  import javax.xml.soap.SOAPElement;
38  
39  import nextgrid.api.env.STSFailureException;
40  import nextgrid.api.env.STSModule;
41  
42  import org.apache.axis.message.MessageElement;
43  import org.apache.axis.message.SOAPHeaderElement;
44  import org.apache.axis.message.addressing.EndpointReference;
45  import org.apache.commons.logging.Log;
46  import org.apache.commons.logging.LogFactory;
47  import org.w3c.dom.Document;
48  import org.w3c.dom.Element;
49  import org.xml.sax.InputSource;
50  
51  import uk.ac.soton.itinnovation.utils.EPRUtils;
52  import uk.ac.soton.itinnovation.wsdlutils.WSDLOperation;
53  import uk.ac.soton.itinnovation.wsdlutils.WSDLService;
54  
55  /**
56   *
57   * @author Nikolaos Matskanis
58   */
59  public class WSTrustModule implements STSModule {
60  
61    /**
62     * Class logger.
63     */
64    private static final Log LOG = LogFactory.getLog(WSTrustModule.class);
65  
66    /**
67     * WS-Trust request token operation name.
68     */
69    private static final String WSTRUST_OPERATION = "RequestSecurityToken";
70  
71    /**
72     * WS-Trust XML namespace.
73     */
74    private static final String WSTRUST_NS = "http://schemas.xmlsoap.org/ws/2005/02/trust";
75  
76    /**
77     * Configuration file name.
78     */
79    public static final String WSTRUST_CONFIG_FILE = "sts-client-config.wsdd";
80  
81    /**
82     * URI used when a service uses WS-Trust security through SAML tokens.
83     */
84    public static final String WSTRUST_TOKEN_TYPE
85      = "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1";
86  
87    /**
88     * URI used when a service does not use security.
89     */
90    public static final String NO_TOKEN = "http://localhost/nosecurity";
91  
92    /**
93     * WS-Trust request type.
94     */
95    private static final String WSTRUST_REQUEST_TYPE
96      = "http://schemas.xmlsoap.org/ws/2005/02/trust/Issue";
97  
98    /**
99     * SOAP body of a WS-Trust requestSecurityToken request.
100    */
101   private static final String REQUEST_SEC_TOKEN = "<?xml version='1.0'?>\n"
102     + "<RequestSecurityToken xmlns='" + WSTRUST_NS + "'>"
103     // Type from TrustCoM:
104     + "<TokenType>" + WSTRUST_TOKEN_TYPE + "</TokenType>"
105     // From the WS-Trust spec (Issuance binding):
106     + "<RequestType>" + WSTRUST_REQUEST_TYPE + "</RequestType>"
107     + "</RequestSecurityToken>";
108 
109   /**
110    * Token cache.
111    */
112   private HashMap<String, Element> securityTokens;
113 
114   /**
115    * Service group EPR as a string.
116    */
117   private String strServiceGroupEPR;
118 
119   /**
120    * Service group EPR.
121    */
122   private EndpointReference serviceGroupEPR;
123 
124   /**
125    * Token URI.
126    */
127   private String uri;
128 
129 
130   /**
131    * Creates a new instance.
132    */
133   public WSTrustModule() {
134     securityTokens = new HashMap<String, Element>();
135   }
136 
137   /**
138    * {@inheritDoc}
139    */
140   public void setMembershipGroup(String epr) {
141     strServiceGroupEPR = epr;
142     //parses epr
143     serviceGroupEPR = new EndpointReference(
144       EPRUtils.decodeAndDeserialise(strServiceGroupEPR));
145 
146     //fills in necessary variables
147     uri = serviceGroupEPR.getAddress().getValue().toString();
148   }
149 
150   /**
151    * {@inheritDoc}
152    */
153   public Element requestSecurityToken() throws STSFailureException {
154     WSDLOperation op = null;
155     Element token = null;
156 
157 
158     //check if token is in the hashmap
159     if (strServiceGroupEPR != null) {
160       token = lookup(strServiceGroupEPR);
161     } else {
162       throw new STSFailureException("No Group Reference Found");
163     }
164 
165     if (token != null) {
166       return token;
167     }
168 
169     //if not, try to get it
170     try {
171       //Add the  Group header
172       //here i assume it is the first and only reference parameter of the epr.
173       MessageElement me = (MessageElement)serviceGroupEPR.getParameters().get(0);
174       QName serviceParameterName = me.getQName();
175       SOAPHeaderElement param = new SOAPHeaderElement(serviceParameterName);
176 
177       param.addTextNode(me.getValue());
178 
179       WSDLService sts = new WSDLService(new java.net.URI(uri), WSTRUST_CONFIG_FILE);
180 
181       Document doc = createDocument(REQUEST_SEC_TOKEN);
182 
183       op = sts.getOperation(WSTRUST_OPERATION);
184       op.addHeader(param);
185       op.setOperationStyle(org.apache.axis.constants.Style.DOCUMENT);
186       op.setRequestDocument(doc);
187 
188       op.invoke();
189     } catch (IllegalArgumentException ex) {
190       throw new STSFailureException(ex.getMessage());
191     } catch (Exception e) {
192       throw new STSFailureException(e.getMessage());
193     }
194 
195     //getOutput ...
196     java.util.Iterator<?> out = op.getResponse();
197     SOAPElement outputValue = null;
198     while (out.hasNext()) {
199       outputValue = (SOAPElement)out.next();
200     }
201     if (outputValue == null) {
202       throw new STSFailureException("Value of security token response is null");
203     }
204 
205     token = (Element)outputValue.getFirstChild();
206     LOG.debug("The token: " + token);
207     this.securityTokens.put(strServiceGroupEPR, token);
208     return token; //the token
209   }
210 
211 
212   /**
213    * Looks up a security in an internal cache.
214    *
215    * @param ref Reference
216    * @return Cached token or null
217    */
218   public Element lookup(String ref) {
219     return securityTokens.get(ref);
220   }
221 
222   /**
223    * Creates a DOM document instance from the specified text.
224    *
225    * @param xmlString XML document text
226    * @return A Document instance
227    * @throws Exception If an error occurs
228    */
229   private static Document createDocument(String xmlString) throws Exception {
230     Document doc; 
231     DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
232     factory.setNamespaceAware(true); 
233     DocumentBuilder docBuilder = factory.newDocumentBuilder(); 
234     return docBuilder.parse(new InputSource(new StringReader(xmlString))); 
235   }
236 }