1 package org.collectionspace.services.common.test;
3 import java.io.ByteArrayInputStream;
5 import javax.xml.bind.JAXBException;
6 import javax.xml.namespace.QName;
8 import org.collectionspace.services.common.config.ServicesConfigReaderImpl;
9 import org.collectionspace.services.config.ServiceConfig;
10 import org.joda.time.DateTime;
11 import org.opensaml.core.config.ConfigurationService;
12 import org.opensaml.core.config.InitializationException;
13 import org.opensaml.core.config.InitializationService;
14 import org.opensaml.core.xml.XMLObjectBuilder;
15 import org.opensaml.core.xml.XMLObjectBuilderFactory;
16 import org.opensaml.core.xml.config.XMLObjectProviderRegistry;
17 import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
18 import org.opensaml.core.xml.schema.XSAny;
19 import org.opensaml.core.xml.schema.XSString;
20 import org.opensaml.saml.common.SAMLObject;
21 import org.opensaml.saml.common.SAMLVersion;
22 import org.opensaml.saml.saml2.core.Assertion;
23 import org.opensaml.saml.saml2.core.Attribute;
24 import org.opensaml.saml.saml2.core.AttributeStatement;
25 import org.opensaml.saml.saml2.core.AttributeValue;
26 import org.opensaml.saml.saml2.core.NameID;
27 import org.opensaml.saml.saml2.core.Subject;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30 import org.testng.annotations.BeforeSuite;
32 public class AbstractSecurityTestBase {
33 private static final Logger logger = LoggerFactory.getLogger(SecurityUtilsTest.class);
34 protected static String BANNER = "-------------------------------------------------------";
35 protected static String FRIENDLY_ATTR_NAME = "mail";
36 protected static String ATTR_NAME = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress";
37 protected static String ATTR_NAME_FORMAT = "urn:oasis:names:tc:SAML:2.0:attrname-format:uri";
38 protected static String EMAIL_ADDRESS = "example@example.org";
39 protected static final String USERNAME_ATTRIBUTE = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress";
40 protected static final String SSOID_ATTRIBUTE = "http://schemas.auth0.com/identifier";
41 protected static final String SSO_CONFIG_STRING = createDefaultTestConfig();
43 protected static String createDefaultTestConfig() {
44 return createTestConfig(USERNAME_ATTRIBUTE, SSOID_ATTRIBUTE);
47 protected static String createTestConfig(String usernameAttribute, String ssoAttribute) {
48 return new StringBuilder().append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
49 .append("<svc:service-config xmlns:svc='http://collectionspace.org/services/config'>")
50 .append("<security>").append("<sso>").append("<saml>").append("<single-logout />")
51 .append("<relying-party-registrations>").append("<relying-party id=\"auth0\">")
52 .append("<name>Auth0 - Scenario 11</name>")
53 .append("<icon location=\"https://cdn.auth0.com/manhattan/versions/1.4478.0/assets/badge.png\" />")
54 .append("<metadata location=\"https://dev-cf0ltyyfory6gtqm.us.auth0.com/samlp/metadata/ZXtZfEN0mj96GP8LCmEUWcpuDO0OtqKY\" />")
55 .append("<assertion-username-probes>").append("<attribute name=\"" + usernameAttribute + "\" />")
56 .append("</assertion-username-probes>").append("<assertion-sso-id-probes>")
57 .append("<attribute name=\"" + ssoAttribute + "\" />").append("</assertion-sso-id-probes>")
58 .append("</relying-party>").append("</relying-party-registrations>").append("</saml>")
59 .append("</sso>\n").append("</security>").append("</svc:service-config>").toString();
62 protected static final String MOCK_ROOT_DIR = "./";
64 protected ServiceConfig parseServiceConfigString() throws JAXBException {
65 return parseServiceConfigString(MOCK_ROOT_DIR, SSO_CONFIG_STRING);
68 protected ServiceConfig parseServiceConfigString(String mockRootDir, String seviceConfigString)
69 throws JAXBException {
70 ServicesConfigReaderImpl rdr = new ServicesConfigReaderImpl(mockRootDir);
71 ByteArrayInputStream in = new ByteArrayInputStream(seviceConfigString.getBytes());
73 serviceConfig = (ServiceConfig) rdr.parse(in, ServiceConfig.class);
74 } catch (JAXBException e) {
75 logger.warn("Could not create test service config: " + e.getLocalizedMessage());
81 /* for mocking useful SAML objects */
82 protected <T extends SAMLObject> T createNewSAMLObject(Class<T> clazz)
83 throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
84 XMLObjectBuilderFactory builderFactory = XMLObjectProviderRegistrySupport.getBuilderFactory();
85 QName defaultElementName = (QName) clazz.getDeclaredField("DEFAULT_ELEMENT_NAME").get(null);
87 @SuppressWarnings("unchecked") // NOTE: the T extends SAMLObject ought to guarantee this works
88 T theObject = (T) builderFactory.getBuilder(defaultElementName).buildObject(defaultElementName);
92 protected XSString createNewXSString(String value) {
93 XMLObjectBuilderFactory builderFactory = XMLObjectProviderRegistrySupport.getBuilderFactory();
94 @SuppressWarnings("unchecked")
95 XMLObjectBuilder<XSString> stringBuilder = (XMLObjectBuilder<XSString>) builderFactory
96 .getBuilder(XSString.TYPE_NAME);
97 XSString theString = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSString.TYPE_NAME);
98 theString.setValue(value);
102 // NOTE: making the assumption that OpenSAML parses an untyped attribute value
103 // into XSAny with value in the text content
104 protected XSAny createNewXSAny(String value) {
105 XMLObjectBuilderFactory builderFactory = XMLObjectProviderRegistrySupport.getBuilderFactory();
106 @SuppressWarnings("unchecked")
107 XMLObjectBuilder<XSAny> stringBuilder = (XMLObjectBuilder<XSAny>) builderFactory.getBuilder(XSAny.TYPE_NAME);
108 XSAny theAny = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSAny.TYPE_NAME);
109 theAny.setTextContent(value);
113 protected Assertion createTestAssertionNoAttributes()
114 throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
115 Assertion testAssertion = createNewSAMLObject(Assertion.class);
116 testAssertion.setVersion(SAMLVersion.VERSION_20);
117 testAssertion.setIssueInstant(new DateTime());
119 Subject testSubject = createNewSAMLObject(Subject.class);
120 NameID testNameId = createNewSAMLObject(NameID.class);
121 testNameId.setValue("test subject nameid");
122 testSubject.setNameID(testNameId);
123 testAssertion.setSubject(testSubject);
125 return testAssertion;
128 protected Attribute createTestAttribute(boolean hasTypedAttributeValues, String attributeName,
129 String attributeNameFormat)
130 throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
131 Attribute attr = createNewSAMLObject(Attribute.class);
132 attr.setFriendlyName(FRIENDLY_ATTR_NAME);
133 attr.setName(attributeName);
134 attr.setNameFormat(attributeNameFormat);
135 if (hasTypedAttributeValues) {
136 XSString attrValue = createNewXSString(EMAIL_ADDRESS);
137 attr.getAttributeValues().add(attrValue);
139 XSAny attrValue = createNewXSAny(EMAIL_ADDRESS);
140 attr.getAttributeValues().add(attrValue);
146 protected Attribute createDefaultTestAttribute(boolean hasTypedAttributeValues)
147 throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
148 return createTestAttribute(hasTypedAttributeValues, ATTR_NAME, ATTR_NAME_FORMAT);
151 protected Assertion createTestAssertion(Attribute attribute)
152 throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
153 Assertion testAssertion = createTestAssertionNoAttributes();
155 AttributeStatement attrStmt = createNewSAMLObject(AttributeStatement.class);
156 attrStmt.getAttributes().add(attribute);
157 testAssertion.getAttributeStatements().add(attrStmt);
159 return testAssertion;
162 protected Assertion createTestAssertionTypedAttributeValues()
163 throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
164 return createTestAssertion(createDefaultTestAttribute(true));
167 protected Assertion createTestAssertionUntypedAttributeValues()
168 throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
169 return createTestAssertion(createDefaultTestAttribute(false));
172 /* test suite setup below */
173 protected Assertion testAssertionTypedAttributeValues = null;
174 protected Assertion testAssertionUntypedAttributeValues = null;
175 protected ServiceConfig serviceConfig = null;
178 protected void setup() throws InitializationException, NoSuchFieldException, IllegalAccessException, JAXBException {
179 /* try to set up openSAML */
180 XMLObjectProviderRegistry registry = new XMLObjectProviderRegistry();
181 ConfigurationService.register(XMLObjectProviderRegistry.class, registry);
183 InitializationService.initialize();
184 } catch (InitializationException e) {
185 logger.error("Could not initialize openSAML: " + e.getLocalizedMessage(), e);
188 // try to create a test assertion with typed attribute values; fail the test if
191 testAssertionTypedAttributeValues = createTestAssertionTypedAttributeValues();
192 } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) {
193 logger.error("Could not create test assertion with typed attribute values: " + e.getLocalizedMessage(), e);
196 // try to create a test assertion with untyped attribute values; fail the test
197 // if this doesn't work
199 testAssertionUntypedAttributeValues = createTestAssertionUntypedAttributeValues();
200 } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) {
201 logger.error("Could not create test assertion with untyped attribute values: " + e.getLocalizedMessage(),
206 /* try to set up mock config */
207 serviceConfig = parseServiceConfigString();