http://git-wip-us.apache.org/repos/asf/cxf/blob/c04c2720/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/xacml/XACMLConstants.java ---------------------------------------------------------------------- diff --git a/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/xacml/XACMLConstants.java b/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/xacml/XACMLConstants.java new file mode 100644 index 0000000..1087280 --- /dev/null +++ b/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/xacml/XACMLConstants.java @@ -0,0 +1,206 @@ +/** + * 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.rt.security.saml.xacml; + + + +/** + * XACML 1.x and 2.0 Constants. + */ +public final class XACMLConstants { + + // + // Attributes + // + + public static final String CURRENT_TIME = + "urn:oasis:names:tc:xacml:1.0:environment:current-time"; + public static final String CURRENT_DATE = + "urn:oasis:names:tc:xacml:1.0:environment:current-date"; + public static final String CURRENT_DATETIME = + "urn:oasis:names:tc:xacml:1.0:environment:current-dateTime"; + + // + // Identifiers + // + + public static final String SUBJECT_DNS_NAME = + "urn:oasis:names:tc:xacml:1.0:subject:authn-locality:dns-name"; + public static final String SUBJECT_IP_ADDR = + "urn:oasis:names:tc:xacml:1.0:subject:authn-locality:ip-address"; + public static final String SUBJECT_AUTHN_METHOD = + "urn:oasis:names:tc:xacml:1.0:subject:authentication-method"; + public static final String SUBJECT_AUTHN_TIME = + "urn:oasis:names:tc:xacml:1.0:subject:authentication-time"; + public static final String SUBJECT_KEY_INFO = + "urn:oasis:names:tc:xacml:1.0:subject:key-info"; + public static final String SUBJECT_REQ_TIME = + "urn:oasis:names:tc:xacml:1.0:subject:request-time"; + public static final String SUBJECT_START_TIME = + "urn:oasis:names:tc:xacml:1.0:subject:session-start-time"; + public static final String SUBJECT_ID = + "urn:oasis:names:tc:xacml:1.0:subject:subject-id"; + public static final String SUBJECT_ID_QUALIFIER = + "urn:oasis:names:tc:xacml:1.0:subject:subject-id-qualifier"; + public static final String SUBJECT_CAT_ACCESS_SUBJECT = + "urn:oasis:names:tc:xacml:1.0:subject-category:access-subject"; + public static final String SUBJECT_CAT_CODEBASE = + "urn:oasis:names:tc:xacml:1.0:subject-category:codebase"; + public static final String SUBJECT_CAT_INTERMED_SUBJECT = + "urn:oasis:names:tc:xacml:1.0:subject-category:intermediary-subject"; + public static final String SUBJECT_CAT_REC_SUBJECT = + "urn:oasis:names:tc:xacml:1.0:subject-category:recipient-subject"; + public static final String SUBJECT_CAT_REQ_MACHINE = + "urn:oasis:names:tc:xacml:1.0:subject-category:requesting-machine"; + public static final String RESOURCE_LOC = + "urn:oasis:names:tc:xacml:1.0:resource:resource-location"; + public static final String RESOURCE_ID = + "urn:oasis:names:tc:xacml:1.0:resource:resource-id"; + + // Non-standard (CXF-specific) tags for sending information about SOAP services to the PDP + public static final String RESOURCE_WSDL_OPERATION_ID = + "urn:cxf:apache:org:wsdl:operation-id"; + public static final String RESOURCE_WSDL_SERVICE_ID = + "urn:cxf:apache:org:wsdl:service-id"; + public static final String RESOURCE_WSDL_ENDPOINT = + "urn:cxf:apache:org:wsdl:endpoint"; + + public static final String RESOURCE_FILE_NAME = + "urn:oasis:names:tc:xacml:1.0:resource:simple-file-name"; + public static final String ACTION_ID = + "urn:oasis:names:tc:xacml:1.0:action:action-id"; + public static final String ACTION_IMPLIED = + "urn:oasis:names:tc:xacml:1.0:action:implied-action"; + public static final String SUBJECT_ROLE = + "urn:oasis:names:tc:xacml:2.0:subject:role"; + + + // + // Datatypes + // + + public static final String XS_STRING = + "http://www.w3.org/2001/XMLSchema#string"; + public static final String XS_BOOLEAN = + "http://www.w3.org/2001/XMLSchema#boolean"; + public static final String XS_INT = + "http://www.w3.org/2001/XMLSchema#integer"; + public static final String XS_DOUBLE = + "http://www.w3.org/2001/XMLSchema#double"; + public static final String XS_TIME = + "http://www.w3.org/2001/XMLSchema#time"; + public static final String XS_DATE = + "http://www.w3.org/2001/XMLSchema#date"; + public static final String XS_DATETIME = + "http://www.w3.org/2001/XMLSchema#dateTime"; + public static final String XS_ANY_URI = + "http://www.w3.org/2001/XMLSchema#anyURI"; + public static final String XS_HEX = + "http://www.w3.org/2001/XMLSchema#hexBinary"; + public static final String XS_BASE64 = + "http://www.w3.org/2001/XMLSchema#base64Binary"; + public static final String RFC_822_NAME = + "urn:oasis:names:tc:xacml:1.0:data-type:rfc822Name"; + public static final String X500_NAME = + "urn:oasis:names:tc:xacml:1.0:data-type:x500Name"; + + // + // Functions + // + public static final String FUNC_STRING_EQUAL = + "urn:oasis:names:tc:xacml:1.0:function:string-equal"; + public static final String FUNC_BOOL_EQUAL = + "urn:oasis:names:tc:xacml:1.0:function:boolean-equal"; + public static final String FUNC_INT_EQUAL = + "urn:oasis:names:tc:xacml:1.0:function:integer-equal"; + public static final String FUNC_DOUBLE_EQUAL = + "urn:oasis:names:tc:xacml:1.0:function:double-equal"; + public static final String FUNC_DATE_EQUAL = + "urn:oasis:names:tc:xacml:1.0:function:date-equal"; + public static final String FUNC_TIME_EQUAL = + "urn:oasis:names:tc:xacml:1.0:function:time-equal"; + public static final String FUNC_DATETIME_EQUAL = + "urn:oasis:names:tc:xacml:1.0:function:dateTime-equal"; + public static final String FUNC_ANY_URI_EQUAL = + "urn:oasis:names:tc:xacml:1.0:function:anyURI-equal"; + public static final String FUNC_X500_NAME_EQUAL = + "urn:oasis:names:tc:xacml:1.0:function:x500Name-equal"; + public static final String FUNC_RFC_822_NAME_EQUAL = + "urn:oasis:names:tc:xacml:1.0:function:rfc822Name-equal"; + public static final String FUNC_HEX_EQUAL = + "urn:oasis:names:tc:xacml:1.0:function:hexBinary-equal"; + public static final String FUNC_BASE64_EQUAL = + "urn:oasis:names:tc:xacml:1.0:function:base64Binary-equal"; + + public static final String FUNC_INT_GT = + "urn:oasis:names:tc:xacml:1.0:function:integer-greater-than"; + public static final String FUNC_INT_GTE = + "urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal"; + public static final String FUNC_INT_LT = + "urn:oasis:names:tc:xacml:1.0:function:integer-less-than"; + public static final String FUNC_INT_LTE = + "urn:oasis:names:tc:xacml:1.0:function:integer-less-than-or-equal"; + public static final String FUNC_DOUBLE_GT = + "urn:oasis:names:tc:xacml:1.0:function:double-greater-than"; + public static final String FUNC_DOUBLE_GTE = + "urn:oasis:names:tc:xacml:1.0:function:double-greater-than-or-equal"; + public static final String FUNC_DOUBLE_LT = + "urn:oasis:names:tc:xacml:1.0:function:double-less-than"; + public static final String FUNC_DOUBLE_LTE = + "urn:oasis:names:tc:xacml:1.0:function:double-less-than-or-equal"; + + public static final String FUNC_STRING_GT = + "urn:oasis:names:tc:xacml:1.0:function:string-greater-than"; + public static final String FUNC_STRING_GTE = + "urn:oasis:names:tc:xacml:1.0:function:string-greater-than-or-equal"; + public static final String FUNC_STRING_LT = + "urn:oasis:names:tc:xacml:1.0:function:string-less-than"; + public static final String FUNC_STRING_LTE = + "urn:oasis:names:tc:xacml:1.0:function:string-less-than-or-equal"; + public static final String FUNC_TIME_GT = + "urn:oasis:names:tc:xacml:1.0:function:time-greater-than"; + public static final String FUNC_TIME_GTE = + "urn:oasis:names:tc:xacml:1.0:function:time-greater-than-or-equal"; + public static final String FUNC_TIME_LT = + "urn:oasis:names:tc:xacml:1.0:function:time-less-than"; + public static final String FUNC_TIME_LTE = + "urn:oasis:names:tc:xacml:1.0:function:time-less-than-or-equal"; + public static final String FUNC_DATETIME_GT = + "urn:oasis:names:tc:xacml:1.0:function:dateTime-greater-than"; + public static final String FUNC_DATETIME_GTE = + "urn:oasis:names:tc:xacml:1.0:function:dateTime-greater-than-or-equal"; + public static final String FUNC_DATETIME_LT = + "urn:oasis:names:tc:xacml:1.0:function:dateTime-less-than"; + public static final String FUNC_DATETIME_LTE = + "urn:oasis:names:tc:xacml:1.0:function:dateTime-less-than-or-equal"; + public static final String FUNC_DATE_GT = + "urn:oasis:names:tc:xacml:1.0:function:date-greater-than"; + public static final String FUNC_DATE_GTE = + "urn:oasis:names:tc:xacml:1.0:function:date-greater-than-or-equal"; + public static final String FUNC_DATE_LT = + "urn:oasis:names:tc:xacml:1.0:function:date-less-than"; + public static final String FUNC_DATE_LTE = + "urn:oasis:names:tc:xacml:1.0:function:date-less-than-or-equal"; + + + private XACMLConstants() { + // complete + } +}
http://git-wip-us.apache.org/repos/asf/cxf/blob/c04c2720/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/xacml/XACMLRequestBuilder.java ---------------------------------------------------------------------- diff --git a/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/xacml/XACMLRequestBuilder.java b/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/xacml/XACMLRequestBuilder.java new file mode 100644 index 0000000..d3bd32c --- /dev/null +++ b/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/xacml/XACMLRequestBuilder.java @@ -0,0 +1,62 @@ +/** + * 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.rt.security.saml.xacml; + +import java.security.Principal; +import java.util.List; + +import org.apache.cxf.message.Message; +import org.opensaml.xacml.ctx.RequestType; + + +/** + * This interface defines a way to create an XACML Request. + */ +public interface XACMLRequestBuilder { + + /** + * Create an XACML Request given a Principal, list of roles and Message. + * + * @param principal The principal to insert into the Subject of the Request + * @param roles The list of roles associated with the principal + * @param message The Message from which to retrieve the resource + * @return An OpenSAML RequestType object + * @throws Exception + */ + RequestType createRequest(Principal principal, List<String> roles, Message message) throws Exception; + + /** + * Return the list of Resources that have been inserted into the Request. + * + * @param message The Message from which to retrieve the resource + * @return the list of Resources that have been inserted into the Request + */ + @Deprecated + List<String> getResources(Message message); + + /** + * Return the Resource that has been inserted into the Request. + * + * @param message The Message from which to retrieve the resource + * @return the Resource that has been inserted into the Request + */ + @Deprecated + String getResource(Message message); +} http://git-wip-us.apache.org/repos/asf/cxf/blob/c04c2720/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/xacml/pdp/api/PolicyDecisionPoint.java ---------------------------------------------------------------------- diff --git a/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/xacml/pdp/api/PolicyDecisionPoint.java b/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/xacml/pdp/api/PolicyDecisionPoint.java new file mode 100644 index 0000000..80e1623 --- /dev/null +++ b/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/xacml/pdp/api/PolicyDecisionPoint.java @@ -0,0 +1,35 @@ +/** + * 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.rt.security.saml.xacml.pdp.api; + +import javax.xml.transform.Source; + +/** + * An interface that describes a PolicyDecisionPoint (PDP). + */ +public interface PolicyDecisionPoint { + + /** + * Evaluate an XACML Request and return a Response + * @param request an XACML Request as a Source + * @return the XACML Response as a Source + */ + Source evaluate(Source request); + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/c04c2720/rt/security-saml/src/test/java/org/apache/cxf/rt/security/saml/claims/SAMLClaimsTest.java ---------------------------------------------------------------------- diff --git a/rt/security-saml/src/test/java/org/apache/cxf/rt/security/saml/claims/SAMLClaimsTest.java b/rt/security-saml/src/test/java/org/apache/cxf/rt/security/saml/claims/SAMLClaimsTest.java new file mode 100644 index 0000000..3b66e12 --- /dev/null +++ b/rt/security-saml/src/test/java/org/apache/cxf/rt/security/saml/claims/SAMLClaimsTest.java @@ -0,0 +1,212 @@ +/** + * 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.rt.security.saml.claims; + +import java.net.URI; +import java.security.Principal; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import org.w3c.dom.Document; +import org.apache.cxf.helpers.DOMUtils; +import org.apache.cxf.rt.security.claims.Claim; +import org.apache.cxf.rt.security.claims.ClaimCollection; +import org.apache.cxf.rt.security.saml.utils.SAMLUtils; +import org.apache.wss4j.common.saml.SAMLCallback; +import org.apache.wss4j.common.saml.SAMLUtil; +import org.apache.wss4j.common.saml.SamlAssertionWrapper; +import org.apache.wss4j.common.saml.bean.AttributeBean; +import org.apache.wss4j.common.saml.builder.SAML2Constants; +import org.junit.Assert; + +public class SAMLClaimsTest extends Assert { + + @org.junit.Test + public void testSAML2Claims() throws Exception { + AttributeBean attributeBean = new AttributeBean(); + attributeBean.setQualifiedName(SAMLClaim.SAML_ROLE_ATTRIBUTENAME_DEFAULT); + attributeBean.setNameFormat(SAML2Constants.ATTRNAME_FORMAT_UNSPECIFIED); + attributeBean.addAttributeValue("employee"); + + SamlCallbackHandler samlCallbackHandler = new SamlCallbackHandler(); + samlCallbackHandler.setAttributes(Collections.singletonList(attributeBean)); + + // Create the SAML Assertion via the CallbackHandler + SAMLCallback samlCallback = new SAMLCallback(); + SAMLUtil.doSAMLCallback(samlCallbackHandler, samlCallback); + SamlAssertionWrapper samlAssertion = new SamlAssertionWrapper(samlCallback); + + Document doc = DOMUtils.newDocument(); + samlAssertion.toDOM(doc); + + ClaimCollection claims = SAMLUtils.getClaims(samlAssertion); + assertEquals(claims.getDialect().toString(), + "http://schemas.xmlsoap.org/ws/2005/05/identity"); + assertEquals(1, claims.size()); + + // Check Claim values + Claim claim = claims.get(0); + assertEquals(claim.getClaimType(), URI.create(SAMLClaim.SAML_ROLE_ATTRIBUTENAME_DEFAULT)); + assertEquals(1, claim.getValues().size()); + assertTrue(claim.getValues().contains("employee")); + + // Check SAMLClaim values + assertTrue(claim instanceof SAMLClaim); + assertEquals(SAMLClaim.SAML_ROLE_ATTRIBUTENAME_DEFAULT, ((SAMLClaim)claim).getName()); + assertEquals(SAML2Constants.ATTRNAME_FORMAT_UNSPECIFIED, ((SAMLClaim)claim).getNameFormat()); + + // Check roles + Set<Principal> roles = + SAMLUtils.parseRolesFromClaims(claims, + SAMLClaim.SAML_ROLE_ATTRIBUTENAME_DEFAULT, + SAML2Constants.ATTRNAME_FORMAT_UNSPECIFIED); + assertEquals(1, roles.size()); + Principal p = roles.iterator().next(); + assertEquals("employee", p.getName()); + } + + @org.junit.Test + public void testSAML2MultipleRoles() throws Exception { + AttributeBean attributeBean = new AttributeBean(); + attributeBean.setQualifiedName(SAMLClaim.SAML_ROLE_ATTRIBUTENAME_DEFAULT); + attributeBean.setNameFormat(SAML2Constants.ATTRNAME_FORMAT_UNSPECIFIED); + attributeBean.addAttributeValue("employee"); + attributeBean.addAttributeValue("boss"); + + SamlCallbackHandler samlCallbackHandler = new SamlCallbackHandler(); + samlCallbackHandler.setAttributes(Collections.singletonList(attributeBean)); + + // Create the SAML Assertion via the CallbackHandler + SAMLCallback samlCallback = new SAMLCallback(); + SAMLUtil.doSAMLCallback(samlCallbackHandler, samlCallback); + SamlAssertionWrapper samlAssertion = new SamlAssertionWrapper(samlCallback); + + Document doc = DOMUtils.newDocument(); + samlAssertion.toDOM(doc); + + ClaimCollection claims = SAMLUtils.getClaims(samlAssertion); + assertEquals(claims.getDialect().toString(), + "http://schemas.xmlsoap.org/ws/2005/05/identity"); + assertEquals(1, claims.size()); + + // Check Claim values + Claim claim = claims.get(0); + assertEquals(claim.getClaimType(), URI.create(SAMLClaim.SAML_ROLE_ATTRIBUTENAME_DEFAULT)); + assertEquals(2, claim.getValues().size()); + assertTrue(claim.getValues().contains("employee")); + assertTrue(claim.getValues().contains("boss")); + + // Check SAMLClaim values + assertTrue(claim instanceof SAMLClaim); + assertEquals(SAMLClaim.SAML_ROLE_ATTRIBUTENAME_DEFAULT, ((SAMLClaim)claim).getName()); + assertEquals(SAML2Constants.ATTRNAME_FORMAT_UNSPECIFIED, ((SAMLClaim)claim).getNameFormat()); + + // Check roles + Set<Principal> roles = + SAMLUtils.parseRolesFromClaims(claims, + SAMLClaim.SAML_ROLE_ATTRIBUTENAME_DEFAULT, + SAML2Constants.ATTRNAME_FORMAT_UNSPECIFIED); + assertEquals(2, roles.size()); + } + + @org.junit.Test + public void testSAML2MultipleClaims() throws Exception { + AttributeBean attributeBean = new AttributeBean(); + attributeBean.setQualifiedName(SAMLClaim.SAML_ROLE_ATTRIBUTENAME_DEFAULT); + attributeBean.setNameFormat(SAML2Constants.ATTRNAME_FORMAT_UNSPECIFIED); + attributeBean.addAttributeValue("employee"); + + AttributeBean attributeBean2 = new AttributeBean(); + attributeBean2.setQualifiedName( + "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"); + attributeBean2.setNameFormat(SAML2Constants.ATTRNAME_FORMAT_UNSPECIFIED); + attributeBean2.addAttributeValue("smith"); + + SamlCallbackHandler samlCallbackHandler = new SamlCallbackHandler(); + List<AttributeBean> attributes = new ArrayList<AttributeBean>(); + attributes.add(attributeBean); + attributes.add(attributeBean2); + samlCallbackHandler.setAttributes(attributes); + + // Create the SAML Assertion via the CallbackHandler + SAMLCallback samlCallback = new SAMLCallback(); + SAMLUtil.doSAMLCallback(samlCallbackHandler, samlCallback); + SamlAssertionWrapper samlAssertion = new SamlAssertionWrapper(samlCallback); + + Document doc = DOMUtils.newDocument(); + samlAssertion.toDOM(doc); + + ClaimCollection claims = SAMLUtils.getClaims(samlAssertion); + assertEquals(claims.getDialect().toString(), + "http://schemas.xmlsoap.org/ws/2005/05/identity"); + assertEquals(2, claims.size()); + + // Check roles + Set<Principal> roles = + SAMLUtils.parseRolesFromClaims(claims, + SAMLClaim.SAML_ROLE_ATTRIBUTENAME_DEFAULT, + SAML2Constants.ATTRNAME_FORMAT_UNSPECIFIED); + assertEquals(1, roles.size()); + Principal p = roles.iterator().next(); + assertEquals("employee", p.getName()); + } + + @org.junit.Test + public void testSAML1Claims() throws Exception { + AttributeBean attributeBean = new AttributeBean(); + attributeBean.setSimpleName("role"); + attributeBean.setQualifiedName("http://schemas.xmlsoap.org/ws/2005/05/identity/claims"); + attributeBean.addAttributeValue("employee"); + + SamlCallbackHandler samlCallbackHandler = new SamlCallbackHandler(false); + samlCallbackHandler.setAttributes(Collections.singletonList(attributeBean)); + + // Create the SAML Assertion via the CallbackHandler + SAMLCallback samlCallback = new SAMLCallback(); + SAMLUtil.doSAMLCallback(samlCallbackHandler, samlCallback); + SamlAssertionWrapper samlAssertion = new SamlAssertionWrapper(samlCallback); + + Document doc = DOMUtils.newDocument(); + samlAssertion.toDOM(doc); + + ClaimCollection claims = SAMLUtils.getClaims(samlAssertion); + assertEquals(claims.getDialect().toString(), + "http://schemas.xmlsoap.org/ws/2005/05/identity"); + assertEquals(1, claims.size()); + + // Check Claim values + Claim claim = claims.get(0); + assertEquals(claim.getClaimType(), URI.create(SAMLClaim.SAML_ROLE_ATTRIBUTENAME_DEFAULT)); + assertEquals(1, claim.getValues().size()); + assertTrue(claim.getValues().contains("employee")); + + // Check SAMLClaim values + assertTrue(claim instanceof SAMLClaim); + assertEquals("role", ((SAMLClaim)claim).getName()); + + // Check roles + Set<Principal> roles = SAMLUtils.parseRolesFromClaims(claims, "role", null); + assertEquals(1, roles.size()); + Principal p = roles.iterator().next(); + assertEquals("employee", p.getName()); + + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/c04c2720/rt/security-saml/src/test/java/org/apache/cxf/rt/security/saml/claims/SamlCallbackHandler.java ---------------------------------------------------------------------- diff --git a/rt/security-saml/src/test/java/org/apache/cxf/rt/security/saml/claims/SamlCallbackHandler.java b/rt/security-saml/src/test/java/org/apache/cxf/rt/security/saml/claims/SamlCallbackHandler.java new file mode 100644 index 0000000..9b051fa --- /dev/null +++ b/rt/security-saml/src/test/java/org/apache/cxf/rt/security/saml/claims/SamlCallbackHandler.java @@ -0,0 +1,99 @@ +/** + * 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.rt.security.saml.claims; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.UnsupportedCallbackException; + +import org.apache.wss4j.common.saml.SAMLCallback; +import org.apache.wss4j.common.saml.bean.AttributeBean; +import org.apache.wss4j.common.saml.bean.AttributeStatementBean; +import org.apache.wss4j.common.saml.bean.SubjectBean; +import org.apache.wss4j.common.saml.bean.Version; +import org.apache.wss4j.common.saml.builder.SAML1Constants; +import org.apache.wss4j.common.saml.builder.SAML2Constants; + +/** + * A CallbackHandler instance to mock up a SAML Attribute Assertion. + */ +public class SamlCallbackHandler implements CallbackHandler { + private boolean saml2 = true; + private String confirmationMethod = SAML2Constants.CONF_BEARER; + private List<AttributeBean> attributes; + + public SamlCallbackHandler() { + // + } + + public SamlCallbackHandler(boolean saml2) { + this.saml2 = saml2; + } + + public void setConfirmationMethod(String confirmationMethod) { + this.confirmationMethod = confirmationMethod; + } + + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { + for (int i = 0; i < callbacks.length; i++) { + if (callbacks[i] instanceof SAMLCallback) { + SAMLCallback callback = (SAMLCallback) callbacks[i]; + if (saml2) { + callback.setSamlVersion(Version.SAML_20); + } else { + callback.setSamlVersion(Version.SAML_11); + } + + callback.setIssuer("sts"); + String subjectName = "uid=sts-client,o=mock-sts.com"; + String subjectQualifier = "www.mock-sts.com"; + if (!saml2 && SAML2Constants.CONF_SENDER_VOUCHES.equals(confirmationMethod)) { + confirmationMethod = SAML1Constants.CONF_SENDER_VOUCHES; + } + SubjectBean subjectBean = + new SubjectBean( + subjectName, subjectQualifier, confirmationMethod + ); + callback.setSubject(subjectBean); + + if (attributes != null) { + AttributeStatementBean attrBean = new AttributeStatementBean(); + attrBean.setSubject(subjectBean); + attrBean.setSamlAttributes(attributes); + callback.setAttributeStatementData(Collections.singletonList(attrBean)); + } + + } + } + } + + public List<AttributeBean> getAttributes() { + return attributes; + } + + public void setAttributes(List<AttributeBean> attributes) { + this.attributes = attributes; + } + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/c04c2720/rt/security-saml/src/test/java/org/apache/cxf/rt/security/saml/interceptor/ClaimsAuthorizingInterceptorTest.java ---------------------------------------------------------------------- diff --git a/rt/security-saml/src/test/java/org/apache/cxf/rt/security/saml/interceptor/ClaimsAuthorizingInterceptorTest.java b/rt/security-saml/src/test/java/org/apache/cxf/rt/security/saml/interceptor/ClaimsAuthorizingInterceptorTest.java new file mode 100644 index 0000000..775f1fc --- /dev/null +++ b/rt/security-saml/src/test/java/org/apache/cxf/rt/security/saml/interceptor/ClaimsAuthorizingInterceptorTest.java @@ -0,0 +1,298 @@ +/** + * 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.rt.security.saml.interceptor; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.security.Principal; +import java.util.Arrays; +import java.util.Collections; +import java.util.Set; + +import org.apache.cxf.common.security.SimplePrincipal; +import org.apache.cxf.interceptor.security.AccessDeniedException; +import org.apache.cxf.interceptor.security.SecureAnnotationsInterceptor; +import org.apache.cxf.message.ExchangeImpl; +import org.apache.cxf.message.Message; +import org.apache.cxf.message.MessageImpl; +import org.apache.cxf.rt.security.claims.ClaimCollection; +import org.apache.cxf.rt.security.saml.claims.ClaimBean; +import org.apache.cxf.rt.security.saml.claims.SAMLClaim; +import org.apache.cxf.rt.security.saml.claims.SAMLSecurityContext; +import org.apache.cxf.rt.security.saml.utils.SAMLUtils; +import org.apache.cxf.security.SecurityContext; +import org.apache.cxf.security.claims.authorization.Claim; +import org.apache.cxf.security.claims.authorization.ClaimMode; +import org.apache.cxf.security.claims.authorization.Claims; +import org.apache.wss4j.common.saml.builder.SAML2Constants; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + +public class ClaimsAuthorizingInterceptorTest extends Assert { + + private ClaimsAuthorizingInterceptor interceptor; + + @Before + public void setUp() { + interceptor = new ClaimsAuthorizingInterceptor(); + interceptor.setNameAliases( + Collections.singletonMap("authentication", "http://authentication")); + interceptor.setFormatAliases( + Collections.singletonMap("claims", "http://claims")); + interceptor.setSecuredObject(new TestService()); + + } + + @Test + public void testClaimDefaultNameAndFormat() throws Exception { + doTestClaims("claimWithDefaultNameAndFormat", + createDefaultClaim("admin", "user"), + createClaim("http://authentication", "http://claims", "password")); + try { + doTestClaims("claimWithDefaultNameAndFormat", + createDefaultClaim("user"), + createClaim("http://authentication", "http://claims", "password")); + fail("AccessDeniedException expected"); + } catch (AccessDeniedException ex) { + // expected + } + } + + @Test + public void testClaimMatchAll() throws Exception { + doTestClaims("claimMatchAll", + createDefaultClaim("admin", "manager"), + createClaim("http://authentication", "http://claims", "password")); + try { + doTestClaims("claimMatchAll", + createDefaultClaim("admin"), + createClaim("http://authentication", "http://claims", "password")); + doTestClaims("claimMatchAll", + createDefaultClaim("manager"), + createClaim("http://authentication", "http://claims", "password")); + fail("AccessDeniedException expected"); + } catch (AccessDeniedException ex) { + // expected + } + } + + @Test + public void testMissingExpectedClaim() throws Exception { + doTestClaims("claimWithDefaultNameAndFormat", + createDefaultClaim("admin"), + createClaim("http://authentication", "http://claims", "password")); + try { + doTestClaims("claimWithDefaultNameAndFormat", + createDefaultClaim("admin")); + fail("AccessDeniedException expected"); + } catch (AccessDeniedException ex) { + // expected + } + } + + @Test + public void testExtraNonExpectedClaim() throws Exception { + doTestClaims("claimWithDefaultNameAndFormat", + createDefaultClaim("admin", "user"), + createClaim("http://authentication", "http://claims", "password"), + createClaim("http://extra/claims", "http://claims", "claim")); + } + + @Test + public void testClaimSpecificNameAndFormat() throws Exception { + doTestClaims("claimWithSpecificNameAndFormat", + createClaim("http://cxf/roles", "http://claims", "admin", "user"), + createClaim("http://authentication", "http://claims", "password")); + try { + doTestClaims("claimWithSpecificNameAndFormat", + createDefaultClaim("admin", "user"), + createClaim("http://authentication", "http://claims", "password")); + fail("AccessDeniedException expected"); + } catch (AccessDeniedException ex) { + // expected + } + } + + @Test + public void testClaimLaxMode() throws Exception { + doTestClaims("claimLaxMode", + createClaim("http://authentication", "http://claims", "password")); + doTestClaims("claimLaxMode"); + try { + doTestClaims("claimLaxMode", + createClaim("http://authentication", "http://claims", "smartcard")); + fail("AccessDeniedException expected"); + } catch (AccessDeniedException ex) { + // expected + } + } + + @Test + public void testMultipleClaims() throws Exception { + doTestClaims("multipleClaims", + createDefaultClaim("admin"), + createClaim("http://authentication", "http://claims", "smartcard"), + createClaim("http://location", "http://claims", "UK")); + doTestClaims("multipleClaims", + createDefaultClaim("admin"), + createClaim("http://authentication", "http://claims", "password"), + createClaim("http://location", "http://claims", "USA")); + try { + doTestClaims("multipleClaims", + createDefaultClaim("admin"), + createClaim("http://authentication", "http://claims", "unsecuretransport"), + createClaim("http://location", "http://claims", "UK")); + fail("AccessDeniedException expected"); + } catch (AccessDeniedException ex) { + // expected + } + } + + @Test + public void testUserInRoleAndClaims() throws Exception { + SecureAnnotationsInterceptor in = new SecureAnnotationsInterceptor(); + in.setAnnotationClassName(SecureRole.class.getName()); + in.setSecuredObject(new TestService2()); + + Message m = prepareMessage(TestService2.class, "test", + createDefaultClaim("admin"), + createClaim("a", "b", "c")); + + in.handleMessage(m); + + ClaimsAuthorizingInterceptor in2 = new ClaimsAuthorizingInterceptor(); + org.apache.cxf.rt.security.saml.claims.SAMLClaim claim = + new org.apache.cxf.rt.security.saml.claims.SAMLClaim(); + claim.setNameFormat("a"); + claim.setName("b"); + claim.addValue("c"); + in2.setClaims(Collections.singletonMap("test", + Collections.singletonList( + new ClaimBean(claim)))); + in2.handleMessage(m); + + try { + in.handleMessage(prepareMessage(TestService2.class, "test", + createDefaultClaim("user"))); + fail("AccessDeniedException expected"); + } catch (AccessDeniedException ex) { + // expected + } + } + + + private void doTestClaims(String methodName, + org.apache.cxf.rt.security.claims.Claim... claim) + throws Exception { + Message m = prepareMessage(TestService.class, methodName, claim); + interceptor.handleMessage(m); + } + + private Message prepareMessage(Class<?> cls, + String methodName, + org.apache.cxf.rt.security.claims.Claim... claim) + throws Exception { + ClaimCollection claims = new ClaimCollection(); + claims.addAll(Arrays.asList(claim)); + + Set<Principal> roles = + SAMLUtils.parseRolesFromClaims(claims, SAMLClaim.SAML_ROLE_ATTRIBUTENAME_DEFAULT, + SAML2Constants.ATTRNAME_FORMAT_UNSPECIFIED); + + SecurityContext sc = new SAMLSecurityContext(new SimplePrincipal("user"), roles, claims); + Message m = new MessageImpl(); + m.setExchange(new ExchangeImpl()); + m.put(SecurityContext.class, sc); + m.put("org.apache.cxf.resource.method", + cls.getMethod(methodName, new Class[]{})); + return m; + } + + private org.apache.cxf.rt.security.claims.Claim createDefaultClaim( + Object... values) { + return createClaim(SAMLClaim.SAML_ROLE_ATTRIBUTENAME_DEFAULT, + SAML2Constants.ATTRNAME_FORMAT_UNSPECIFIED, + values); + } + + private org.apache.cxf.rt.security.claims.Claim createClaim( + String name, String format, Object... values) { + SAMLClaim claim = new SAMLClaim(); + claim.setName(name); + claim.setNameFormat(format); + claim.setValues(Arrays.asList(values)); + return claim; + } + + @Claim(name = "authentication", format = "claims", + value = "password") + public static class TestService { + // default name and format are used + @Claim({"admin", "manager" }) + public void claimWithDefaultNameAndFormat() { + + } + + // explicit name and format + @Claim(name = "http://cxf/roles", format = "http://claims", + value = {"admin", "manager" }) + public void claimWithSpecificNameAndFormat() { + + } + + @Claim(name = "http://authentication", format = "http://claims", + value = "password", mode = ClaimMode.LAX) + public void claimLaxMode() { + + } + + @Claims({ + @Claim(name = "http://location", format = "http://claims", + value = {"UK", "USA" }), + @Claim(value = {"admin", "manager" }), + @Claim(name = "authentication", format = "claims", + value = {"password", "smartcard" }) + }) + public void multipleClaims() { + + } + + // user must have both admin and manager roles, default is 'or' + @Claim(value = {"admin", "manager" }, + matchAll = true) + public void claimMatchAll() { + + } + } + public static class TestService2 { + @SecureRole("admin") + public void test() { + + } + } + @Target(ElementType.METHOD) + @Retention(RetentionPolicy.RUNTIME) + public @interface SecureRole { + String[] value(); + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/c04c2720/rt/security-saml/src/test/java/org/apache/cxf/rt/security/saml/xacml/DummyPDP.java ---------------------------------------------------------------------- diff --git a/rt/security-saml/src/test/java/org/apache/cxf/rt/security/saml/xacml/DummyPDP.java b/rt/security-saml/src/test/java/org/apache/cxf/rt/security/saml/xacml/DummyPDP.java new file mode 100644 index 0000000..a096208 --- /dev/null +++ b/rt/security-saml/src/test/java/org/apache/cxf/rt/security/saml/xacml/DummyPDP.java @@ -0,0 +1,153 @@ +/** + * 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.rt.security.saml.xacml; + +import java.util.List; + +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.dom.DOMSource; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.apache.cxf.helpers.DOMUtils; +import org.apache.cxf.rt.security.saml.xacml.pdp.api.PolicyDecisionPoint; +import org.apache.wss4j.common.ext.WSSecurityException; +import org.apache.wss4j.common.saml.OpenSAMLUtil; +import org.opensaml.core.xml.XMLObjectBuilderFactory; +import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; +import org.opensaml.xacml.XACMLObjectBuilder; +import org.opensaml.xacml.ctx.AttributeType; +import org.opensaml.xacml.ctx.DecisionType; +import org.opensaml.xacml.ctx.DecisionType.DECISION; +import org.opensaml.xacml.ctx.RequestType; +import org.opensaml.xacml.ctx.ResponseType; +import org.opensaml.xacml.ctx.ResultType; +import org.opensaml.xacml.ctx.StatusCodeType; +import org.opensaml.xacml.ctx.StatusType; +import org.opensaml.xacml.ctx.SubjectType; + +/** + * A test implementation of AbstractXACMLAuthorizingInterceptor. It just mocks up a Response + * object based on the role of the Subject. If the role is "manager" then it permits the + * request, otherwise it denies it. + */ +public class DummyPDP implements PolicyDecisionPoint { + + public Source evaluate(Source requestSource) { + RequestType request = requestSourceToRequestType(requestSource); + String role = getSubjectRole(request); + DECISION decision = "manager".equals(role) ? DecisionType.DECISION.Permit : DecisionType.DECISION.Deny; + ResponseType response = createResponse(decision); + return responseType2Source(response); + } + + private RequestType requestSourceToRequestType(Source requestSource) { + try { + Transformer trans = TransformerFactory.newInstance().newTransformer(); + DOMResult res = new DOMResult(); + trans.transform(requestSource, res); + Node nd = res.getNode(); + if (nd instanceof Document) { + nd = ((Document)nd).getDocumentElement(); + } + return (RequestType)OpenSAMLUtil.fromDom((Element)nd); + } catch (Exception e) { + throw new RuntimeException("Error converting pdp response to ResponseType", e); + } + } + + private Source responseType2Source(ResponseType response) { + Document doc = DOMUtils.createDocument(); + Element responseElement; + try { + responseElement = OpenSAMLUtil.toDom(response, doc); + } catch (WSSecurityException e) { + throw new RuntimeException("Error converting PDP RequestType to Dom", e); + } + return new DOMSource(responseElement); + } + + private ResponseType createResponse(DECISION decision) { + XMLObjectBuilderFactory builderFactory = XMLObjectProviderRegistrySupport.getBuilderFactory(); + + @SuppressWarnings("unchecked") + XACMLObjectBuilder<ResponseType> responseTypeBuilder = + (XACMLObjectBuilder<ResponseType>) + builderFactory.getBuilder(ResponseType.DEFAULT_ELEMENT_NAME); + + @SuppressWarnings("unchecked") + XACMLObjectBuilder<ResultType> resultTypeBuilder = + (XACMLObjectBuilder<ResultType>) + builderFactory.getBuilder(ResultType.DEFAULT_ELEMENT_NAME); + + @SuppressWarnings("unchecked") + XACMLObjectBuilder<DecisionType> decisionTypeBuilder = + (XACMLObjectBuilder<DecisionType>) + builderFactory.getBuilder(DecisionType.DEFAULT_ELEMENT_NAME); + + @SuppressWarnings("unchecked") + XACMLObjectBuilder<StatusType> statusTypeBuilder = + (XACMLObjectBuilder<StatusType>) + builderFactory.getBuilder(StatusType.DEFAULT_ELEMENT_NAME); + + @SuppressWarnings("unchecked") + XACMLObjectBuilder<StatusCodeType> statusCodeTypeBuilder = + (XACMLObjectBuilder<StatusCodeType>) + builderFactory.getBuilder(StatusCodeType.DEFAULT_ELEMENT_NAME); + + ResultType result = resultTypeBuilder.buildObject(); + + DecisionType decisionType = decisionTypeBuilder.buildObject(); + decisionType.setDecision(decision); + result.setDecision(decisionType); + + StatusType status = statusTypeBuilder.buildObject(); + StatusCodeType statusCode = statusCodeTypeBuilder.buildObject(); + statusCode.setValue("urn:oasis:names:tc:xacml:1.0:status:ok"); + status.setStatusCode(statusCode); + result.setStatus(status); + + ResponseType response = responseTypeBuilder.buildObject(); + response.getResults().add(result); + return response; + } + + private String getSubjectRole(RequestType request) { + List<SubjectType> subjects = request.getSubjects(); + if (subjects != null) { + for (SubjectType subject : subjects) { + List<AttributeType> attributes = subject.getAttributes(); + if (attributes != null) { + for (AttributeType attribute : attributes) { + if (XACMLConstants.SUBJECT_ROLE.equals(attribute.getAttributeId())) { + return attribute.getAttributeValues().get(0).getValue(); + } + } + } + } + } + return null; + } + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/c04c2720/rt/security-saml/src/test/java/org/apache/cxf/rt/security/saml/xacml/RequestComponentBuilderTest.java ---------------------------------------------------------------------- diff --git a/rt/security-saml/src/test/java/org/apache/cxf/rt/security/saml/xacml/RequestComponentBuilderTest.java b/rt/security-saml/src/test/java/org/apache/cxf/rt/security/saml/xacml/RequestComponentBuilderTest.java new file mode 100644 index 0000000..53cd863 --- /dev/null +++ b/rt/security-saml/src/test/java/org/apache/cxf/rt/security/saml/xacml/RequestComponentBuilderTest.java @@ -0,0 +1,222 @@ +/** + * 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.rt.security.saml.xacml; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import org.apache.wss4j.common.saml.OpenSAMLUtil; +import org.joda.time.DateTime; +import org.opensaml.xacml.ctx.ActionType; +import org.opensaml.xacml.ctx.AttributeType; +import org.opensaml.xacml.ctx.AttributeValueType; +import org.opensaml.xacml.ctx.EnvironmentType; +import org.opensaml.xacml.ctx.RequestType; +import org.opensaml.xacml.ctx.ResourceType; +import org.opensaml.xacml.ctx.SubjectType; + + +/** + * Some unit tests to create a XACML Request using the RequestComponentBuilder. + */ +public class RequestComponentBuilderTest extends org.junit.Assert { + + private DocumentBuilder docBuilder; + static { + OpenSAMLUtil.initSamlEngine(); + } + + public RequestComponentBuilderTest() throws ParserConfigurationException { + DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); + docBuilderFactory.setNamespaceAware(true); + docBuilder = docBuilderFactory.newDocumentBuilder(); + } + + @org.junit.Test + public void testCreateXACMLRequest() throws Exception { + Document doc = docBuilder.newDocument(); + + // Subject + AttributeValueType subjectIdAttributeValue = + RequestComponentBuilder.createAttributeValueType( + "[email protected]" + ); + AttributeType subjectIdAttribute = + RequestComponentBuilder.createAttributeType( + XACMLConstants.SUBJECT_ID, + XACMLConstants.RFC_822_NAME, + null, + Collections.singletonList(subjectIdAttributeValue) + ); + + AttributeValueType subjectGroupAttributeValue = + RequestComponentBuilder.createAttributeValueType( + "manager" + ); + AttributeType subjectGroupAttribute = + RequestComponentBuilder.createAttributeType( + XACMLConstants.SUBJECT_ROLE, + XACMLConstants.XS_ANY_URI, + "[email protected]", + Collections.singletonList(subjectGroupAttributeValue) + ); + List<AttributeType> attributes = new ArrayList<AttributeType>(); + attributes.add(subjectIdAttribute); + attributes.add(subjectGroupAttribute); + SubjectType subject = RequestComponentBuilder.createSubjectType(attributes, null); + + // Resource + AttributeValueType resourceAttributeValue = + RequestComponentBuilder.createAttributeValueType( + "{http://www.example.org/contract/DoubleIt}DoubleIt" + ); + AttributeType resourceAttribute = + RequestComponentBuilder.createAttributeType( + XACMLConstants.RESOURCE_ID, + XACMLConstants.XS_STRING, + null, + Collections.singletonList(resourceAttributeValue) + ); + attributes.clear(); + attributes.add(resourceAttribute); + ResourceType resource = RequestComponentBuilder.createResourceType(attributes, null); + + // Action + AttributeValueType actionAttributeValue = + RequestComponentBuilder.createAttributeValueType( + "execute" + ); + AttributeType actionAttribute = + RequestComponentBuilder.createAttributeType( + XACMLConstants.ACTION_ID, + XACMLConstants.XS_STRING, + null, + Collections.singletonList(actionAttributeValue) + ); + attributes.clear(); + attributes.add(actionAttribute); + ActionType action = RequestComponentBuilder.createActionType(attributes); + + // Request + RequestType request = + RequestComponentBuilder.createRequestType( + Collections.singletonList(subject), + Collections.singletonList(resource), + action, + null + ); + + Element policyElement = OpenSAMLUtil.toDom(request, doc); + // String outputString = DOM2Writer.nodeToString(policyElement); + assertNotNull(policyElement); + } + + @org.junit.Test + public void testEnvironment() throws Exception { + Document doc = docBuilder.newDocument(); + + // Subject + AttributeValueType subjectIdAttributeValue = + RequestComponentBuilder.createAttributeValueType( + "[email protected]" + ); + AttributeType subjectIdAttribute = + RequestComponentBuilder.createAttributeType( + XACMLConstants.SUBJECT_ID, + XACMLConstants.RFC_822_NAME, + null, + Collections.singletonList(subjectIdAttributeValue) + ); + + List<AttributeType> attributes = new ArrayList<AttributeType>(); + attributes.add(subjectIdAttribute); + SubjectType subject = RequestComponentBuilder.createSubjectType(attributes, null); + + // Resource + AttributeValueType resourceAttributeValue = + RequestComponentBuilder.createAttributeValueType( + "{http://www.example.org/contract/DoubleIt}DoubleIt" + ); + AttributeType resourceAttribute = + RequestComponentBuilder.createAttributeType( + XACMLConstants.RESOURCE_ID, + XACMLConstants.XS_STRING, + null, + Collections.singletonList(resourceAttributeValue) + ); + attributes.clear(); + attributes.add(resourceAttribute); + ResourceType resource = RequestComponentBuilder.createResourceType(attributes, null); + + // Action + AttributeValueType actionAttributeValue = + RequestComponentBuilder.createAttributeValueType( + "execute" + ); + AttributeType actionAttribute = + RequestComponentBuilder.createAttributeType( + XACMLConstants.ACTION_ID, + XACMLConstants.XS_STRING, + null, + Collections.singletonList(actionAttributeValue) + ); + attributes.clear(); + attributes.add(actionAttribute); + ActionType action = RequestComponentBuilder.createActionType(attributes); + + // Environment + DateTime dateTime = new DateTime(); + AttributeValueType environmentAttributeValue = + RequestComponentBuilder.createAttributeValueType(dateTime.toString()); + AttributeType environmentAttribute = + RequestComponentBuilder.createAttributeType( + XACMLConstants.CURRENT_DATETIME, + XACMLConstants.XS_DATETIME, + null, + Collections.singletonList(environmentAttributeValue) + ); + attributes.clear(); + attributes.add(environmentAttribute); + EnvironmentType environmentType = + RequestComponentBuilder.createEnvironmentType(attributes); + + // Request + RequestType request = + RequestComponentBuilder.createRequestType( + Collections.singletonList(subject), + Collections.singletonList(resource), + action, + environmentType + ); + + Element policyElement = OpenSAMLUtil.toDom(request, doc); + // String outputString = DOM2Writer.nodeToString(policyElement); + assertNotNull(policyElement); + } + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/c04c2720/rt/security-saml/src/test/java/org/apache/cxf/rt/security/saml/xacml/SamlRequestComponentBuilderTest.java ---------------------------------------------------------------------- diff --git a/rt/security-saml/src/test/java/org/apache/cxf/rt/security/saml/xacml/SamlRequestComponentBuilderTest.java b/rt/security-saml/src/test/java/org/apache/cxf/rt/security/saml/xacml/SamlRequestComponentBuilderTest.java new file mode 100644 index 0000000..526be4a --- /dev/null +++ b/rt/security-saml/src/test/java/org/apache/cxf/rt/security/saml/xacml/SamlRequestComponentBuilderTest.java @@ -0,0 +1,153 @@ +/** + * 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.rt.security.saml.xacml; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import org.apache.wss4j.common.saml.OpenSAMLUtil; +import org.opensaml.xacml.ctx.ActionType; +import org.opensaml.xacml.ctx.AttributeType; +import org.opensaml.xacml.ctx.AttributeValueType; +import org.opensaml.xacml.ctx.RequestType; +import org.opensaml.xacml.ctx.ResourceType; +import org.opensaml.xacml.ctx.SubjectType; +import org.opensaml.xacml.profile.saml.SAMLProfileConstants; +import org.opensaml.xacml.profile.saml.XACMLAuthzDecisionQueryType; + + +/** + * Some unit tests for creating a SAML XACML Request. + */ +public class SamlRequestComponentBuilderTest extends org.junit.Assert { + + private DocumentBuilder docBuilder; + static { + OpenSAMLUtil.initSamlEngine(); + } + + public SamlRequestComponentBuilderTest() throws ParserConfigurationException { + DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); + docBuilderFactory.setNamespaceAware(true); + docBuilder = docBuilderFactory.newDocumentBuilder(); + } + + @org.junit.Test + public void testCreateXACMLSamlAuthzQueryRequest() throws Exception { + Document doc = docBuilder.newDocument(); + + // + // Create XACML request + // + + // Subject + AttributeValueType subjectIdAttributeValue = + RequestComponentBuilder.createAttributeValueType( + "[email protected]" + ); + AttributeType subjectIdAttribute = + RequestComponentBuilder.createAttributeType( + XACMLConstants.SUBJECT_ID, + XACMLConstants.RFC_822_NAME, + null, + Collections.singletonList(subjectIdAttributeValue) + ); + + AttributeValueType subjectGroupAttributeValue = + RequestComponentBuilder.createAttributeValueType( + "manager" + ); + AttributeType subjectGroupAttribute = + RequestComponentBuilder.createAttributeType( + XACMLConstants.SUBJECT_ROLE, + XACMLConstants.XS_ANY_URI, + "[email protected]", + Collections.singletonList(subjectGroupAttributeValue) + ); + List<AttributeType> attributes = new ArrayList<AttributeType>(); + attributes.add(subjectIdAttribute); + attributes.add(subjectGroupAttribute); + SubjectType subject = RequestComponentBuilder.createSubjectType(attributes, null); + + // Resource + AttributeValueType resourceAttributeValue = + RequestComponentBuilder.createAttributeValueType( + "{http://www.example.org/contract/DoubleIt}DoubleIt" + ); + AttributeType resourceAttribute = + RequestComponentBuilder.createAttributeType( + XACMLConstants.RESOURCE_ID, + XACMLConstants.XS_STRING, + null, + Collections.singletonList(resourceAttributeValue) + ); + attributes.clear(); + attributes.add(resourceAttribute); + ResourceType resource = RequestComponentBuilder.createResourceType(attributes, null); + + // Action + AttributeValueType actionAttributeValue = + RequestComponentBuilder.createAttributeValueType( + "execute" + ); + AttributeType actionAttribute = + RequestComponentBuilder.createAttributeType( + XACMLConstants.ACTION_ID, + XACMLConstants.XS_STRING, + null, + Collections.singletonList(actionAttributeValue) + ); + attributes.clear(); + attributes.add(actionAttribute); + ActionType action = RequestComponentBuilder.createActionType(attributes); + + // Request + RequestType request = + RequestComponentBuilder.createRequestType( + Collections.singletonList(subject), + Collections.singletonList(resource), + action, + null + ); + + // + // Create SAML wrapper + // + + XACMLAuthzDecisionQueryType authzQuery = + SamlRequestComponentBuilder.createAuthzDecisionQuery( + "Issuer", request, SAMLProfileConstants.SAML20XACML20P_NS + ); + + Element policyElement = OpenSAMLUtil.toDom(authzQuery, doc); + // String outputString = DOM2Writer.nodeToString(policyElement); + assertNotNull(policyElement); + } + + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/c04c2720/rt/security-saml/src/test/java/org/apache/cxf/rt/security/saml/xacml/XACMLAuthorizingInterceptorTest.java ---------------------------------------------------------------------- diff --git a/rt/security-saml/src/test/java/org/apache/cxf/rt/security/saml/xacml/XACMLAuthorizingInterceptorTest.java b/rt/security-saml/src/test/java/org/apache/cxf/rt/security/saml/xacml/XACMLAuthorizingInterceptorTest.java new file mode 100644 index 0000000..30fb821 --- /dev/null +++ b/rt/security-saml/src/test/java/org/apache/cxf/rt/security/saml/xacml/XACMLAuthorizingInterceptorTest.java @@ -0,0 +1,127 @@ +/** + * 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.rt.security.saml.xacml; + +import java.security.Principal; +import java.util.HashSet; +import java.util.Set; + +import javax.security.auth.Subject; +import javax.xml.namespace.QName; + +import org.apache.cxf.message.Message; +import org.apache.cxf.message.MessageImpl; +import org.apache.cxf.rt.security.saml.xacml.pdp.api.PolicyDecisionPoint; +import org.apache.cxf.security.LoginSecurityContext; +import org.apache.cxf.security.SecurityContext; + + +/** + * Some unit tests to test the AbstractXACMLAuthorizingInterceptor. + */ +public class XACMLAuthorizingInterceptorTest extends org.junit.Assert { + + static { + org.apache.wss4j.common.saml.OpenSAMLUtil.initSamlEngine(); + } + + @SuppressWarnings("deprecation") + @org.junit.Test + public void testPermit() throws Exception { + // Mock up a Security Context + SecurityContext sc = createSecurityContext("alice", "manager"); + + String operation = "{http://www.example.org/contract/DoubleIt}DoubleIt"; + MessageImpl msg = new MessageImpl(); + msg.put(Message.WSDL_OPERATION, QName.valueOf(operation)); + String service = "{http://www.example.org/contract/DoubleIt}DoubleItService"; + msg.put(Message.WSDL_SERVICE, QName.valueOf(service)); + String resourceURI = "https://localhost:8080/doubleit"; + msg.put(Message.REQUEST_URI, resourceURI); + msg.put(SecurityContext.class, sc); + + PolicyDecisionPoint pdp = new DummyPDP(); + XACMLAuthorizingInterceptor authorizingInterceptor = new XACMLAuthorizingInterceptor(pdp); + authorizingInterceptor.handleMessage(msg); + } + + @SuppressWarnings("deprecation") + @org.junit.Test + public void testDeny() throws Exception { + // Mock up a Security Context + SecurityContext sc = createSecurityContext("alice", "boss"); + + String operation = "{http://www.example.org/contract/DoubleIt}DoubleIt"; + MessageImpl msg = new MessageImpl(); + msg.put(Message.WSDL_OPERATION, QName.valueOf(operation)); + String service = "{http://www.example.org/contract/DoubleIt}DoubleItService"; + msg.put(Message.WSDL_SERVICE, QName.valueOf(service)); + String resourceURI = "https://localhost:8080/doubleit"; + msg.put(Message.REQUEST_URI, resourceURI); + msg.put(SecurityContext.class, sc); + + PolicyDecisionPoint pdp = new DummyPDP(); + XACMLAuthorizingInterceptor authorizingInterceptor = new XACMLAuthorizingInterceptor(pdp); + + try { + authorizingInterceptor.handleMessage(msg); + fail("Failure expected on deny"); + } catch (Exception ex) { + // Failure expected + } + } + + private SecurityContext createSecurityContext(final String user, final String role) { + return new LoginSecurityContext() { + + @Override + public Principal getUserPrincipal() { + return new Principal() { + public String getName() { + return user; + } + }; + } + + @Override + public boolean isUserInRole(String role) { + return false; + } + + @Override + public Subject getSubject() { + return null; + } + + @Override + public Set<Principal> getUserRoles() { + Set<Principal> principals = new HashSet<Principal>(); + principals.add(new Principal() { + public String getName() { + return role; + } + }); + return principals; + } + + }; + } + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/c04c2720/rt/security-saml/src/test/java/org/apache/cxf/rt/security/saml/xacml/XACMLRequestBuilderTest.java ---------------------------------------------------------------------- diff --git a/rt/security-saml/src/test/java/org/apache/cxf/rt/security/saml/xacml/XACMLRequestBuilderTest.java b/rt/security-saml/src/test/java/org/apache/cxf/rt/security/saml/xacml/XACMLRequestBuilderTest.java new file mode 100644 index 0000000..ed34e7a --- /dev/null +++ b/rt/security-saml/src/test/java/org/apache/cxf/rt/security/saml/xacml/XACMLRequestBuilderTest.java @@ -0,0 +1,307 @@ +/** + * 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.rt.security.saml.xacml; + +import java.security.Principal; +import java.util.Collections; +import java.util.List; + +import javax.xml.namespace.QName; + +import org.apache.cxf.message.Message; +import org.apache.cxf.message.MessageImpl; +import org.opensaml.xacml.ctx.AttributeType; +import org.opensaml.xacml.ctx.RequestType; +import org.opensaml.xacml.ctx.ResourceType; + + +/** + * Some unit tests to create a XACML Request via the XACMLRequestBuilder interface. + */ +public class XACMLRequestBuilderTest extends org.junit.Assert { + + static { + org.apache.wss4j.common.saml.OpenSAMLUtil.initSamlEngine(); + } + + @org.junit.Test + public void testXACMLRequestBuilder() throws Exception { + // Mock up a request + Principal principal = new Principal() { + public String getName() { + return "alice"; + } + }; + + String operation = "{http://www.example.org/contract/DoubleIt}DoubleIt"; + MessageImpl msg = new MessageImpl(); + msg.put(Message.WSDL_OPERATION, QName.valueOf(operation)); + String service = "{http://www.example.org/contract/DoubleIt}DoubleItService"; + msg.put(Message.WSDL_SERVICE, QName.valueOf(service)); + String resourceURL = "https://localhost:8080/doubleit"; + msg.put(Message.REQUEST_URI, resourceURL); + + XACMLRequestBuilder builder = new DefaultXACMLRequestBuilder(); + RequestType request = + builder.createRequest(principal, Collections.singletonList("manager"), msg); + assertNotNull(request); + } + + + @org.junit.Test + public void testAction() throws Exception { + // Mock up a request + Principal principal = new Principal() { + public String getName() { + return "alice"; + } + }; + + String operation = "{http://www.example.org/contract/DoubleIt}DoubleIt"; + MessageImpl msg = new MessageImpl(); + msg.put(Message.WSDL_OPERATION, QName.valueOf(operation)); + String service = "{http://www.example.org/contract/DoubleIt}DoubleItService"; + msg.put(Message.WSDL_SERVICE, QName.valueOf(service)); + String resourceURL = "https://localhost:8080/doubleit"; + msg.put(Message.REQUEST_URI, resourceURL); + + DefaultXACMLRequestBuilder builder = new DefaultXACMLRequestBuilder(); + RequestType request = + builder.createRequest(principal, Collections.singletonList("manager"), msg); + assertNotNull(request); + + String action = + request.getAction().getAttributes().get(0).getAttributeValues().get(0).getValue(); + assertEquals("execute", action); + + builder.setAction("write"); + request = builder.createRequest(principal, Collections.singletonList("manager"), msg); + assertNotNull(request); + + action = + request.getAction().getAttributes().get(0).getAttributeValues().get(0).getValue(); + assertEquals("write", action); + } + + @org.junit.Test + public void testEnvironment() throws Exception { + // Mock up a request + Principal principal = new Principal() { + public String getName() { + return "alice"; + } + }; + + String operation = "{http://www.example.org/contract/DoubleIt}DoubleIt"; + MessageImpl msg = new MessageImpl(); + msg.put(Message.WSDL_OPERATION, QName.valueOf(operation)); + String service = "{http://www.example.org/contract/DoubleIt}DoubleItService"; + msg.put(Message.WSDL_SERVICE, QName.valueOf(service)); + String resourceURL = "https://localhost:8080/doubleit"; + msg.put(Message.REQUEST_URL, resourceURL); + + XACMLRequestBuilder builder = new DefaultXACMLRequestBuilder(); + RequestType request = + builder.createRequest(principal, Collections.singletonList("manager"), msg); + assertNotNull(request); + assertFalse(request.getEnvironment().getAttributes().isEmpty()); + + ((DefaultXACMLRequestBuilder)builder).setSendDateTime(false); + request = builder.createRequest(principal, Collections.singletonList("manager"), msg); + assertNotNull(request); + assertTrue(request.getEnvironment().getAttributes().isEmpty()); + } + + @org.junit.Test + public void testSOAPResource() throws Exception { + // Mock up a request + Principal principal = new Principal() { + public String getName() { + return "alice"; + } + }; + + String operation = "{http://www.example.org/contract/DoubleIt}DoubleIt"; + MessageImpl msg = new MessageImpl(); + msg.put(Message.WSDL_OPERATION, QName.valueOf(operation)); + String service = "{http://www.example.org/contract/DoubleIt}DoubleItService"; + msg.put(Message.WSDL_SERVICE, QName.valueOf(service)); + String resourceURL = "https://localhost:8080/doubleit"; + msg.put(Message.REQUEST_URL, resourceURL); + + XACMLRequestBuilder builder = new DefaultXACMLRequestBuilder(); + RequestType request = + builder.createRequest(principal, Collections.singletonList("manager"), msg); + assertNotNull(request); + + List<ResourceType> resources = request.getResources(); + assertNotNull(resources); + assertEquals(1, resources.size()); + + ResourceType resource = resources.get(0); + assertEquals(4, resource.getAttributes().size()); + + boolean resourceIdSatisfied = false; + boolean soapServiceSatisfied = false; + boolean soapOperationSatisfied = false; + boolean resourceURISatisfied = false; + for (AttributeType attribute : resource.getAttributes()) { + String attributeValue = attribute.getAttributeValues().get(0).getValue(); + if (XACMLConstants.RESOURCE_ID.equals(attribute.getAttributeId()) + && "{http://www.example.org/contract/DoubleIt}DoubleItService#DoubleIt".equals( + attributeValue)) { + resourceIdSatisfied = true; + } else if (XACMLConstants.RESOURCE_WSDL_SERVICE_ID.equals(attribute.getAttributeId()) + && service.equals(attributeValue)) { + soapServiceSatisfied = true; + } else if (XACMLConstants.RESOURCE_WSDL_OPERATION_ID.equals(attribute.getAttributeId()) + && operation.equals(attributeValue)) { + soapOperationSatisfied = true; + } else if (XACMLConstants.RESOURCE_WSDL_ENDPOINT.equals(attribute.getAttributeId()) + && resourceURL.equals(attributeValue)) { + resourceURISatisfied = true; + } + } + + assertTrue(resourceIdSatisfied && soapServiceSatisfied && soapOperationSatisfied + && resourceURISatisfied); + } + + @org.junit.Test + public void testSOAPResourceDifferentNamespace() throws Exception { + // Mock up a request + Principal principal = new Principal() { + public String getName() { + return "alice"; + } + }; + + String operation = "{http://www.example.org/contract/DoubleIt}DoubleIt"; + MessageImpl msg = new MessageImpl(); + msg.put(Message.WSDL_OPERATION, QName.valueOf(operation)); + String service = "{http://www.example.org/contract/DoubleItService}DoubleItService"; + msg.put(Message.WSDL_SERVICE, QName.valueOf(service)); + String resourceURL = "https://localhost:8080/doubleit"; + msg.put(Message.REQUEST_URL, resourceURL); + + XACMLRequestBuilder builder = new DefaultXACMLRequestBuilder(); + RequestType request = + builder.createRequest(principal, Collections.singletonList("manager"), msg); + assertNotNull(request); + + List<ResourceType> resources = request.getResources(); + assertNotNull(resources); + assertEquals(1, resources.size()); + + ResourceType resource = resources.get(0); + assertEquals(4, resource.getAttributes().size()); + + boolean resourceIdSatisfied = false; + boolean soapServiceSatisfied = false; + boolean soapOperationSatisfied = false; + boolean resourceURISatisfied = false; + String expectedResourceId = + service + "#" + operation; + for (AttributeType attribute : resource.getAttributes()) { + String attributeValue = attribute.getAttributeValues().get(0).getValue(); + if (XACMLConstants.RESOURCE_ID.equals(attribute.getAttributeId()) + && expectedResourceId.equals(attributeValue)) { + resourceIdSatisfied = true; + } else if (XACMLConstants.RESOURCE_WSDL_SERVICE_ID.equals(attribute.getAttributeId()) + && service.equals(attributeValue)) { + soapServiceSatisfied = true; + } else if (XACMLConstants.RESOURCE_WSDL_OPERATION_ID.equals(attribute.getAttributeId()) + && operation.equals(attributeValue)) { + soapOperationSatisfied = true; + } else if (XACMLConstants.RESOURCE_WSDL_ENDPOINT.equals(attribute.getAttributeId()) + && resourceURL.equals(attributeValue)) { + resourceURISatisfied = true; + } + } + + assertTrue(resourceIdSatisfied && soapServiceSatisfied && soapOperationSatisfied + && resourceURISatisfied); + } + + @org.junit.Test + public void testRESTResource() throws Exception { + // Mock up a request + Principal principal = new Principal() { + public String getName() { + return "alice"; + } + }; + + MessageImpl msg = new MessageImpl(); + String resourceURL = "https://localhost:8080/doubleit"; + msg.put(Message.REQUEST_URL, resourceURL); + + XACMLRequestBuilder builder = new DefaultXACMLRequestBuilder(); + RequestType request = + builder.createRequest(principal, Collections.singletonList("manager"), msg); + assertNotNull(request); + + List<ResourceType> resources = request.getResources(); + assertNotNull(resources); + assertEquals(1, resources.size()); + + ResourceType resource = resources.get(0); + assertEquals(1, resource.getAttributes().size()); + + for (AttributeType attribute : resource.getAttributes()) { + String attributeValue = attribute.getAttributeValues().get(0).getValue(); + assertEquals(attributeValue, resourceURL); + } + } + + @org.junit.Test + public void testRESTResourceTruncatedURI() throws Exception { + // Mock up a request + Principal principal = new Principal() { + public String getName() { + return "alice"; + } + }; + + MessageImpl msg = new MessageImpl(); + String resourceURL = "https://localhost:8080/doubleit"; + msg.put(Message.REQUEST_URL, resourceURL); + String resourceURI = "/doubleit"; + msg.put(Message.REQUEST_URI, resourceURI); + + XACMLRequestBuilder builder = new DefaultXACMLRequestBuilder(); + ((DefaultXACMLRequestBuilder)builder).setSendFullRequestURL(false); + RequestType request = + builder.createRequest(principal, Collections.singletonList("manager"), msg); + assertNotNull(request); + + List<ResourceType> resources = request.getResources(); + assertNotNull(resources); + assertEquals(1, resources.size()); + + ResourceType resource = resources.get(0); + assertEquals(1, resource.getAttributes().size()); + + for (AttributeType attribute : resource.getAttributes()) { + String attributeValue = attribute.getAttributeValues().get(0).getValue(); + assertEquals(attributeValue, resourceURI); + } + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/c04c2720/rt/security/pom.xml ---------------------------------------------------------------------- diff --git a/rt/security/pom.xml b/rt/security/pom.xml index 1a1ca60..5ae8972 100644 --- a/rt/security/pom.xml +++ b/rt/security/pom.xml @@ -30,11 +30,6 @@ <version>3.1.0-SNAPSHOT</version> <relativePath>../../parent/pom.xml</relativePath> </parent> - <properties> - <cxf.osgi.import> - org.opensaml*, - </cxf.osgi.import> - </properties> <dependencies> <dependency> <groupId>org.apache.cxf</groupId> @@ -42,11 +37,6 @@ <version>${project.version}</version> </dependency> <dependency> - <groupId>org.apache.wss4j</groupId> - <artifactId>wss4j-ws-security-common</artifactId> - <version>${cxf.wss4j.version}</version> - </dependency> - <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-jdk14</artifactId> <scope>test</scope> http://git-wip-us.apache.org/repos/asf/cxf/blob/c04c2720/rt/security/src/main/java/org/apache/cxf/rt/security/claims/ClaimBean.java ---------------------------------------------------------------------- diff --git a/rt/security/src/main/java/org/apache/cxf/rt/security/claims/ClaimBean.java b/rt/security/src/main/java/org/apache/cxf/rt/security/claims/ClaimBean.java deleted file mode 100644 index 6c3908d..0000000 --- a/rt/security/src/main/java/org/apache/cxf/rt/security/claims/ClaimBean.java +++ /dev/null @@ -1,51 +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.rt.security.claims; - -import org.apache.cxf.security.claims.authorization.ClaimMode; - -public class ClaimBean { - private SAMLClaim claim; - private ClaimMode claimMode; - private boolean matchAll; - - public ClaimBean(SAMLClaim claim) { - this.claim = claim; - } - - public ClaimBean(SAMLClaim claim, - ClaimMode claimMode, - boolean matchAll) { - this.claim = claim; - this.claimMode = claimMode; - this.matchAll = matchAll; - } - - public SAMLClaim getClaim() { - return claim; - } - - public boolean isMatchAll() { - return matchAll; - } - - public ClaimMode getClaimMode() { - return claimMode; - } -}
