You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by co...@apache.org on 2015/04/13 14:04:53 UTC
[4/4] cxf git commit: Adding a new cxf-rt-security-saml module to
remove OpenSAML dependencies from cxf-rt-security
Adding a new cxf-rt-security-saml module to remove OpenSAML dependencies from cxf-rt-security
Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/c04c2720
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/c04c2720
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/c04c2720
Branch: refs/heads/master
Commit: c04c27200226b564108b4fe58b8ac70ca5ec7638
Parents: 71e9ada
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Mon Apr 13 13:04:26 2015 +0100
Committer: Colm O hEigeartaigh <co...@apache.org>
Committed: Mon Apr 13 13:04:26 2015 +0100
----------------------------------------------------------------------
.../features/src/main/resources/features.xml | 10 +-
rt/pom.xml | 1 +
.../grants/saml/Saml2BearerGrantHandler.java | 2 +-
.../saml/sso/AbstractServiceProviderFilter.java | 10 +-
.../authorization/ClaimsAuthorizingFilter.java | 4 +-
.../SecurityContextProviderImpl.java | 6 +-
rt/security-saml/pom.xml | 60 ++++
.../cxf/rt/security/saml/claims/ClaimBean.java | 51 +++
.../cxf/rt/security/saml/claims/SAMLClaim.java | 68 ++++
.../saml/claims/SAMLSecurityContext.java | 104 +++++++
.../ClaimsAuthorizingInterceptor.java | 244 +++++++++++++++
.../cxf/rt/security/saml/utils/SAMLUtils.java | 141 +++++++++
.../AbstractXACMLAuthorizingInterceptor.java | 170 ++++++++++
.../security/saml/xacml/CXFMessageParser.java | 97 ++++++
.../saml/xacml/DefaultXACMLRequestBuilder.java | 217 +++++++++++++
.../saml/xacml/RequestComponentBuilder.java | 183 +++++++++++
.../saml/xacml/SamlRequestComponentBuilder.java | 118 +++++++
.../saml/xacml/XACMLAuthorizingInterceptor.java | 86 ++++++
.../rt/security/saml/xacml/XACMLConstants.java | 206 +++++++++++++
.../saml/xacml/XACMLRequestBuilder.java | 62 ++++
.../saml/xacml/pdp/api/PolicyDecisionPoint.java | 35 +++
.../rt/security/saml/claims/SAMLClaimsTest.java | 212 +++++++++++++
.../saml/claims/SamlCallbackHandler.java | 99 ++++++
.../ClaimsAuthorizingInterceptorTest.java | 298 ++++++++++++++++++
.../cxf/rt/security/saml/xacml/DummyPDP.java | 153 +++++++++
.../saml/xacml/RequestComponentBuilderTest.java | 222 ++++++++++++++
.../xacml/SamlRequestComponentBuilderTest.java | 153 +++++++++
.../xacml/XACMLAuthorizingInterceptorTest.java | 127 ++++++++
.../saml/xacml/XACMLRequestBuilderTest.java | 307 +++++++++++++++++++
rt/security/pom.xml | 10 -
.../cxf/rt/security/claims/ClaimBean.java | 51 ---
.../claims/ClaimsAuthorizingInterceptor.java | 242 ---------------
.../cxf/rt/security/claims/SAMLClaim.java | 66 ----
.../rt/security/saml/SAMLSecurityContext.java | 104 -------
.../apache/cxf/rt/security/saml/SAMLUtils.java | 141 ---------
.../AbstractXACMLAuthorizingInterceptor.java | 170 ----------
.../cxf/rt/security/xacml/CXFMessageParser.java | 97 ------
.../xacml/DefaultXACMLRequestBuilder.java | 217 -------------
.../security/xacml/RequestComponentBuilder.java | 183 -----------
.../xacml/SamlRequestComponentBuilder.java | 118 -------
.../xacml/XACMLAuthorizingInterceptor.java | 87 ------
.../cxf/rt/security/xacml/XACMLConstants.java | 206 -------------
.../rt/security/xacml/XACMLRequestBuilder.java | 62 ----
.../xacml/pdp/api/PolicyDecisionPoint.java | 35 ---
.../ClaimsAuthorizingInterceptorTest.java | 295 ------------------
.../cxf/rt/security/saml/SAMLClaimsTest.java | 212 -------------
.../rt/security/saml/SamlCallbackHandler.java | 99 ------
.../apache/cxf/rt/security/xacml/DummyPDP.java | 153 ---------
.../xacml/RequestComponentBuilderTest.java | 222 --------------
.../xacml/SamlRequestComponentBuilderTest.java | 153 ---------
.../xacml/XACMLAuthorizingInterceptorTest.java | 127 --------
.../security/xacml/XACMLRequestBuilderTest.java | 307 -------------------
rt/ws/security/pom.xml | 2 +-
.../trust/AuthPolicyValidatingInterceptor.java | 5 +-
.../cxf/ws/security/trust/STSLoginModule.java | 3 +-
.../wss4j/StaxSecurityContextInInterceptor.java | 4 +-
.../wss4j/UsernameTokenInterceptor.java | 4 +-
.../ws/security/wss4j/WSS4JInInterceptor.java | 5 +-
.../token/validator/DefaultSAMLRoleParser.java | 4 +-
.../security/oauth2/SamlCallbackHandler.java | 2 +-
.../security/oauth2/SamlCallbackHandler2.java | 2 +-
.../security/saml/SamlCallbackHandler.java | 2 +-
.../ws/saml/PolicyDecisionPointMockImpl.java | 4 +-
.../org/apache/cxf/systest/ws/saml/server.xml | 2 +-
.../apache/cxf/systest/ws/saml/stax-server.xml | 2 +-
65 files changed, 3451 insertions(+), 3393 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cxf/blob/c04c2720/osgi/karaf/features/src/main/resources/features.xml
----------------------------------------------------------------------
diff --git a/osgi/karaf/features/src/main/resources/features.xml b/osgi/karaf/features/src/main/resources/features.xml
index 33b418d..0705424 100644
--- a/osgi/karaf/features/src/main/resources/features.xml
+++ b/osgi/karaf/features/src/main/resources/features.xml
@@ -119,14 +119,18 @@
<feature version="${project.version}">cxf-ws-addr</feature>
<bundle start-level="40" dependency="true">mvn:net.sf.ehcache/ehcache/${cxf.ehcache.version}</bundle>
<bundle start-level="40">mvn:org.apache.cxf/cxf-rt-ws-security/${project.version}</bundle>
- <bundle start-level="40">mvn:org.apache.cxf/cxf-rt-security/${project.version}</bundle>
+ <bundle start-level="40">mvn:org.apache.cxf/cxf-rt-security-saml/${project.version}</bundle>
</feature>
<feature name="cxf-rt-security" version="${project.version}" resolver="(obr)">
<feature version="${project.version}">cxf-core</feature>
<feature version="${project.version}">cxf-wsdl</feature>
- <feature version="${cxf.wss4j.version}">wss4j</feature>
<bundle start-level="40">mvn:org.apache.cxf/cxf-rt-security/${project.version}</bundle>
</feature>
+ <feature name="cxf-rt-security-saml" version="${project.version}" resolver="(obr)">
+ <feature version="${project.version}">cxf-rt-security</feature>
+ <feature version="${cxf.wss4j.version}">wss4j</feature>
+ <bundle start-level="40">mvn:org.apache.cxf/cxf-rt-security-saml/${project.version}</bundle>
+ </feature>
<feature name="cxf-http" version="${project.version}" resolver="(obr)">
<feature version="${project.version}">cxf-core</feature>
<bundle start-level="40">mvn:${cxf.servlet-api.group}/${cxf.servlet-api.artifact}/${cxf.servlet-api.version}</bundle>
@@ -189,7 +193,7 @@
</feature>
<feature name="cxf-rs-security-xml" version="${project.version}" resolver="(obr)">
<feature version="${project.version}">cxf-jaxrs</feature>
- <feature version="${project.version}">cxf-rt-security</feature>
+ <feature version="${project.version}">cxf-rt-security-saml</feature>
<bundle start-level="40">mvn:org.apache.cxf/cxf-rt-rs-security-xml/${project.version}</bundle>
</feature>
<feature name="cxf-rs-security-sso-saml" version="${project.version}" resolver="(obr)">
http://git-wip-us.apache.org/repos/asf/cxf/blob/c04c2720/rt/pom.xml
----------------------------------------------------------------------
diff --git a/rt/pom.xml b/rt/pom.xml
index fd9da64..2458834 100644
--- a/rt/pom.xml
+++ b/rt/pom.xml
@@ -75,5 +75,6 @@
<module>management-web</module>
<module>javascript</module>
<module>security</module>
+ <module>security-saml</module>
</modules>
</project>
http://git-wip-us.apache.org/repos/asf/cxf/blob/c04c2720/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/grants/saml/Saml2BearerGrantHandler.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/grants/saml/Saml2BearerGrantHandler.java b/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/grants/saml/Saml2BearerGrantHandler.java
index 9dbc021..6a29910 100644
--- a/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/grants/saml/Saml2BearerGrantHandler.java
+++ b/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/grants/saml/Saml2BearerGrantHandler.java
@@ -52,7 +52,7 @@ import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants;
import org.apache.cxf.rs.security.oauth2.utils.OAuthUtils;
import org.apache.cxf.rs.security.saml.authorization.SecurityContextProvider;
import org.apache.cxf.rs.security.saml.authorization.SecurityContextProviderImpl;
-import org.apache.cxf.rt.security.saml.SAMLSecurityContext;
+import org.apache.cxf.rt.security.saml.claims.SAMLSecurityContext;
import org.apache.cxf.security.SecurityContext;
import org.apache.cxf.security.transport.TLSSessionInfo;
import org.apache.cxf.staxutils.StaxUtils;
http://git-wip-us.apache.org/repos/asf/cxf/blob/c04c2720/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/AbstractServiceProviderFilter.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/AbstractServiceProviderFilter.java b/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/AbstractServiceProviderFilter.java
index d3ccfac..b4afac4 100644
--- a/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/AbstractServiceProviderFilter.java
+++ b/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/AbstractServiceProviderFilter.java
@@ -55,7 +55,7 @@ import org.apache.cxf.rs.security.saml.assertion.Subject;
import org.apache.cxf.rs.security.saml.sso.state.RequestState;
import org.apache.cxf.rs.security.saml.sso.state.ResponseState;
import org.apache.cxf.rt.security.claims.ClaimCollection;
-import org.apache.cxf.rt.security.saml.SAMLSecurityContext;
+import org.apache.cxf.rt.security.saml.claims.SAMLSecurityContext;
import org.apache.cxf.security.SecurityContext;
import org.apache.cxf.staxutils.StaxUtils;
import org.apache.cxf.ws.security.SecurityConstants;
@@ -193,16 +193,16 @@ public abstract class AbstractServiceProviderFilter extends AbstractSSOSpHandler
roleAttributeName = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role";
}
ClaimCollection claims =
- org.apache.cxf.rt.security.saml.SAMLUtils.getClaims(assertionWrapper);
+ org.apache.cxf.rt.security.saml.utils.SAMLUtils.getClaims(assertionWrapper);
Set<Principal> roles =
- org.apache.cxf.rt.security.saml.SAMLUtils.parseRolesFromClaims(
+ org.apache.cxf.rt.security.saml.utils.SAMLUtils.parseRolesFromClaims(
claims, roleAttributeName, null);
SAMLSecurityContext context =
new SAMLSecurityContext(new SimplePrincipal(name), roles, claims);
- context.setIssuer(org.apache.cxf.rt.security.saml.SAMLUtils.getIssuer(assertionWrapper));
+ context.setIssuer(org.apache.cxf.rt.security.saml.utils.SAMLUtils.getIssuer(assertionWrapper));
context.setAssertionElement(
- org.apache.cxf.rt.security.saml.SAMLUtils.getAssertionElement(assertionWrapper));
+ org.apache.cxf.rt.security.saml.utils.SAMLUtils.getAssertionElement(assertionWrapper));
m.put(SecurityContext.class, context);
}
}
http://git-wip-us.apache.org/repos/asf/cxf/blob/c04c2720/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/authorization/ClaimsAuthorizingFilter.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/authorization/ClaimsAuthorizingFilter.java b/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/authorization/ClaimsAuthorizingFilter.java
index f373d91..09c3d26 100644
--- a/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/authorization/ClaimsAuthorizingFilter.java
+++ b/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/authorization/ClaimsAuthorizingFilter.java
@@ -28,8 +28,8 @@ import javax.ws.rs.core.Response;
import org.apache.cxf.interceptor.security.AccessDeniedException;
import org.apache.cxf.jaxrs.utils.JAXRSUtils;
import org.apache.cxf.message.Message;
-import org.apache.cxf.rt.security.claims.ClaimBean;
-import org.apache.cxf.rt.security.claims.ClaimsAuthorizingInterceptor;
+import org.apache.cxf.rt.security.saml.claims.ClaimBean;
+import org.apache.cxf.rt.security.saml.interceptor.ClaimsAuthorizingInterceptor;
public class ClaimsAuthorizingFilter implements ContainerRequestFilter {
http://git-wip-us.apache.org/repos/asf/cxf/blob/c04c2720/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/authorization/SecurityContextProviderImpl.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/authorization/SecurityContextProviderImpl.java b/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/authorization/SecurityContextProviderImpl.java
index 604efb5..9899085 100644
--- a/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/authorization/SecurityContextProviderImpl.java
+++ b/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/authorization/SecurityContextProviderImpl.java
@@ -25,9 +25,9 @@ import org.w3c.dom.Element;
import org.apache.cxf.message.Message;
import org.apache.cxf.rs.security.saml.assertion.Subject;
import org.apache.cxf.rt.security.claims.ClaimCollection;
-import org.apache.cxf.rt.security.claims.SAMLClaim;
-import org.apache.cxf.rt.security.saml.SAMLSecurityContext;
-import org.apache.cxf.rt.security.saml.SAMLUtils;
+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.wss4j.common.saml.SamlAssertionWrapper;
import org.apache.wss4j.common.saml.builder.SAML2Constants;
http://git-wip-us.apache.org/repos/asf/cxf/blob/c04c2720/rt/security-saml/pom.xml
----------------------------------------------------------------------
diff --git a/rt/security-saml/pom.xml b/rt/security-saml/pom.xml
new file mode 100644
index 0000000..d740e27
--- /dev/null
+++ b/rt/security-saml/pom.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>cxf-rt-security-saml</artifactId>
+ <packaging>bundle</packaging>
+ <name>Apache CXF Runtime SAML Security functionality</name>
+ <description>Apache CXF Runtime SAML Security functionality</description>
+ <url>http://cxf.apache.org</url>
+ <parent>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-parent</artifactId>
+ <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>
+ <artifactId>cxf-rt-security</artifactId>
+ <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>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
http://git-wip-us.apache.org/repos/asf/cxf/blob/c04c2720/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/claims/ClaimBean.java
----------------------------------------------------------------------
diff --git a/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/claims/ClaimBean.java b/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/claims/ClaimBean.java
new file mode 100644
index 0000000..4d9606f
--- /dev/null
+++ b/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/claims/ClaimBean.java
@@ -0,0 +1,51 @@
+/**
+ * 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 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;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/c04c2720/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/claims/SAMLClaim.java
----------------------------------------------------------------------
diff --git a/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/claims/SAMLClaim.java b/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/claims/SAMLClaim.java
new file mode 100644
index 0000000..5fb080d
--- /dev/null
+++ b/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/claims/SAMLClaim.java
@@ -0,0 +1,68 @@
+/**
+ * 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 org.apache.cxf.rt.security.claims.Claim;
+
+
+/**
+ * This represents a Claim that is coupled to a SAML Assertion
+ */
+public class SAMLClaim extends Claim {
+
+ /**
+ * This configuration tag specifies the default attribute name where the roles are present
+ * The default is "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role".
+ */
+ public static final String SAML_ROLE_ATTRIBUTENAME_DEFAULT =
+ "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role";
+
+ private static final long serialVersionUID = 5530712294179589442L;
+
+ private String nameFormat;
+ private String name;
+ private String friendlyName;
+
+ public String getNameFormat() {
+ return nameFormat;
+ }
+
+ public void setNameFormat(String nameFormat) {
+ this.nameFormat = nameFormat;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getFriendlyName() {
+ return friendlyName;
+ }
+
+ public void setFriendlyName(String friendlyName) {
+ this.friendlyName = friendlyName;
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/c04c2720/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/claims/SAMLSecurityContext.java
----------------------------------------------------------------------
diff --git a/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/claims/SAMLSecurityContext.java b/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/claims/SAMLSecurityContext.java
new file mode 100644
index 0000000..b9b012a
--- /dev/null
+++ b/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/claims/SAMLSecurityContext.java
@@ -0,0 +1,104 @@
+/**
+ * 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.security.Principal;
+import java.util.Set;
+
+import org.w3c.dom.Element;
+import org.apache.cxf.rt.security.claims.ClaimCollection;
+import org.apache.cxf.rt.security.claims.ClaimsSecurityContext;
+
+public class SAMLSecurityContext implements ClaimsSecurityContext {
+
+ private final Principal principal;
+ private Set<Principal> roles;
+ private Element assertionElement;
+ private String issuer;
+ private ClaimCollection claims;
+
+ public SAMLSecurityContext(Principal principal) {
+ this(principal, null);
+ }
+
+ public SAMLSecurityContext(
+ Principal principal,
+ Set<Principal> roles
+ ) {
+ this(principal, roles, null);
+ }
+
+ public SAMLSecurityContext(
+ Principal principal,
+ Set<Principal> roles,
+ ClaimCollection claims
+ ) {
+ this.principal = principal;
+ this.roles = roles;
+ this.claims = claims;
+ }
+
+ public ClaimCollection getClaims() {
+ return claims;
+ }
+
+ public Principal getUserPrincipal() {
+ return principal;
+ }
+
+ public boolean isUserInRole(String role) {
+ if (roles == null) {
+ return false;
+ }
+ for (Principal principalRole : roles) {
+ if (principalRole.getName().equals(role)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public javax.security.auth.Subject getSubject() {
+ return null;
+ }
+
+ public void setUserRoles(Set<Principal> userRoles) {
+ this.roles = userRoles;
+ }
+
+ public Set<Principal> getUserRoles() {
+ return roles;
+ }
+
+ public void setAssertionElement(Element assertionElement) {
+ this.assertionElement = assertionElement;
+ }
+
+ public Element getAssertionElement() {
+ return assertionElement;
+ }
+
+ public void setIssuer(String issuer) {
+ this.issuer = issuer;
+ }
+
+ public String getIssuer() {
+ return issuer;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/c04c2720/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/interceptor/ClaimsAuthorizingInterceptor.java
----------------------------------------------------------------------
diff --git a/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/interceptor/ClaimsAuthorizingInterceptor.java b/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/interceptor/ClaimsAuthorizingInterceptor.java
new file mode 100644
index 0000000..c0244ea
--- /dev/null
+++ b/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/interceptor/ClaimsAuthorizingInterceptor.java
@@ -0,0 +1,244 @@
+/**
+ * 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.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Logger;
+
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.common.util.ClassHelper;
+import org.apache.cxf.interceptor.Fault;
+import org.apache.cxf.interceptor.security.AccessDeniedException;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.phase.AbstractPhaseInterceptor;
+import org.apache.cxf.phase.Phase;
+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.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.cxf.service.Service;
+import org.apache.cxf.service.invoker.MethodDispatcher;
+import org.apache.cxf.service.model.BindingOperationInfo;
+
+
+public class ClaimsAuthorizingInterceptor extends AbstractPhaseInterceptor<Message> {
+
+ private static final Logger LOG = LogUtils.getL7dLogger(ClaimsAuthorizingInterceptor.class);
+
+ private static final Set<String> SKIP_METHODS;
+ static {
+ SKIP_METHODS = new HashSet<>();
+ SKIP_METHODS.addAll(Arrays.asList(
+ new String[] {"wait", "notify", "notifyAll",
+ "equals", "toString", "hashCode"}));
+ }
+
+ private Map<String, List<ClaimBean>> claims = new HashMap<>();
+ private Map<String, String> nameAliases = Collections.emptyMap();
+ private Map<String, String> formatAliases = Collections.emptyMap();
+
+ public ClaimsAuthorizingInterceptor() {
+ super(Phase.PRE_INVOKE);
+ }
+
+ public void handleMessage(Message message) throws Fault {
+ SecurityContext sc = message.get(SecurityContext.class);
+ if (!(sc instanceof SAMLSecurityContext)) {
+ throw new AccessDeniedException("Security Context is unavailable or unrecognized");
+ }
+
+ Method method = getTargetMethod(message);
+
+ if (authorize((SAMLSecurityContext)sc, method)) {
+ return;
+ }
+
+ throw new AccessDeniedException("Unauthorized");
+ }
+
+ public void setClaims(Map<String, List<ClaimBean>> claimsMap) {
+ claims.putAll(claimsMap);
+ }
+
+ protected Method getTargetMethod(Message m) {
+ BindingOperationInfo bop = m.getExchange().get(BindingOperationInfo.class);
+ if (bop != null) {
+ MethodDispatcher md = (MethodDispatcher)
+ m.getExchange().get(Service.class).get(MethodDispatcher.class.getName());
+ return md.getMethod(bop);
+ }
+ Method method = (Method)m.get("org.apache.cxf.resource.method");
+ if (method != null) {
+ return method;
+ }
+ throw new AccessDeniedException("Method is not available : Unauthorized");
+ }
+
+ protected boolean authorize(SAMLSecurityContext sc, Method method) {
+ List<ClaimBean> list = claims.get(method.getName());
+ org.apache.cxf.rt.security.claims.ClaimCollection actualClaims = sc.getClaims();
+
+ for (ClaimBean claimBean : list) {
+ org.apache.cxf.rt.security.claims.Claim claim = claimBean.getClaim();
+ org.apache.cxf.rt.security.claims.Claim matchingClaim = null;
+ for (org.apache.cxf.rt.security.claims.Claim cl : actualClaims) {
+ if (cl instanceof SAMLClaim
+ && ((SAMLClaim)cl).getName().equals(((SAMLClaim)claim).getName())
+ && ((SAMLClaim)cl).getNameFormat().equals(((SAMLClaim)claim).getNameFormat())) {
+ matchingClaim = cl;
+ break;
+ }
+ }
+ if (matchingClaim == null) {
+ if (claimBean.getClaimMode() == ClaimMode.STRICT) {
+ return false;
+ } else {
+ continue;
+ }
+ }
+ List<Object> claimValues = claim.getValues();
+ List<Object> matchingClaimValues = matchingClaim.getValues();
+ if (claimBean.isMatchAll()
+ && !matchingClaimValues.containsAll(claimValues)) {
+ return false;
+ } else {
+ boolean matched = false;
+ for (Object value : matchingClaimValues) {
+ if (claimValues.contains(value)) {
+ matched = true;
+ break;
+ }
+ }
+ if (!matched) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ public void setSecuredObject(Object object) {
+ Class<?> cls = ClassHelper.getRealClass(object);
+ findClaims(cls);
+ if (claims.isEmpty()) {
+ LOG.warning("The claims list is empty, the service object is not protected");
+ }
+ }
+
+ protected void findClaims(Class<?> cls) {
+ if (cls == null || cls == Object.class) {
+ return;
+ }
+ List<ClaimBean> clsClaims =
+ getClaims(cls.getAnnotation(Claims.class), cls.getAnnotation(Claim.class));
+ for (Method m : cls.getMethods()) {
+ if (SKIP_METHODS.contains(m.getName())) {
+ continue;
+ }
+ List<ClaimBean> methodClaims =
+ getClaims(m.getAnnotation(Claims.class), m.getAnnotation(Claim.class));
+
+ List<ClaimBean> allClaims = new ArrayList<>(methodClaims);
+ for (ClaimBean bean : clsClaims) {
+ if (isClaimOverridden(bean, methodClaims)) {
+ continue;
+ }
+ allClaims.add(bean);
+ }
+
+ claims.put(m.getName(), allClaims);
+ }
+ if (!claims.isEmpty()) {
+ return;
+ }
+
+ findClaims(cls.getSuperclass());
+
+ if (!claims.isEmpty()) {
+ return;
+ }
+
+ for (Class<?> interfaceCls : cls.getInterfaces()) {
+ findClaims(interfaceCls);
+ }
+ }
+
+ private static boolean isClaimOverridden(ClaimBean bean, List<ClaimBean> mClaims) {
+ for (ClaimBean methodBean : mClaims) {
+ if (bean.getClaim().getName().equals(methodBean.getClaim().getName())
+ && bean.getClaim().getNameFormat().equals(methodBean.getClaim().getNameFormat())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private List<ClaimBean> getClaims(
+ Claims claimsAnn, Claim claimAnn) {
+ List<ClaimBean> claimsList = new ArrayList<>();
+
+ List<Claim> annClaims = new ArrayList<>();
+ if (claimsAnn != null) {
+ annClaims.addAll(Arrays.asList(claimsAnn.value()));
+ } else if (claimAnn != null) {
+ annClaims.add(claimAnn);
+ }
+ for (Claim ann : annClaims) {
+ SAMLClaim claim = new SAMLClaim();
+
+ String claimName = ann.name();
+ if (nameAliases.containsKey(claimName)) {
+ claimName = nameAliases.get(claimName);
+ }
+ String claimFormat = ann.format();
+ if (formatAliases.containsKey(claimFormat)) {
+ claimFormat = formatAliases.get(claimFormat);
+ }
+
+ claim.setName(claimName);
+ claim.setNameFormat(claimFormat);
+ for (String value : ann.value()) {
+ claim.addValue(value);
+ }
+
+ claimsList.add(new ClaimBean(claim, ann.mode(), ann.matchAll()));
+ }
+ return claimsList;
+ }
+
+ public void setNameAliases(Map<String, String> nameAliases) {
+ this.nameAliases = nameAliases;
+ }
+
+ public void setFormatAliases(Map<String, String> formatAliases) {
+ this.formatAliases = formatAliases;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/c04c2720/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/utils/SAMLUtils.java
----------------------------------------------------------------------
diff --git a/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/utils/SAMLUtils.java b/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/utils/SAMLUtils.java
new file mode 100644
index 0000000..5cb5bd6
--- /dev/null
+++ b/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/utils/SAMLUtils.java
@@ -0,0 +1,141 @@
+/**
+ * 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.utils;
+
+import java.net.URI;
+import java.security.Principal;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.w3c.dom.Element;
+import org.apache.cxf.common.security.SimpleGroup;
+import org.apache.cxf.rt.security.claims.Claim;
+import org.apache.cxf.rt.security.claims.ClaimCollection;
+import org.apache.cxf.rt.security.saml.claims.SAMLClaim;
+import org.apache.wss4j.common.saml.SamlAssertionWrapper;
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.saml.common.SAMLVersion;
+import org.opensaml.saml.saml2.core.Attribute;
+import org.opensaml.saml.saml2.core.AttributeStatement;
+
+public final class SAMLUtils {
+
+ private SAMLUtils() {
+
+ }
+
+ /**
+ * Extract Claims from a SAML Assertion
+ */
+ public static ClaimCollection getClaims(SamlAssertionWrapper assertion) {
+ ClaimCollection claims = new ClaimCollection();
+
+ if (assertion.getSamlVersion().equals(SAMLVersion.VERSION_20)) {
+ List<AttributeStatement> statements = assertion.getSaml2().getAttributeStatements();
+ for (AttributeStatement as : statements) {
+ for (Attribute atr : as.getAttributes()) {
+ SAMLClaim claim = new SAMLClaim();
+ claim.setClaimType(URI.create(atr.getName()));
+
+ claim.setName(atr.getName());
+ claim.setNameFormat(atr.getNameFormat());
+ claim.setFriendlyName(atr.getFriendlyName());
+
+ for (XMLObject o : atr.getAttributeValues()) {
+ String attrValue = o.getDOM().getTextContent();
+ claim.getValues().add(attrValue);
+ }
+
+ claims.add(claim);
+ }
+ }
+ } else {
+ List<org.opensaml.saml.saml1.core.AttributeStatement> attributeStatements =
+ assertion.getSaml1().getAttributeStatements();
+
+ for (org.opensaml.saml.saml1.core.AttributeStatement statement : attributeStatements) {
+ for (org.opensaml.saml.saml1.core.Attribute atr : statement.getAttributes()) {
+ SAMLClaim claim = new SAMLClaim();
+
+ String claimType = atr.getAttributeName();
+ if (atr.getAttributeNamespace() != null) {
+ claimType = atr.getAttributeNamespace() + "/" + claimType;
+ }
+ claim.setClaimType(URI.create(claimType));
+
+ claim.setName(atr.getAttributeName());
+ claim.setNameFormat(atr.getAttributeNamespace());
+
+ for (XMLObject o : atr.getAttributeValues()) {
+ String attrValue = o.getDOM().getTextContent();
+ claim.getValues().add(attrValue);
+ }
+
+ claims.add(claim);
+ }
+ }
+ }
+
+ return claims;
+ }
+
+ /**
+ * Extract roles from the given Claims
+ */
+ public static Set<Principal> parseRolesFromClaims(
+ ClaimCollection claims,
+ String name,
+ String nameFormat
+ ) {
+ String roleAttributeName = name;
+ if (roleAttributeName == null) {
+ roleAttributeName = SAMLClaim.SAML_ROLE_ATTRIBUTENAME_DEFAULT;
+ }
+
+ Set<Principal> roles = new HashSet<>();
+
+ for (Claim claim : claims) {
+ if (claim instanceof SAMLClaim && ((SAMLClaim)claim).getName().equals(name)
+ && (nameFormat == null
+ || claim instanceof SAMLClaim && nameFormat.equals(((SAMLClaim)claim).getNameFormat()))) {
+ for (Object claimValue : claim.getValues()) {
+ if (claimValue instanceof String) {
+ roles.add(new SimpleGroup((String)claimValue));
+ }
+ }
+ if (claim.getValues().size() > 1) {
+ // Don't search for other attributes with the same name if > 1 claim value
+ break;
+ }
+ }
+ }
+
+ return roles;
+ }
+
+ public static String getIssuer(Object assertion) {
+ return ((SamlAssertionWrapper)assertion).getIssuerString();
+ }
+
+ public static Element getAssertionElement(Object assertion) {
+ return ((SamlAssertionWrapper)assertion).getElement();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/c04c2720/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/xacml/AbstractXACMLAuthorizingInterceptor.java
----------------------------------------------------------------------
diff --git a/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/xacml/AbstractXACMLAuthorizingInterceptor.java b/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/xacml/AbstractXACMLAuthorizingInterceptor.java
new file mode 100644
index 0000000..590b324
--- /dev/null
+++ b/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/xacml/AbstractXACMLAuthorizingInterceptor.java
@@ -0,0 +1,170 @@
+/**
+ * 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.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.helpers.DOMUtils;
+import org.apache.cxf.interceptor.Fault;
+import org.apache.cxf.interceptor.security.AccessDeniedException;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.phase.AbstractPhaseInterceptor;
+import org.apache.cxf.phase.Phase;
+import org.apache.cxf.security.LoginSecurityContext;
+import org.apache.cxf.security.SecurityContext;
+import org.apache.wss4j.common.saml.OpenSAMLUtil;
+import org.apache.wss4j.common.util.DOM2Writer;
+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.StatusType;
+
+
+/**
+ * An abstract interceptor to perform an XACML authorization request to a remote PDP,
+ * and make an authorization decision based on the response. It takes the principal and roles
+ * from the SecurityContext, and uses the XACMLRequestBuilder to construct an XACML Request
+ * statement.
+ *
+ * This class must be subclassed to actually perform the request to the PDP.
+ *
+ * @deprecated: Use XACMLAuthorizingInterceptor instead
+ */
+@Deprecated
+public abstract class AbstractXACMLAuthorizingInterceptor extends AbstractPhaseInterceptor<Message> {
+
+ private static final Logger LOG = LogUtils.getL7dLogger(AbstractXACMLAuthorizingInterceptor.class);
+
+ private XACMLRequestBuilder requestBuilder = new DefaultXACMLRequestBuilder();
+
+ public AbstractXACMLAuthorizingInterceptor() {
+ super(Phase.PRE_INVOKE);
+ org.apache.wss4j.common.saml.OpenSAMLUtil.initSamlEngine();
+ }
+
+ public void handleMessage(Message message) throws Fault {
+ SecurityContext sc = message.get(SecurityContext.class);
+
+ if (sc instanceof LoginSecurityContext) {
+ Principal principal = sc.getUserPrincipal();
+
+ LoginSecurityContext loginSecurityContext = (LoginSecurityContext)sc;
+ Set<Principal> principalRoles = loginSecurityContext.getUserRoles();
+ List<String> roles = new ArrayList<>();
+ if (principalRoles != null) {
+ for (Principal p : principalRoles) {
+ if (p != principal) {
+ roles.add(p.getName());
+ }
+ }
+ }
+
+ try {
+ if (authorize(principal, roles, message)) {
+ return;
+ }
+ } catch (Exception e) {
+ LOG.log(Level.FINE, "Unauthorized: " + e.getMessage(), e);
+ throw new AccessDeniedException("Unauthorized");
+ }
+ } else {
+ LOG.log(
+ Level.FINE,
+ "The SecurityContext was not an instance of LoginSecurityContext. No authorization "
+ + "is possible as a result"
+ );
+ }
+
+ throw new AccessDeniedException("Unauthorized");
+ }
+
+ public XACMLRequestBuilder getRequestBuilder() {
+ return requestBuilder;
+ }
+
+ public void setRequestBuilder(XACMLRequestBuilder requestBuilder) {
+ this.requestBuilder = requestBuilder;
+ }
+
+ /**
+ * Perform a (remote) authorization decision and return a boolean depending on the result
+ */
+ protected boolean authorize(
+ Principal principal, List<String> roles, Message message
+ ) throws Exception {
+ RequestType request = requestBuilder.createRequest(principal, roles, message);
+ if (LOG.isLoggable(Level.FINE)) {
+ Document doc = DOMUtils.createDocument();
+ Element requestElement = OpenSAMLUtil.toDom(request, doc);
+ LOG.log(Level.FINE, DOM2Writer.nodeToString(requestElement));
+ }
+
+ ResponseType response = performRequest(request, message);
+
+ List<ResultType> results = response.getResults();
+
+ if (results == null) {
+ return false;
+ }
+
+ for (ResultType result : results) {
+ // Handle any Obligations returned by the PDP
+ handleObligations(request, principal, message, result);
+
+ DECISION decision = result.getDecision() != null ? result.getDecision().getDecision() : DECISION.Deny;
+ String code = "";
+ String statusMessage = "";
+ if (result.getStatus() != null) {
+ StatusType status = result.getStatus();
+ code = status.getStatusCode() != null ? status.getStatusCode().getValue() : "";
+ statusMessage = status.getStatusMessage() != null ? status.getStatusMessage().getValue() : "";
+ }
+ LOG.fine("XACML authorization result: " + decision + ", code: " + code + ", message: " + statusMessage);
+ return decision == DECISION.Permit;
+ }
+
+ return false;
+ }
+
+ public abstract ResponseType performRequest(RequestType request, Message message) throws Exception;
+
+ /**
+ * Handle any Obligations returned by the PDP
+ */
+ protected void handleObligations(
+ RequestType request,
+ Principal principal,
+ Message message,
+ ResultType result
+ ) throws Exception {
+ // Do nothing by default
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/c04c2720/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/xacml/CXFMessageParser.java
----------------------------------------------------------------------
diff --git a/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/xacml/CXFMessageParser.java b/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/xacml/CXFMessageParser.java
new file mode 100644
index 0000000..1af0f5e
--- /dev/null
+++ b/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/xacml/CXFMessageParser.java
@@ -0,0 +1,97 @@
+/**
+ * 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 javax.xml.namespace.QName;
+
+import org.w3c.dom.Element;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.rt.security.saml.claims.SAMLSecurityContext;
+import org.apache.cxf.security.SecurityContext;
+import org.apache.wss4j.common.ext.WSSecurityException;
+import org.apache.wss4j.common.saml.SamlAssertionWrapper;
+
+public class CXFMessageParser {
+ private Message message;
+
+ /**
+ * @param message
+ */
+ public CXFMessageParser(Message message) {
+ this.message = message;
+ }
+
+ public boolean isSOAPService() {
+ return getWSDLOperation() != null;
+ }
+
+ public QName getWSDLOperation() {
+ if (message != null && message.get(Message.WSDL_OPERATION) != null) {
+ return (QName)message.get(Message.WSDL_OPERATION);
+ }
+ return null;
+ }
+
+ public QName getWSDLService() {
+ if (message != null && message.get(Message.WSDL_SERVICE) != null) {
+ return (QName)message.get(Message.WSDL_SERVICE);
+ }
+ return null;
+ }
+
+ /**
+ * @param fullRequestURL Whether to send the full Request URL as the resource or not. If set to true, the
+ * full Request URL will be sent for both a JAX-WS and JAX-RS service. If set to false (the
+ * default), a JAX-WS service will send the "{namespace}operation" QName, and a JAX-RS service
+ * will send the RequestURI (i.e. minus the initial https:<ip> prefix)
+ */
+ public String getResourceURI(boolean fullRequestURL) {
+ String property = fullRequestURL ? Message.REQUEST_URL : Message.REQUEST_URI;
+ if (message != null && message.get(property) != null) {
+ return (String)message.get(property);
+ }
+ return null;
+ }
+
+ public String getAction(String defaultSOAPAction) {
+ String actionToUse = defaultSOAPAction;
+ // For REST use the HTTP Verb
+ if (message.get(Message.WSDL_OPERATION) == null && message.get(Message.HTTP_REQUEST_METHOD) != null) {
+ actionToUse = (String)message.get(Message.HTTP_REQUEST_METHOD);
+ }
+ return actionToUse;
+ }
+
+ /**
+ * Get the Issuer of the SAML Assertion
+ */
+ public String getIssuer() throws WSSecurityException {
+ SecurityContext sc = message.get(SecurityContext.class);
+
+ if (sc instanceof SAMLSecurityContext) {
+ Element assertionElement = ((SAMLSecurityContext)sc).getAssertionElement();
+ if (assertionElement != null) {
+ SamlAssertionWrapper wrapper = new SamlAssertionWrapper(assertionElement);
+ return wrapper.getIssuerString();
+ }
+ }
+
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/c04c2720/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/xacml/DefaultXACMLRequestBuilder.java
----------------------------------------------------------------------
diff --git a/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/xacml/DefaultXACMLRequestBuilder.java b/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/xacml/DefaultXACMLRequestBuilder.java
new file mode 100644
index 0000000..02d115f
--- /dev/null
+++ b/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/xacml/DefaultXACMLRequestBuilder.java
@@ -0,0 +1,217 @@
+/**
+ * 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.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import javax.xml.namespace.QName;
+
+import org.apache.cxf.message.Message;
+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;
+
+/**
+ * This class constructs an XACML Request given a Principal, list of roles and MessageContext,
+ * following the SAML 2.0 profile of XACML 2.0. The principal name is inserted as the Subject ID,
+ * and the list of roles associated with that principal are inserted as Subject roles. The action
+ * to send defaults to "execute".
+ *
+ * For a SOAP Service, the resource-id Attribute refers to the
+ * "{serviceNamespace}serviceName#{operationNamespace}operationName" String (shortened to
+ * "{serviceNamespace}serviceName#operationName" if the namespaces are identical). The
+ * "{serviceNamespace}serviceName", "{operationNamespace}operationName" and resource URI are also
+ * sent to simplify processing at the PDP side.
+ *
+ * For a REST service the request URL is the resource. You can also configure the ability to
+ * send the truncated request URI instead for a SOAP or REST service. The current DateTime is
+ * also sent in an Environment, however this can be disabled via configuration.
+ */
+public class DefaultXACMLRequestBuilder implements XACMLRequestBuilder {
+
+ private boolean sendDateTime = true;
+ private String action = "execute";
+ private boolean sendFullRequestURL = true;
+
+ /**
+ * Create an XACML Request given a Principal, list of roles and Message.
+ */
+ public RequestType createRequest(Principal principal, List<String> roles, Message message)
+ throws Exception {
+ CXFMessageParser messageParser = new CXFMessageParser(message);
+ String issuer = messageParser.getIssuer();
+
+ String actionToUse = messageParser.getAction(action);
+
+ SubjectType subjectType = createSubjectType(principal, roles, issuer);
+ ResourceType resourceType = createResourceType(messageParser);
+ AttributeType actionAttribute = createAttribute(XACMLConstants.ACTION_ID, XACMLConstants.XS_STRING,
+ null, actionToUse);
+ ActionType actionType = RequestComponentBuilder.createActionType(Collections.singletonList(actionAttribute));
+
+ return RequestComponentBuilder.createRequestType(Collections.singletonList(subjectType),
+ Collections.singletonList(resourceType),
+ actionType,
+ createEnvironmentType());
+ }
+
+ private ResourceType createResourceType(CXFMessageParser messageParser) {
+ List<AttributeType> attributes = new ArrayList<>();
+
+ // Resource-id
+ String resourceId = null;
+ boolean isSoapService = messageParser.isSOAPService();
+ if (isSoapService) {
+ QName serviceName = messageParser.getWSDLService();
+ QName operationName = messageParser.getWSDLOperation();
+
+ if (serviceName != null) {
+ resourceId = serviceName.toString() + "#";
+ if (serviceName.getNamespaceURI() != null
+ && serviceName.getNamespaceURI().equals(operationName.getNamespaceURI())) {
+ resourceId += operationName.getLocalPart();
+ } else {
+ resourceId += operationName.toString();
+ }
+ } else {
+ resourceId = operationName.toString();
+ }
+ } else {
+ resourceId = messageParser.getResourceURI(sendFullRequestURL);
+ }
+
+ attributes.add(createAttribute(XACMLConstants.RESOURCE_ID, XACMLConstants.XS_STRING, null,
+ resourceId));
+
+ if (isSoapService) {
+ // WSDL Service
+ QName wsdlService = messageParser.getWSDLService();
+ if (wsdlService != null) {
+ attributes.add(createAttribute(XACMLConstants.RESOURCE_WSDL_SERVICE_ID, XACMLConstants.XS_STRING, null,
+ wsdlService.toString()));
+ }
+
+ // WSDL Operation
+ QName wsdlOperation = messageParser.getWSDLOperation();
+ attributes.add(createAttribute(XACMLConstants.RESOURCE_WSDL_OPERATION_ID, XACMLConstants.XS_STRING, null,
+ wsdlOperation.toString()));
+
+ // WSDL Endpoint
+ String endpointURI = messageParser.getResourceURI(sendFullRequestURL);
+ attributes.add(createAttribute(XACMLConstants.RESOURCE_WSDL_ENDPOINT, XACMLConstants.XS_STRING, null,
+ endpointURI));
+ }
+
+ return RequestComponentBuilder.createResourceType(attributes, null);
+ }
+
+ private EnvironmentType createEnvironmentType() {
+ if (sendDateTime) {
+ List<AttributeType> attributes = new ArrayList<>();
+ AttributeType environmentAttribute = createAttribute(XACMLConstants.CURRENT_DATETIME,
+ XACMLConstants.XS_DATETIME, null,
+ new DateTime().toString());
+ attributes.add(environmentAttribute);
+ return RequestComponentBuilder.createEnvironmentType(attributes);
+ }
+
+ List<AttributeType> attributes = Collections.emptyList();
+ return RequestComponentBuilder.createEnvironmentType(attributes);
+ }
+
+ private SubjectType createSubjectType(Principal principal, List<String> roles, String issuer) {
+ List<AttributeType> attributes = new ArrayList<>();
+ attributes.add(createAttribute(XACMLConstants.SUBJECT_ID, XACMLConstants.XS_STRING, issuer,
+ principal.getName()));
+
+ if (roles != null) {
+ List<AttributeValueType> roleAttributes = new ArrayList<>();
+ for (String role : roles) {
+ if (role != null) {
+ AttributeValueType subjectRoleAttributeValue =
+ RequestComponentBuilder.createAttributeValueType(role);
+ roleAttributes.add(subjectRoleAttributeValue);
+ }
+ }
+
+ if (!roleAttributes.isEmpty()) {
+ AttributeType subjectRoleAttribute =
+ createAttribute(
+ XACMLConstants.SUBJECT_ROLE,
+ XACMLConstants.XS_ANY_URI,
+ issuer,
+ roleAttributes
+ );
+ attributes.add(subjectRoleAttribute);
+ }
+ }
+
+ return RequestComponentBuilder.createSubjectType(attributes, null);
+ }
+
+ private AttributeType createAttribute(String id, String type, String issuer, List<AttributeValueType> values) {
+ return RequestComponentBuilder.createAttributeType(id, type, issuer, values);
+ }
+
+ private AttributeType createAttribute(String id, String type, String issuer, String value) {
+ return createAttribute(id, type, issuer,
+ Collections.singletonList(RequestComponentBuilder.createAttributeValueType(value)));
+ }
+
+ /**
+ * Set a new Action String to use
+ */
+ public void setAction(String action) {
+ this.action = action;
+ }
+
+ public void setSendDateTime(boolean sendDateTime) {
+ this.sendDateTime = sendDateTime;
+ }
+
+ /**
+ * Whether to send the full Request URL as the resource or not. If set to true,
+ * the full Request URL will be sent for both a JAX-WS and JAX-RS service. If set
+ * to false (the default), a JAX-WS service will send the "{namespace}operation" QName,
+ * and a JAX-RS service will send the RequestURI (i.e. minus the initial https:<ip> prefix).
+ */
+ public void setSendFullRequestURL(boolean sendFullRequestURL) {
+ this.sendFullRequestURL = sendFullRequestURL;
+ }
+
+ @Override
+ public List<String> getResources(Message message) {
+ throw new IllegalAccessError("Deprecated");
+ }
+
+ @Override
+ public String getResource(Message message) {
+ throw new IllegalAccessError("Deprecated");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/c04c2720/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/xacml/RequestComponentBuilder.java
----------------------------------------------------------------------
diff --git a/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/xacml/RequestComponentBuilder.java b/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/xacml/RequestComponentBuilder.java
new file mode 100644
index 0000000..08f8da8
--- /dev/null
+++ b/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/xacml/RequestComponentBuilder.java
@@ -0,0 +1,183 @@
+/**
+ * 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 org.opensaml.core.xml.XMLObjectBuilderFactory;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.xacml.XACMLObjectBuilder;
+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.ResourceContentType;
+import org.opensaml.xacml.ctx.ResourceType;
+import org.opensaml.xacml.ctx.SubjectType;
+
+/**
+ * A set of utility methods to construct XACML 2.0 Request statements
+ */
+public final class RequestComponentBuilder {
+ private static volatile XACMLObjectBuilder<AttributeValueType> attributeValueTypeBuilder;
+
+ private static volatile XACMLObjectBuilder<AttributeType> attributeTypeBuilder;
+
+ private static volatile XACMLObjectBuilder<SubjectType> subjectTypeBuilder;
+
+ private static volatile XACMLObjectBuilder<ResourceType> resourceTypeBuilder;
+
+ private static volatile XACMLObjectBuilder<ActionType> actionTypeBuilder;
+
+ private static volatile XACMLObjectBuilder<EnvironmentType> environmentTypeBuilder;
+
+ private static volatile XACMLObjectBuilder<RequestType> requestTypeBuilder;
+
+ private static volatile XMLObjectBuilderFactory builderFactory =
+ XMLObjectProviderRegistrySupport.getBuilderFactory();
+
+ private RequestComponentBuilder() {
+ // complete
+ }
+
+ @SuppressWarnings("unchecked")
+ public static AttributeValueType createAttributeValueType(
+ String value
+ ) {
+ if (attributeValueTypeBuilder == null) {
+ attributeValueTypeBuilder = (XACMLObjectBuilder<AttributeValueType>)
+ builderFactory.getBuilder(AttributeValueType.DEFAULT_ELEMENT_NAME);
+ }
+ AttributeValueType attributeValue = attributeValueTypeBuilder.buildObject();
+ attributeValue.setValue(value);
+
+ return attributeValue;
+ }
+
+ @SuppressWarnings("unchecked")
+ public static AttributeType createAttributeType(
+ String attributeId,
+ String dataType,
+ String issuer,
+ List<AttributeValueType> attributeValues
+ ) {
+ if (attributeTypeBuilder == null) {
+ attributeTypeBuilder = (XACMLObjectBuilder<AttributeType>)
+ builderFactory.getBuilder(AttributeType.DEFAULT_ELEMENT_NAME);
+ }
+ AttributeType attributeType = attributeTypeBuilder.buildObject();
+ attributeType.setAttributeID(attributeId);
+ attributeType.setDataType(dataType);
+ attributeType.setIssuer(issuer);
+ attributeType.getAttributeValues().addAll(attributeValues);
+
+ return attributeType;
+ }
+
+ @SuppressWarnings("unchecked")
+ public static SubjectType createSubjectType(
+ List<AttributeType> attributes,
+ String subjectCategory
+ ) {
+ if (subjectTypeBuilder == null) {
+ subjectTypeBuilder = (XACMLObjectBuilder<SubjectType>)
+ builderFactory.getBuilder(SubjectType.DEFAULT_ELEMENT_NAME);
+ }
+ SubjectType subject = subjectTypeBuilder.buildObject();
+ if (attributes != null) {
+ subject.getAttributes().addAll(attributes);
+ }
+ subject.setSubjectCategory(subjectCategory);
+
+ return subject;
+ }
+
+ @SuppressWarnings("unchecked")
+ public static ResourceType createResourceType(
+ List<AttributeType> attributes,
+ ResourceContentType resourceContent
+ ) {
+ if (resourceTypeBuilder == null) {
+ resourceTypeBuilder = (XACMLObjectBuilder<ResourceType>)
+ builderFactory.getBuilder(ResourceType.DEFAULT_ELEMENT_NAME);
+ }
+ ResourceType resource = resourceTypeBuilder.buildObject();
+ if (attributes != null) {
+ resource.getAttributes().addAll(attributes);
+ }
+ resource.setResourceContent(resourceContent);
+
+ return resource;
+ }
+
+ @SuppressWarnings("unchecked")
+ public static ActionType createActionType(
+ List<AttributeType> attributes
+ ) {
+ if (actionTypeBuilder == null) {
+ actionTypeBuilder = (XACMLObjectBuilder<ActionType>)
+ builderFactory.getBuilder(ActionType.DEFAULT_ELEMENT_NAME);
+ }
+ ActionType action = actionTypeBuilder.buildObject();
+ if (attributes != null) {
+ action.getAttributes().addAll(attributes);
+ }
+
+ return action;
+ }
+
+ @SuppressWarnings("unchecked")
+ public static EnvironmentType createEnvironmentType(
+ List<AttributeType> attributes
+ ) {
+ if (environmentTypeBuilder == null) {
+ environmentTypeBuilder = (XACMLObjectBuilder<EnvironmentType>)
+ builderFactory.getBuilder(EnvironmentType.DEFAULT_ELEMENT_NAME);
+ }
+ EnvironmentType enviroment = environmentTypeBuilder.buildObject();
+ if (attributes != null) {
+ enviroment.getAttributes().addAll(attributes);
+ }
+
+ return enviroment;
+ }
+
+ @SuppressWarnings("unchecked")
+ public static RequestType createRequestType(
+ List<SubjectType> subjects,
+ List<ResourceType> resources,
+ ActionType action,
+ EnvironmentType environment
+ ) {
+ if (requestTypeBuilder == null) {
+ requestTypeBuilder = (XACMLObjectBuilder<RequestType>)
+ builderFactory.getBuilder(RequestType.DEFAULT_ELEMENT_NAME);
+ }
+ RequestType request = requestTypeBuilder.buildObject();
+ request.getSubjects().addAll(subjects);
+ request.getResources().addAll(resources);
+ request.setAction(action);
+ request.setEnvironment(environment);
+
+ return request;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/c04c2720/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/xacml/SamlRequestComponentBuilder.java
----------------------------------------------------------------------
diff --git a/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/xacml/SamlRequestComponentBuilder.java b/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/xacml/SamlRequestComponentBuilder.java
new file mode 100644
index 0000000..c0d8255
--- /dev/null
+++ b/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/xacml/SamlRequestComponentBuilder.java
@@ -0,0 +1,118 @@
+/**
+ * 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.UUID;
+
+import org.joda.time.DateTime;
+import org.opensaml.core.xml.XMLObjectBuilderFactory;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.saml.common.SAMLObjectBuilder;
+import org.opensaml.saml.common.SAMLVersion;
+import org.opensaml.saml.saml2.core.Issuer;
+import org.opensaml.xacml.XACMLObjectBuilder;
+import org.opensaml.xacml.ctx.RequestType;
+import org.opensaml.xacml.profile.saml.SAMLProfileConstants;
+import org.opensaml.xacml.profile.saml.XACMLAuthzDecisionQueryType;
+
+/**
+ * A set of utility methods to construct XACML SAML Request statements, based on the
+ * SAML 2.0 profile of XACML v2.0 specification.
+ */
+public final class SamlRequestComponentBuilder {
+ private static volatile XACMLObjectBuilder<XACMLAuthzDecisionQueryType> xacmlAuthzDecisionQueryTypeBuilder;
+
+ private static volatile SAMLObjectBuilder<Issuer> issuerBuilder;
+
+ private static volatile XMLObjectBuilderFactory builderFactory =
+ XMLObjectProviderRegistrySupport.getBuilderFactory();
+
+ private SamlRequestComponentBuilder() {
+ // complete
+ }
+
+ /**
+ * Create an AuthzDecisionQuery using the defaults
+ */
+ public static XACMLAuthzDecisionQueryType createAuthzDecisionQuery(
+ String issuerValue,
+ RequestType request,
+ String namespace
+ ) {
+ return createAuthzDecisionQuery(false, false, issuerValue, request, namespace);
+ }
+
+ @SuppressWarnings("unchecked")
+ public static XACMLAuthzDecisionQueryType createAuthzDecisionQuery(
+ boolean inputContextOnly,
+ boolean returnContext,
+ String issuerValue,
+ RequestType request,
+ String namespace
+ ) {
+ if (xacmlAuthzDecisionQueryTypeBuilder == null) {
+ xacmlAuthzDecisionQueryTypeBuilder = (XACMLObjectBuilder<XACMLAuthzDecisionQueryType>)
+ builderFactory.getBuilder(XACMLAuthzDecisionQueryType.DEFAULT_ELEMENT_NAME_XACML20);
+ }
+ XACMLAuthzDecisionQueryType authzQuery =
+ xacmlAuthzDecisionQueryTypeBuilder.buildObject(
+ namespace,
+ XACMLAuthzDecisionQueryType.DEFAULT_ELEMENT_LOCAL_NAME,
+ SAMLProfileConstants.SAML20XACMLPROTOCOL_PREFIX
+ );
+ authzQuery.setID("_" + UUID.randomUUID().toString());
+ authzQuery.setVersion(SAMLVersion.VERSION_20);
+ authzQuery.setIssueInstant(new DateTime());
+ authzQuery.setInputContextOnly(Boolean.valueOf(inputContextOnly));
+ authzQuery.setReturnContext(Boolean.valueOf(returnContext));
+
+ if (issuerValue != null) {
+ Issuer issuer = createIssuer(issuerValue);
+ authzQuery.setIssuer(issuer);
+ }
+
+ authzQuery.setRequest(request);
+
+ return authzQuery;
+ }
+
+
+ /**
+ * Create an Issuer object
+ *
+ * @param issuerValue of type String
+ * @return an Issuer object
+ */
+ @SuppressWarnings("unchecked")
+ public static Issuer createIssuer(String issuerValue) {
+ if (issuerBuilder == null) {
+ issuerBuilder = (SAMLObjectBuilder<Issuer>)
+ builderFactory.getBuilder(Issuer.DEFAULT_ELEMENT_NAME);
+
+ }
+ Issuer issuer = issuerBuilder.buildObject();
+ //
+ // The SAML authority that is making the claim(s) in the assertion. The issuer SHOULD
+ // be unambiguous to the intended relying parties.
+ issuer.setValue(issuerValue);
+ return issuer;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/c04c2720/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/xacml/XACMLAuthorizingInterceptor.java
----------------------------------------------------------------------
diff --git a/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/xacml/XACMLAuthorizingInterceptor.java b/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/xacml/XACMLAuthorizingInterceptor.java
new file mode 100644
index 0000000..065c5a9
--- /dev/null
+++ b/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/xacml/XACMLAuthorizingInterceptor.java
@@ -0,0 +1,86 @@
+/**
+ * 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 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.message.Message;
+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.xacml.ctx.RequestType;
+import org.opensaml.xacml.ctx.ResponseType;
+
+/**
+ * An interceptor to perform an XACML authorization request to a remote PDP,
+ * and make an authorization decision based on the response. It takes the principal and roles
+ * from the SecurityContext, and uses the XACMLRequestBuilder to construct an XACML Request
+ * statement.
+ */
+@SuppressWarnings("deprecation")
+public class XACMLAuthorizingInterceptor extends AbstractXACMLAuthorizingInterceptor {
+ private PolicyDecisionPoint pdp;
+
+ public XACMLAuthorizingInterceptor(PolicyDecisionPoint pdp) {
+ super();
+ this.pdp = pdp;
+ }
+
+ @Override
+ public ResponseType performRequest(RequestType request, Message message) throws Exception {
+ Source requestSource = requestType2Source(request);
+ Source responseSource = this.pdp.evaluate(requestSource);
+ return responseSourceToResponseType(responseSource);
+ }
+
+ private Source requestType2Source(RequestType request) {
+ Document doc = DOMUtils.createDocument();
+ Element requestElement;
+ try {
+ requestElement = OpenSAMLUtil.toDom(request, doc);
+ } catch (WSSecurityException e) {
+ throw new RuntimeException("Error converting PDP RequestType to Dom", e);
+ }
+ return new DOMSource(requestElement);
+ }
+
+ private ResponseType responseSourceToResponseType(Source responseSource) {
+ try {
+ Transformer trans = TransformerFactory.newInstance().newTransformer();
+ DOMResult res = new DOMResult();
+ trans.transform(responseSource, res);
+ Node nd = res.getNode();
+ if (nd instanceof Document) {
+ nd = ((Document)nd).getDocumentElement();
+ }
+ return (ResponseType)OpenSAMLUtil.fromDom((Element)nd);
+ } catch (Exception e) {
+ throw new RuntimeException("Error converting pdp response to ResponseType", e);
+ }
+ }
+}