Return-Path: X-Original-To: apmail-cxf-commits-archive@www.apache.org Delivered-To: apmail-cxf-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 9FB0F17C9D for ; Thu, 30 Oct 2014 12:16:58 +0000 (UTC) Received: (qmail 50159 invoked by uid 500); 30 Oct 2014 12:16:58 -0000 Delivered-To: apmail-cxf-commits-archive@cxf.apache.org Received: (qmail 50099 invoked by uid 500); 30 Oct 2014 12:16:58 -0000 Mailing-List: contact commits-help@cxf.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cxf.apache.org Delivered-To: mailing list commits@cxf.apache.org Received: (qmail 50090 invoked by uid 99); 30 Oct 2014 12:16:58 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 30 Oct 2014 12:16:58 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 5EBFB9802B8; Thu, 30 Oct 2014 12:16:57 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: coheigea@apache.org To: commits@cxf.apache.org Message-Id: <1743680ed0904ddda43be652be366c1e@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: git commit: Allow configuring the STS JAAS LoginModule solely via jaas config Date: Thu, 30 Oct 2014 12:16:57 +0000 (UTC) Repository: cxf Updated Branches: refs/heads/3.0.x-fixes c1c95f18e -> 83e5e4570 Allow configuring the STS JAAS LoginModule solely via jaas config Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/83e5e457 Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/83e5e457 Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/83e5e457 Branch: refs/heads/3.0.x-fixes Commit: 83e5e4570cde28064749c02019c6173d0aa10c3d Parents: c1c95f1 Author: Colm O hEigeartaigh Authored: Thu Oct 30 12:15:27 2014 +0000 Committer: Colm O hEigeartaigh Committed: Thu Oct 30 12:16:49 2014 +0000 ---------------------------------------------------------------------- .../cxf/ws/security/trust/STSLoginModule.java | 120 ++++++++++++++++++- .../trust/claims/RoleClaimsCallbackHandler.java | 67 +++++++++++ .../systest/sts/jaas/ClaimsCallbackHandler.java | 68 ----------- .../apache/cxf/systest/sts/jaas/JAASTest.java | 32 +++++ .../apache/cxf/systest/sts/jaas/DoubleIt.wsdl | 3 + .../apache/cxf/systest/sts/jaas/cxf-service.xml | 24 +++- .../systests/basic/src/test/resources/sts.jaas | 10 ++ 7 files changed, 246 insertions(+), 78 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/83e5e457/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSLoginModule.java ---------------------------------------------------------------------- diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSLoginModule.java b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSLoginModule.java index 37f8749..f4f83eb 100644 --- a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSLoginModule.java +++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSLoginModule.java @@ -22,6 +22,7 @@ package org.apache.cxf.ws.security.trust; import java.io.IOException; import java.security.Principal; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -38,7 +39,6 @@ import javax.security.auth.login.LoginException; import javax.security.auth.spi.LoginModule; import org.w3c.dom.Document; - import org.apache.cxf.common.logging.LogUtils; import org.apache.cxf.common.security.SimplePrincipal; import org.apache.cxf.helpers.DOMUtils; @@ -47,6 +47,7 @@ import org.apache.cxf.phase.PhaseInterceptorChain; import org.apache.cxf.rt.security.claims.ClaimCollection; import org.apache.cxf.rt.security.saml.SAMLUtils; import org.apache.cxf.ws.security.SecurityConstants; +import org.apache.cxf.ws.security.trust.claims.RoleClaimsCallbackHandler; import org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor; import org.apache.wss4j.common.saml.SamlAssertionWrapper; import org.apache.wss4j.dom.WSConstants; @@ -55,25 +56,69 @@ import org.apache.wss4j.dom.message.token.UsernameToken; import org.apache.wss4j.dom.validate.Credential; /** - * A JAAS LoginModule for authenticating a Username/Password to the STS. The - * STSClient object itself must be configured separately and picked up either via - * the endpoint name, the "default" STSClient or as a JAX-WS/JAX-RS property with the - * key "ws-security.sts.client". + * A JAAS LoginModule for authenticating a Username/Password to the STS. It can be configured + * either by specifying the various options (documented below) in the JAAS configuration, or + * else by picking up a CXF STSClient from the CXF bus (either the default one, or else one + * that has the same QName as the service name). */ public class STSLoginModule implements LoginModule { /** * Whether we require roles or not from the STS. If this is not set then the * WS-Trust validate binding is used. If it is set then the issue binding is * used, where the Username + Password credentials are passed via "OnBehalfOf". + * In addition, claims are added to the request for the standard "role" ClaimType. */ public static final String REQUIRE_ROLES = "require.roles"; + /** + * The WSDL Location of the STS + */ + public static final String WSDL_LOCATION = "wsdl.location"; + + /** + * The Service QName of the STS + */ + public static final String SERVICE_NAME = "service.name"; + + /** + * The Endpoint QName of the STS + */ + public static final String ENDPOINT_NAME = "endpoint.name"; + + /** + * The default key size to use if using the SymmetricKey KeyType. Defaults to 256. + */ + public static final String KEY_SIZE = "key.size"; + + /** + * The key type to use. The default is the standard "Bearer" URI. + */ + public static final String KEY_TYPE = "key.type"; + + /** + * The token type to use. The default is the standard SAML 2.0 URI. + */ + public static final String TOKEN_TYPE = "token.type"; + + /** + * The WS-Trust namespace to use. The default is the WS-Trust 1.3 namespace. + */ + public static final String WS_TRUST_NAMESPACE = "ws.trust.namespace"; + private static final Logger LOG = LogUtils.getL7dLogger(STSLoginModule.class); private Set principals = new HashSet(); private Subject subject; private CallbackHandler callbackHandler; private boolean requireRoles; + private String wsdlLocation; + private String serviceName; + private String endpointName; + private int keySize; + private String keyType = "http://docs.oasis-open.org/ws-sx/ws-trust/200512/Bearer"; + private String tokenType = "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0"; + private String namespace; + private Map stsClientProperties = new HashMap(); @Override public void initialize(Subject subj, CallbackHandler cbHandler, Map sharedState, @@ -83,6 +128,34 @@ public class STSLoginModule implements LoginModule { if (options.containsKey(REQUIRE_ROLES)) { requireRoles = Boolean.parseBoolean((String)options.get(REQUIRE_ROLES)); } + if (options.containsKey(WSDL_LOCATION)) { + wsdlLocation = (String)options.get(WSDL_LOCATION); + } + if (options.containsKey(SERVICE_NAME)) { + serviceName = (String)options.get(SERVICE_NAME); + } + if (options.containsKey(ENDPOINT_NAME)) { + endpointName = (String)options.get(ENDPOINT_NAME); + } + if (options.containsKey(KEY_SIZE)) { + keySize = Integer.parseInt((String)options.get(KEY_SIZE)); + } + if (options.containsKey(KEY_TYPE)) { + keyType = (String)options.get(KEY_TYPE); + } + if (options.containsKey(TOKEN_TYPE)) { + tokenType = (String)options.get(TOKEN_TYPE); + } + if (options.containsKey(WS_TRUST_NAMESPACE)) { + namespace = (String)options.get(WS_TRUST_NAMESPACE); + } + + stsClientProperties.clear(); + for (String s : SecurityConstants.ALL_PROPERTIES) { + if (options.containsKey(s)) { + stsClientProperties.put(s, options.get(s)); + } + } } @Override @@ -122,6 +195,8 @@ public class STSLoginModule implements LoginModule { RequestData data = new RequestData(); Message message = PhaseInterceptorChain.getCurrentMessage(); + configureSTSClient(message); + data.setMsgContext(message); credential = validator.validate(credential, data); @@ -131,12 +206,45 @@ public class STSLoginModule implements LoginModule { // Add roles if a SAML Assertion was returned from the STS principals.addAll(getRoles(message, credential)); } catch (Exception e) { - LOG.log(Level.INFO, "User " + user + "authentication failed", e); + LOG.log(Level.INFO, "User " + user + " authentication failed", e); throw new LoginException("User " + user + " authentication failed: " + e.getMessage()); } return true; } + + private void configureSTSClient(Message msg) { + STSClient c = STSUtils.getClient(msg, "sts"); + if (wsdlLocation != null) { + c.setWsdlLocation(wsdlLocation); + } + if (serviceName != null) { + c.setServiceName(serviceName); + } + if (endpointName != null) { + c.setEndpointName(endpointName); + } + if (keySize > 0) { + c.setKeySize(keySize); + } + if (keyType != null) { + c.setKeyType(keyType); + } + if (tokenType != null) { + c.setTokenType(tokenType); + } + if (namespace != null) { + c.setNamespace(namespace); + } + + c.setProperties(stsClientProperties); + + if (requireRoles && c.getClaimsCallbackHandler() == null) { + c.setClaimsCallbackHandler(new RoleClaimsCallbackHandler()); + } + + msg.setContextualProperty(SecurityConstants.STS_CLIENT, c); + } private UsernameToken convertToToken(String username, String password) throws Exception { http://git-wip-us.apache.org/repos/asf/cxf/blob/83e5e457/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/claims/RoleClaimsCallbackHandler.java ---------------------------------------------------------------------- diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/claims/RoleClaimsCallbackHandler.java b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/claims/RoleClaimsCallbackHandler.java new file mode 100644 index 0000000..d3bb24d --- /dev/null +++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/claims/RoleClaimsCallbackHandler.java @@ -0,0 +1,67 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.cxf.ws.security.trust.claims; + +import java.io.IOException; + +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.UnsupportedCallbackException; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import org.apache.cxf.helpers.DOMUtils; + +/** + * This CallbackHandler implementation creates a Claims Element for a "role" ClaimType and + * stores it on the ClaimsCallback object. + */ +public class RoleClaimsCallbackHandler implements CallbackHandler { + + public void handle(Callback[] callbacks) + throws IOException, UnsupportedCallbackException { + for (int i = 0; i < callbacks.length; i++) { + if (callbacks[i] instanceof ClaimsCallback) { + ClaimsCallback callback = (ClaimsCallback) callbacks[i]; + callback.setClaims(createClaims()); + + } else { + throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback"); + } + } + } + + /** + * Create a Claims Element for a "role" + */ + private Element createClaims() { + Document doc = DOMUtils.createDocument(); + Element claimsElement = + doc.createElementNS("http://docs.oasis-open.org/ws-sx/ws-trust/200512", "Claims"); + claimsElement.setAttributeNS(null, "Dialect", "http://schemas.xmlsoap.org/ws/2005/05/identity"); + Element claimType = + doc.createElementNS("http://schemas.xmlsoap.org/ws/2005/05/identity", "ClaimType"); + claimType.setAttributeNS(null, "Uri", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role"); + claimsElement.appendChild(claimType); + return claimsElement; + } + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/83e5e457/services/sts/systests/basic/src/test/java/org/apache/cxf/systest/sts/jaas/ClaimsCallbackHandler.java ---------------------------------------------------------------------- diff --git a/services/sts/systests/basic/src/test/java/org/apache/cxf/systest/sts/jaas/ClaimsCallbackHandler.java b/services/sts/systests/basic/src/test/java/org/apache/cxf/systest/sts/jaas/ClaimsCallbackHandler.java deleted file mode 100644 index cb0b701..0000000 --- a/services/sts/systests/basic/src/test/java/org/apache/cxf/systest/sts/jaas/ClaimsCallbackHandler.java +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.apache.cxf.systest.sts.jaas; - -import java.io.IOException; - -import javax.security.auth.callback.Callback; -import javax.security.auth.callback.CallbackHandler; -import javax.security.auth.callback.UnsupportedCallbackException; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import org.apache.cxf.helpers.DOMUtils; -import org.apache.cxf.ws.security.trust.claims.ClaimsCallback; - -/** - * This CallbackHandler implementation creates a Claims Element for a "role" ClaimType and - * stores it on the ClaimsCallback object. - */ -public class ClaimsCallbackHandler implements CallbackHandler { - - public void handle(Callback[] callbacks) - throws IOException, UnsupportedCallbackException { - for (int i = 0; i < callbacks.length; i++) { - if (callbacks[i] instanceof ClaimsCallback) { - ClaimsCallback callback = (ClaimsCallback) callbacks[i]; - callback.setClaims(createClaims()); - - } else { - throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback"); - } - } - } - - /** - * Create a Claims Element for a "role" - */ - private Element createClaims() { - Document doc = DOMUtils.createDocument(); - Element claimsElement = - doc.createElementNS("http://docs.oasis-open.org/ws-sx/ws-trust/200512", "Claims"); - claimsElement.setAttributeNS(null, "Dialect", "http://schemas.xmlsoap.org/ws/2005/05/identity"); - Element claimType = - doc.createElementNS("http://schemas.xmlsoap.org/ws/2005/05/identity", "ClaimType"); - claimType.setAttributeNS(null, "Uri", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role"); - claimsElement.appendChild(claimType); - return claimsElement; - } - -} http://git-wip-us.apache.org/repos/asf/cxf/blob/83e5e457/services/sts/systests/basic/src/test/java/org/apache/cxf/systest/sts/jaas/JAASTest.java ---------------------------------------------------------------------- diff --git a/services/sts/systests/basic/src/test/java/org/apache/cxf/systest/sts/jaas/JAASTest.java b/services/sts/systests/basic/src/test/java/org/apache/cxf/systest/sts/jaas/JAASTest.java index c02705f..eab5830 100644 --- a/services/sts/systests/basic/src/test/java/org/apache/cxf/systest/sts/jaas/JAASTest.java +++ b/services/sts/systests/basic/src/test/java/org/apache/cxf/systest/sts/jaas/JAASTest.java @@ -108,6 +108,37 @@ public class JAASTest extends AbstractBusClientServerTestBase { } @org.junit.Test + public void testSuccessfulInvocationWithProperties() throws Exception { + + SpringBusFactory bf = new SpringBusFactory(); + URL busFile = JAASTest.class.getResource("cxf-client.xml"); + + Bus bus = bf.createBus(busFile.toString()); + SpringBusFactory.setDefaultBus(bus); + SpringBusFactory.setThreadDefaultBus(bus); + + URL wsdl = JAASTest.class.getResource("DoubleIt.wsdl"); + Service service = Service.create(wsdl, SERVICE_QNAME); + QName portQName = new QName(NAMESPACE, "DoubleItUTPort2"); + DoubleItPortType utPort = + service.getPort(portQName, DoubleItPortType.class); + updateAddressPort(utPort, PORT); + + ((BindingProvider)utPort).getRequestContext().put( + SecurityConstants.USERNAME, "alice"); + ((BindingProvider)utPort).getRequestContext().put( + SecurityConstants.PASSWORD, "clarinet"); + + doubleIt(utPort, 25); + + // Note that the UsernameToken should be cached for the second invocation + doubleIt(utPort, 35); + + ((java.io.Closeable)utPort).close(); + bus.shutdown(true); + } + + @org.junit.Test public void testUnsuccessfulAuthentication() throws Exception { SpringBusFactory bf = new SpringBusFactory(); @@ -218,4 +249,5 @@ public class JAASTest extends AbstractBusClientServerTestBase { org.junit.Assert.assertEquals(500, ex.getResponse().getStatus()); } } + } http://git-wip-us.apache.org/repos/asf/cxf/blob/83e5e457/services/sts/systests/basic/src/test/resources/org/apache/cxf/systest/sts/jaas/DoubleIt.wsdl ---------------------------------------------------------------------- diff --git a/services/sts/systests/basic/src/test/resources/org/apache/cxf/systest/sts/jaas/DoubleIt.wsdl b/services/sts/systests/basic/src/test/resources/org/apache/cxf/systest/sts/jaas/DoubleIt.wsdl index 27a483a..25b6d90 100644 --- a/services/sts/systests/basic/src/test/resources/org/apache/cxf/systest/sts/jaas/DoubleIt.wsdl +++ b/services/sts/systests/basic/src/test/resources/org/apache/cxf/systest/sts/jaas/DoubleIt.wsdl @@ -36,6 +36,9 @@ + + + http://git-wip-us.apache.org/repos/asf/cxf/blob/83e5e457/services/sts/systests/basic/src/test/resources/org/apache/cxf/systest/sts/jaas/cxf-service.xml ---------------------------------------------------------------------- diff --git a/services/sts/systests/basic/src/test/resources/org/apache/cxf/systest/sts/jaas/cxf-service.xml b/services/sts/systests/basic/src/test/resources/org/apache/cxf/systest/sts/jaas/cxf-service.xml index f3373d1..0699a78 100644 --- a/services/sts/systests/basic/src/test/resources/org/apache/cxf/systest/sts/jaas/cxf-service.xml +++ b/services/sts/systests/basic/src/test/resources/org/apache/cxf/systest/sts/jaas/cxf-service.xml @@ -21,11 +21,9 @@ + class="org.apache.cxf.ws.security.trust.claims.RoleClaimsCallbackHandler" /> - + @@ -60,6 +58,7 @@ + @@ -67,8 +66,25 @@ + + + + + + + + + + + + + + + + + http://git-wip-us.apache.org/repos/asf/cxf/blob/83e5e457/services/sts/systests/basic/src/test/resources/sts.jaas ---------------------------------------------------------------------- diff --git a/services/sts/systests/basic/src/test/resources/sts.jaas b/services/sts/systests/basic/src/test/resources/sts.jaas index f1e6c19..1ae10af 100644 --- a/services/sts/systests/basic/src/test/resources/sts.jaas +++ b/services/sts/systests/basic/src/test/resources/sts.jaas @@ -2,3 +2,13 @@ sts { org.apache.cxf.ws.security.trust.STSLoginModule required require.roles="true"; }; + +sts_standalone { + org.apache.cxf.ws.security.trust.STSLoginModule required + require.roles="true" + wsdl.location="https://localhost:${testutil.ports.STSServer}/SecurityTokenService/Transport?wsdl" + service.name="{http://docs.oasis-open.org/ws-sx/ws-trust/200512/}SecurityTokenService" + endpoint.name="{http://docs.oasis-open.org/ws-sx/ws-trust/200512/}Transport_Port" + ws-security.username="bob" + ws-security.password="trombone"; +};