All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.xacml4j.opensaml.OpenSamlObjectBuilder Maven / Gradle / Ivy

There is a newer version: 1.2.2
Show newest version
package org.xacml4j.opensaml;

/*
 * #%L
 * XACML/OpenSAML Integration
 * %%
 * Copyright (C) 2009 - 2014 Xacml4J.org
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 * #L%
 */

import java.io.File;
import java.io.OutputStream;

import javax.xml.namespace.QName;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.joda.time.DateTime;
import org.opensaml.DefaultBootstrap;
import org.opensaml.common.IdentifierGenerator;
import org.opensaml.common.SAMLObject;
import org.opensaml.common.SAMLObjectBuilder;
import org.opensaml.common.SAMLVersion;
import org.opensaml.common.binding.BasicEndpointSelector;
import org.opensaml.common.binding.BasicSAMLMessageContext;
import org.opensaml.common.binding.SAMLMessageContext;
import org.opensaml.common.impl.SecureRandomIdentifierGenerator;
import org.opensaml.saml2.core.Assertion;
import org.opensaml.saml2.core.Audience;
import org.opensaml.saml2.core.AudienceRestriction;
import org.opensaml.saml2.core.Conditions;
import org.opensaml.saml2.core.Issuer;
import org.opensaml.saml2.core.NameID;
import org.opensaml.saml2.core.NameIDPolicy;
import org.opensaml.saml2.core.RequestAbstractType;
import org.opensaml.saml2.core.Response;
import org.opensaml.saml2.core.Statement;
import org.opensaml.saml2.core.Status;
import org.opensaml.saml2.core.StatusCode;
import org.opensaml.saml2.core.StatusMessage;
import org.opensaml.saml2.core.StatusResponseType;
import org.opensaml.saml2.core.Subject;
import org.opensaml.saml2.metadata.EntityDescriptor;
import org.opensaml.saml2.metadata.RoleDescriptor;
import org.opensaml.saml2.metadata.provider.FilesystemMetadataProvider;
import org.opensaml.saml2.metadata.provider.MetadataProvider;
import org.opensaml.saml2.metadata.provider.MetadataProviderException;
import org.opensaml.xacml.ctx.RequestType;
import org.opensaml.xacml.ctx.ResponseType;
import org.opensaml.xacml.ctx.impl.RequestTypeMarshaller;
import org.opensaml.xacml.ctx.impl.RequestTypeUnmarshaller;
import org.opensaml.xacml.ctx.impl.ResponseTypeUnmarshaller;
import org.opensaml.xacml.profile.saml.XACMLAuthzDecisionQueryType;
import org.opensaml.xacml.profile.saml.XACMLAuthzDecisionStatementType;
import org.opensaml.xacml.profile.saml.impl.XACMLAuthzDecisionQueryTypeUnmarshaller;
import org.opensaml.xml.Configuration;
import org.opensaml.xml.ConfigurationException;
import org.opensaml.xml.XMLObject;
import org.opensaml.xml.XMLObjectBuilder;
import org.opensaml.xml.XMLObjectBuilderFactory;
import org.opensaml.xml.io.Marshaller;
import org.opensaml.xml.io.MarshallerFactory;
import org.opensaml.xml.io.MarshallingException;
import org.opensaml.xml.io.Unmarshaller;
import org.opensaml.xml.io.UnmarshallerFactory;
import org.opensaml.xml.io.UnmarshallingException;
import org.opensaml.xml.parse.BasicParserPool;
import org.opensaml.xml.signature.Signature;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import com.google.common.base.Preconditions;

public class OpenSamlObjectBuilder {
	/** Private constructor for utility class */
	private OpenSamlObjectBuilder() {}

	private static final SAMLObjectBuilder assertionBuilder;

	private static final SAMLObjectBuilder audienceBuilder;
	private static final SAMLObjectBuilder audienceRestrictionBuilder;

	private static final SAMLObjectBuilder conditionsBuilder;
	private static final SAMLObjectBuilder issuerBuilder;
	private static final SAMLObjectBuilder nameIDBuilder;
	private static final SAMLObjectBuilder nameIdPolicyBuilder;
	private static final SAMLObjectBuilder responseBuilder;
	private static final SAMLObjectBuilder statusBuilder;
	private static final SAMLObjectBuilder statusCodeBuilder;
	private static final SAMLObjectBuilder statusMessageBuilder;
	private static final SAMLObjectBuilder subjectBuilder;
	private static final XMLObjectBuilder signatureBuilder;
	private static final SAMLObjectBuilder xacml20SamlAuthzQueryBuilder;


	private static final XACMLAuthzDecisionQueryTypeUnmarshaller xacml20SamlAuthzQueryUnmarshaller;
	private static final SAMLObjectBuilder xacml20SamlAuthzStatementBuilder;

	private static final RequestTypeUnmarshaller xacml20ReqUnmarshaller;
	private static final ResponseTypeUnmarshaller xacml20ResUnmarshaller;
	private static final RequestTypeMarshaller xacml20ReqMarshaller;

	private static final XMLObjectBuilderFactory objectBuilderFactory;
	private static final UnmarshallerFactory unmarshallerFactory;
	private static final MarshallerFactory marshallerFactory;

	static {
		try {
			DefaultBootstrap.bootstrap();
		} catch (ConfigurationException e) {
			throw new IllegalStateException(e);
		}

		objectBuilderFactory = Configuration.getBuilderFactory();
		unmarshallerFactory = Configuration.getUnmarshallerFactory();
		marshallerFactory = Configuration.getMarshallerFactory();

		assertionBuilder = makeSamlObjectBuilder(Assertion.DEFAULT_ELEMENT_NAME);


		audienceBuilder = makeSamlObjectBuilder(Audience.DEFAULT_ELEMENT_NAME);
		audienceRestrictionBuilder = makeSamlObjectBuilder(AudienceRestriction.DEFAULT_ELEMENT_NAME);

		conditionsBuilder = makeSamlObjectBuilder(Conditions.DEFAULT_ELEMENT_NAME);
		issuerBuilder = makeSamlObjectBuilder(Issuer.DEFAULT_ELEMENT_NAME);
		nameIDBuilder = makeSamlObjectBuilder(NameID.DEFAULT_ELEMENT_NAME);
		nameIdPolicyBuilder = makeSamlObjectBuilder(NameIDPolicy.DEFAULT_ELEMENT_NAME);
		responseBuilder = makeSamlObjectBuilder(Response.DEFAULT_ELEMENT_NAME);
		statusBuilder = makeSamlObjectBuilder(Status.DEFAULT_ELEMENT_NAME);
		statusCodeBuilder = makeSamlObjectBuilder(StatusCode.DEFAULT_ELEMENT_NAME);
		statusMessageBuilder = makeSamlObjectBuilder(StatusMessage.DEFAULT_ELEMENT_NAME);
		subjectBuilder = makeSamlObjectBuilder(Subject.DEFAULT_ELEMENT_NAME);
		xacml20SamlAuthzQueryBuilder = makeSamlObjectBuilder(XACMLAuthzDecisionQueryType.DEFAULT_ELEMENT_NAME_XACML20);
		xacml20SamlAuthzQueryUnmarshaller = makeSamlObjectUnmarshaller(XACMLAuthzDecisionQueryType.DEFAULT_ELEMENT_NAME_XACML20);
		xacml20SamlAuthzStatementBuilder = makeSamlObjectBuilder(XACMLAuthzDecisionStatementType.DEFAULT_ELEMENT_NAME_XACML20);
		signatureBuilder = makeXmlObjectBuilder(Signature.DEFAULT_ELEMENT_NAME);

		xacml20ReqMarshaller = makeSamlObjectMarshaller(RequestType.DEFAULT_ELEMENT_NAME);

		xacml20ReqUnmarshaller = makeSamlObjectUnmarshaller(RequestType.DEFAULT_ELEMENT_NAME);
		xacml20ResUnmarshaller = makeSamlObjectUnmarshaller(ResponseType.DEFAULT_ELEMENT_NAME);
	}

	private static final IdentifierGenerator idGenerator;

	private static final TransformerFactory transformerFactory;

	static {
		try {
			transformerFactory = TransformerFactory.newInstance();
			idGenerator = new SecureRandomIdentifierGenerator();
		} catch (Exception e) {
			throw new IllegalStateException(e);
		}
	}

	private static void initializeResponse(StatusResponseType response,
			Status status, RequestAbstractType request) {
		response.setID(generateIdentifier());
		response.setVersion(SAMLVersion.VERSION_20);
		response.setIssueInstant(new DateTime());
		response.setStatus(status);
		if (request != null) {
			response.setInResponseTo(request.getID());
		}
	}

	/**
	 * A convenience method for generating a random identifier.
	 *
	 * @return A new identifier string.
	 */
	public static String generateIdentifier() {
		return idGenerator.generateIdentifier();
	}

	@SuppressWarnings("unchecked")
	private static  SAMLObjectBuilder makeSamlObjectBuilder(
			QName name) {
		SAMLObjectBuilder b = (SAMLObjectBuilder) objectBuilderFactory
				.getBuilder(name);
		Preconditions.checkState(b != null);
		return b;
	}


	@SuppressWarnings("unchecked")
	private static  XMLObjectBuilder makeXmlObjectBuilder(
			QName name) {
		XMLObjectBuilder b = objectBuilderFactory
				.getBuilder(name);
		Preconditions.checkState(b != null);
		return b;
	}

	@SuppressWarnings("unchecked")
	private static  M makeSamlObjectMarshaller(QName name) {
		M m = (M) marshallerFactory.getMarshaller(name);
		Preconditions.checkState(m != null);
		return m;
	}

	@SuppressWarnings("unchecked")
	private static  M makeSamlObjectUnmarshaller(
			QName name) {
		M u = (M) unmarshallerFactory.getUnmarshaller(name);
		Preconditions.checkState(u != null);
		return u;

	}

	public static void serialize(Node e, OutputStream out,
			boolean identOutput, boolean ommitXmlDecl) throws Exception {

		Preconditions.checkState(e != null);
		Transformer serializer = transformerFactory.newTransformer();
		serializer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, ommitXmlDecl?"no":"yes");
		serializer.setOutputProperty(OutputKeys.ENCODING, "utf-8");
		serializer.setOutputProperty(OutputKeys.METHOD, "xml");
		serializer.setOutputProperty(OutputKeys.INDENT, identOutput ? "yes": "no");
		Source source = new DOMSource(e);
		Result result = new StreamResult(out);
		serializer.transform(source, result);
	}

	public static void serialize(Node xml, OutputStream out) throws Exception
	{
		serialize(xml, out, false, false);
	}

	public static void serialize(XMLObject xml, OutputStream out) throws Exception
	{
		Marshaller m = Configuration.getMarshallerFactory().getMarshaller(xml);
		Preconditions.checkState(m != null);
		serialize(m.marshall(xml), out, false, false);
	}

	/**
	 * Static factory for OpenSAML message-context objects.
	 *
	 * @param 
	 *            The type of the request object.
	 * @param 
	 *            The type of the response object.
	 * @param 
	 *            The type of the name identifier used for subjects.
	 * @return A new message-context object.
	 */
	public static  SAMLMessageContext makeSamlMessageContext() {
		return new BasicSAMLMessageContext();
	}

	/**
	 * Static factory for SAML Assertion objects.
	 *
	 * @param issuer
	 *            The entity issuing this assertion.
	 * @return A new Assertion object.
	 */
	public static Assertion makeAssertion(String issuer) {
		Assertion assertion = assertionBuilder.buildObject();
		assertion.setID(generateIdentifier());
		assertion.setVersion(SAMLVersion.VERSION_20);
		assertion.setIssueInstant(new DateTime());
		assertion.setIssuer(makeIssuer(issuer));
		return assertion;
	}

	/**
	 * Static factory for SAML Assertion objects.
	 *
	 * @param issuer
	 *            The entity issuing this assertion.
	 * @param subject
	 *            The subject of the assertion.
	 * @return A new Assertion object.
	 */
	public static Assertion makeAssertion(String issuer, Subject subject) {
		Assertion assertion = makeAssertion(issuer);
		assertion.setSubject(subject);
		return assertion;
	}

	public static RequestType unmarshallXacml20Request(Element request)
			throws UnmarshallingException {
		return (RequestType) xacml20ReqUnmarshaller.unmarshall(request);
	}

	public static void marshallXacml20Request(RequestType request, Document doc)
		throws MarshallingException {
		xacml20ReqMarshaller.marshall(request, doc);
	}

	public static XACMLAuthzDecisionQueryType unmarshallXacml20AuthzDecisionQuery(Element request)
		throws UnmarshallingException {
		return (XACMLAuthzDecisionQueryType) xacml20SamlAuthzQueryUnmarshaller.unmarshall(request);
	}

	public static ResponseType unmarshallXacml20Response(Element request)
			throws UnmarshallingException {
		return (ResponseType) xacml20ResUnmarshaller.unmarshall(request);
	}

	public static Signature makeSiganture()
	{
		return signatureBuilder.buildObject(Signature.DEFAULT_ELEMENT_NAME);
	}

	/**
	 * Static factory for SAML Audience objects.
	 *
	 * @param uri
	 *            The audience URI.
	 * @return A new Audience object.
	 */
	public static Audience makeAudience(String uri) {
		Audience audience = audienceBuilder.buildObject();
		audience.setAudienceURI(uri);
		return audience;
	}

	public static XACMLAuthzDecisionQueryType makeXacml20SamlAuthzDecisionQuery(
			String issuer, String destination, boolean combinePolicies,
			RequestType xacml20Request) {
		XACMLAuthzDecisionQueryType xacmlQuery = xacml20SamlAuthzQueryBuilder
				.buildObject(XACMLAuthzDecisionQueryType.DEFAULT_ELEMENT_NAME_XACML20);
		Preconditions.checkState(xacmlQuery != null);
		xacmlQuery.setID(generateIdentifier());
		xacmlQuery.setIssuer(makeIssuer(issuer));
		xacmlQuery.setIssueInstant(new DateTime());
		xacmlQuery.setVersion(SAMLVersion.VERSION_20);
		xacmlQuery.setRequest(xacml20Request);
		xacmlQuery.setCombinePolicies(combinePolicies);
		xacmlQuery.setDestination(destination);
		return xacmlQuery;
	}

	public static Response makeXacml20AuthzDecisionQueryResponse(String issuer,
			XACMLAuthzDecisionQueryType request, Assertion assertion) {
		Response response = responseBuilder.buildObject(Response.DEFAULT_ELEMENT_NAME);
		initializeResponse(response, makeStatus(StatusCode.SUCCESS_URI),
				request);
		response.setIssuer(makeIssuer(issuer));
		response.getAssertions().add(assertion);
		return response;
	}


	public static Assertion makeXacml20AuthzDecisionAssertion(String issuer,
			RequestType xacml20Request, ResponseType xacml20Response)
	{
		XACMLAuthzDecisionStatementType authzStatement = xacml20SamlAuthzStatementBuilder.buildObject(
				Statement.DEFAULT_ELEMENT_NAME,
				XACMLAuthzDecisionStatementType.TYPE_NAME_XACML20);
		authzStatement.setRequest(xacml20Request);
		authzStatement.setResponse(xacml20Response);
		Assertion authzAssertion = makeAssertion(issuer);
		authzAssertion.getStatements(XACMLAuthzDecisionStatementType.DEFAULT_ELEMENT_NAME_XACML20).add(authzStatement);
		return authzAssertion;
	}

	/**
	 * Static factory for SAML AudienceRestriction objects.
	 *
	 * @return A new AudienceRestriction object.
	 */
	public static AudienceRestriction makeAudienceRestriction() {
		return audienceRestrictionBuilder.buildObject();
	}

	/**
	 * Static factory for SAML Conditions objects.
	 *
	 * @return A new Conditions object.
	 */
	public static Conditions makeConditions() {
		return conditionsBuilder.buildObject();
	}

	@SuppressWarnings("unchecked")
	public static  T unmarshall(Element source) throws Exception
	{
		Unmarshaller u = Configuration.getUnmarshallerFactory().getUnmarshaller(source);
		return (T)u.unmarshall(source);
	}

	public static Element marshall(SAMLObject o) throws Exception
	{
		Marshaller m = Configuration.getMarshallerFactory().getMarshaller(o);
		return m.marshall(o);
	}

	/**
	 * Static factory for SAML Issuer objects.
	 *
	 * @param name
	 *            The issuer of a response object. In the absence of a specific
	 *            format, this is a URI identifying the issuer.
	 * @return A new Issuer object.
	 */
	public static Issuer makeIssuer(String name) {
		Preconditions.checkState(issuerBuilder != null);
		Issuer issuer = issuerBuilder.buildObject(Issuer.DEFAULT_ELEMENT_NAME);
		issuer.setValue(name);
		return issuer;
	}

	/**
	 * Static factory for SAML NameID objects.
	 *
	 * @param name
	 *            The name represented by this object.
	 * @return A new NameID object.
	 */
	public static NameID makeNameId(String name) {
		NameID id = nameIDBuilder.buildObject();
		id.setValue(name);
		return id;
	}

	/**
	 * Static factory for SAML NameIDPolicy objects.
	 *
	 * @param format
	 *            The URI specifying the format of a class of names.
	 * @return A new NameIDPolicy object.
	 */
	public static NameIDPolicy makeNameIdPolicy(String format) {
		NameIDPolicy idPolicy = nameIdPolicyBuilder.buildObject();
		idPolicy.setFormat(format);
		return idPolicy;
	}

	/**
	 * Static factory for SAML Response objects.
	 *
	 * @param request
	 *            The request that this is a response to.
	 * @param status
	 *            The Status object indicating the success of
	 *            requested action.
	 * @return A new Response object.
	 */
	public static Response makeResponse(RequestAbstractType request,
			Status status) {
		Response response = responseBuilder.buildObject();
		initializeResponse(response, status, request);
		return response;
	}

	/**
	 * Static factory for SAML Status objects.
	 *
	 * @param code
	 *            A StatusCode object containing the SAML
	 *            status-code URI.
	 * @return A new Status object.
	 */
	public static Status makeStatus(StatusCode code) {
		Status status = statusBuilder.buildObject();
		status.setStatusCode(code);
		return status;
	}

	/**
	 * Static factory for SAML Status objects.
	 *
	 * A convenience method that generates a status object with a message.
	 *
	 * @param value
	 *            A URI specifying one of the standard SAML status codes.
	 * @param message
	 *            A string describing the status.
	 * @return A new Status object.
	 */
	public static Status makeStatus(String value, String message) {
		Status status = makeStatus(value);
		status.setStatusMessage(makeStatusMessage(message));
		return status;
	}

	/**
	 * Static factory for SAML Status objects.
	 *
	 * A convenience method that wraps the given URI in a
	 * StatusCode object.
	 *
	 * @param value
	 *            A URI specifying one of the standard SAML status codes.
	 * @return A new Status object.
	 */
	public static Status makeStatus(String value) {
		return makeStatus(makeStatusCode(value));
	}

	/**
	 * Static factory for SAML StatusCode objects.
	 *
	 * @return A new StatusCode object.
	 */
	public static StatusCode makeStatusCode() {
		return statusCodeBuilder.buildObject();
	}

	/**
	 * Static factory for SAML StatusCode objects.
	 *
	 * @param value
	 *            A URI specifying one of the standard SAML status codes.
	 * @return A new StatusCode object.
	 */
	public static StatusCode makeStatusCode(String value) {
		StatusCode code = makeStatusCode();
		code.setValue(value);
		return code;
	}

	/**
	 * Static factory for SAML StatusMessage objects.
	 *
	 * @param value
	 *            A status message string.
	 * @return A new StatusMessage object.
	 */
	public static StatusMessage makeStatusMessage(String value) {
		StatusMessage message = statusMessageBuilder.buildObject();
		message.setMessage(value);
		return message;
	}

	/**
	 * Static factory for SAML Subject objects.
	 *
	 * Returns a subject that has no distinguished identifier. The caller is
	 * expected to fill in one or more SubjectConfirmation
	 * elements.
	 *
	 * @return A new Subject object.
	 */
	public static Subject makeSubject() {
		return subjectBuilder.buildObject();
	}

	/**
	 * Static factory for SAML Subject objects.
	 *
	 * Returns a subject that has the given identifier. The caller may
	 * optionally fill in any number of SubjectConfirmation
	 * elements.
	 *
	 * @param id
	 *            The identifier for this subject.
	 * @return A new Subject object.
	 */
	public static Subject makeSubject(NameID id) {
		Subject samlSubject = makeSubject();
		samlSubject.setNameID(id);
		return samlSubject;
	}

	/**
	 * Static factory for SAML Subject objects.
	 *
	 * A convenience method that wraps the given name in a NameId
	 * object.
	 *
	 * @param name
	 *            The name identifying the subject.
	 * @return A new Subject object.
	 */
	public static Subject makeSubject(String name) {
		return makeSubject(makeNameId(name));
	}

	public static void initializeLocalEntity(
			SAMLMessageContext context,
			EntityDescriptor entity, RoleDescriptor role, QName endpointType)
	{
		context.setLocalEntityId(entity.getEntityID());
		context.setLocalEntityMetadata(entity);
		context.setLocalEntityRole(endpointType);
		context.setLocalEntityRoleMetadata(role);
		context.setOutboundMessageIssuer(entity.getEntityID());
	}

	public static void initializePeerEntity(
			SAMLMessageContext context,
			EntityDescriptor entity,
			RoleDescriptor role,
			QName endpointType,
			String binding) {
		context.setPeerEntityId(entity.getEntityID());
		context.setPeerEntityMetadata(entity);
		context.setPeerEntityRole(endpointType);
		context.setPeerEntityRoleMetadata(role);
		{
			BasicEndpointSelector selector = new BasicEndpointSelector();
			selector.setEntityMetadata(entity);
			selector.setEndpointType(endpointType);
			selector.setEntityRoleMetadata(role);
			selector.getSupportedIssuerBindings().add(binding);
			context.setPeerEntityEndpoint(selector.selectEndpoint());
		}
	}

	public static MetadataProvider getMetadata(File input) throws MetadataProviderException
	{
		FilesystemMetadataProvider provider = new FilesystemMetadataProvider(input);
		BasicParserPool parserPool = new BasicParserPool();
		parserPool.setNamespaceAware(true);
		provider.setParserPool(parserPool);
		provider.initialize();
		return provider;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy