package org.jboss.resteasy.setup;
import org.jboss.as.arquillian.api.ServerSetupTask;
import org.jboss.as.arquillian.container.ManagementClient;
import org.jboss.resteasy.utils.TestUtil;
import org.wildfly.extras.creaper.commands.security.AddLoginModule;
import org.wildfly.extras.creaper.commands.security.AddSecurityDomain;
import org.wildfly.extras.creaper.core.online.OnlineManagementClient;
import org.wildfly.extras.creaper.core.online.operations.Address;
import org.wildfly.extras.creaper.core.online.operations.Operations;
import org.wildfly.extras.creaper.core.online.operations.Values;
import org.wildfly.extras.creaper.core.online.operations.admin.Administration;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import static org.junit.Assert.assertTrue;
/**
* This abstract class implements steps needed to create PicketBox or Elytron security domain.
*
*/
public abstract class AbstractUsersRolesSecurityDomainSetup implements ServerSetupTask {
// Creaper fields
private static OnlineManagementClient managementClient;
private Operations ops;
private Administration administration;
// Properties file path
private static final String USERS_FILENAME = "users.properties";
private static final String ROLES_FILENAME = "roles.properties";
private File USERS_FILE;
private File ROLES_FILE;
// This property decides under which security subsystem will be used for the tests
private String subsystem = System.getProperty("security.domain", "picketbox");
// Security domain name shared by elytron and picketBox configuration
private String securityDomainName = "jaxrsSecDomain";
// PicketBox related settings
private Address PICKETBOX_SECURITY_DOMAIN_ADDRESS
= Address.subsystem("security").and("security-domain", securityDomainName);
private Address PICKETBOX_AUTHN_CLASSIC_ADDRESS = PICKETBOX_SECURITY_DOMAIN_ADDRESS
.and("authentication", "classic");
private static final String PICKETBOX_LOGIN_MODULE_NAME = "UsersRoles";
private Address PICKETBOX_LOGIN_MODULE_ADDRESS = PICKETBOX_AUTHN_CLASSIC_ADDRESS
.and("login-module", PICKETBOX_LOGIN_MODULE_NAME);
// Elytron related settings
private static final String ELYTRON_PROPERTIES_REALM_NAME = "propRealm";
private static final Address ELYTRON_PROPERTIES_REALM_ADDRESS
= Address.subsystem("elytron").and("properties-realm", ELYTRON_PROPERTIES_REALM_NAME);
private static final String ELYTRON_SECURITY_DOMAIN_NAME = "propertyElytronSecDomain";
private static final Address ELYTRON_SECURITY_DOMAIN_ADDRESS
= Address.subsystem("elytron").and("security-domain", ELYTRON_SECURITY_DOMAIN_NAME);
private static final String ELYTRON_PROP_HTTP_AUTHENTICATION_FACTORY_NAME = "prop-http-authentication-factory";
private static final Address ELYTRON_PROP_HTTP_AUTHENTICATION_FACTORY_ADDRESS
= Address.subsystem("elytron").and("http-authentication-factory", ELYTRON_PROP_HTTP_AUTHENTICATION_FACTORY_NAME);
private String UNDERTOW_APPLICATION_SECURITY_DOMAIN_NAME = securityDomainName;
private Address UNDERTOW_APPLICATION_SECURITY_DOMAIN_ADDRESS
= Address.subsystem("undertow").and("application-security-domain", UNDERTOW_APPLICATION_SECURITY_DOMAIN_NAME);
/**
* Set security subsystem
* @param subsystem
*/
public void setSubsystem(String subsystem) {
this.subsystem = subsystem;
}
/**
* Set security domain name related configuration
* @param securityDomainName
*/
public void setSecurityDomainName(String securityDomainName) {
this.securityDomainName = securityDomainName;
this.PICKETBOX_SECURITY_DOMAIN_ADDRESS=Address.subsystem("security").and("security-domain", securityDomainName);
this.UNDERTOW_APPLICATION_SECURITY_DOMAIN_NAME=securityDomainName;
this.UNDERTOW_APPLICATION_SECURITY_DOMAIN_ADDRESS
= Address.subsystem("undertow").and("application-security-domain", UNDERTOW_APPLICATION_SECURITY_DOMAIN_NAME);
}
/**
* Creates Files pointing to users.properties and roles.properties for the current test.
* @param folder
*/
public void createPropertiesFiles(File folder) {
this.USERS_FILE = new File(folder, USERS_FILENAME);
this.ROLES_FILE = new File(folder, ROLES_FILENAME);
}
@Override
public void setup(ManagementClient fakemanagementClient, String s) throws Exception {
// Set path for users.properties and roles.properties
setConfigurationPath();
// Create and initialize management client
managementClient = TestUtil.clientInit();
administration = new Administration(managementClient);
ops = new Operations(managementClient);
if (subsystem.equals("elytron")) {
configureElytron();
} else {
configurePicketBox();
}
}
@Override
public void tearDown(ManagementClient fakemanagementClient, String s) throws Exception {
if (subsystem.equals("elytron")) {
cleanUpElytron();
} else {
cleanUpPicketBox();
}
}
/**
* Set necessary test related paths
*/
public abstract void setConfigurationPath() throws URISyntaxException, MalformedURLException;
/**
* Creates Elytron security domain
* @throws Exception
*/
private void configureElytron() throws Exception {
// Note: This complicated setting may be simplified once WFLY-7949 is resolved
// Create Elytron properties-realm
ops.add(ELYTRON_PROPERTIES_REALM_ADDRESS, Values.empty()
.andObject("users-properties", Values.empty()
.and("path", USERS_FILE.getAbsolutePath())
.andOptional("plain-text", true))
.andObjectOptional("groups-properties", Values.empty()
.and("path", ROLES_FILE.getAbsolutePath())));
administration.reloadIfRequired();
// Create Elytron security-domain
managementClient.executeCli("/subsystem=elytron/security-domain="
+ ELYTRON_SECURITY_DOMAIN_NAME
+ ":add(realms=[{realm="
+ ELYTRON_PROPERTIES_REALM_NAME + ",role-decoder=groups-to-roles}],default-realm=propRealm,permission-mapper=default-permission-mapper)");
// Create Elytron http-authentication-factory with previous security-domain
managementClient.executeCli("/subsystem=elytron/http-authentication-factory="
+ ELYTRON_PROP_HTTP_AUTHENTICATION_FACTORY_NAME + ":add(http-server-mechanism-factory=global,security-domain="
+ ELYTRON_SECURITY_DOMAIN_NAME
+ ",mechanism-configurations=[{mechanism-name=BASIC,mechanism-realm-configurations=[{realm-name=\"Property Elytron\"}]}])");
// Set undertow application-security-domain to the custom http-authentication-factory
managementClient.executeCli("/subsystem=undertow/application-security-domain="
+ securityDomainName + ":add(http-authentication-factory="
+ ELYTRON_PROP_HTTP_AUTHENTICATION_FACTORY_NAME + ")");
administration.reloadIfRequired();
assertTrue("The elytron/properties-realm should be created", ops.exists(ELYTRON_PROPERTIES_REALM_ADDRESS));
assertTrue("The elytron/security-domain should be created", ops.exists(ELYTRON_SECURITY_DOMAIN_ADDRESS));
assertTrue("The elytron/http-authentication-factory should be created", ops.exists(ELYTRON_PROP_HTTP_AUTHENTICATION_FACTORY_ADDRESS));
assertTrue("The undertow/application-security-domain should be created", ops.exists(UNDERTOW_APPLICATION_SECURITY_DOMAIN_ADDRESS));
}
/**
* Creates PicketBox security domain
* @throws Exception
*/
private void configurePicketBox() throws Exception {
// Create security domain
AddSecurityDomain addSecurityDomain = new AddSecurityDomain.Builder(securityDomainName).build();
managementClient.apply(addSecurityDomain);
// Create login module
AddLoginModule addLoginModule = new AddLoginModule.Builder("org.jboss.security.auth.spi.UsersRolesLoginModule",
PICKETBOX_LOGIN_MODULE_NAME)
.securityDomainName(securityDomainName)
.flag("required")
.module("org.picketbox")
.addModuleOption("usersProperties", USERS_FILE.getAbsolutePath())
.addModuleOption("rolesProperties", ROLES_FILE.getAbsolutePath())
.build();
managementClient.apply(addLoginModule);
administration.reloadIfRequired();
assertTrue("The login module should be created", ops.exists(PICKETBOX_LOGIN_MODULE_ADDRESS));
}
/**
* Reverts all configuration done for Elytron
* @throws Exception
*/
private void cleanUpElytron() throws Exception {
try {
ops.removeIfExists(UNDERTOW_APPLICATION_SECURITY_DOMAIN_ADDRESS);
ops.removeIfExists(ELYTRON_PROP_HTTP_AUTHENTICATION_FACTORY_ADDRESS);
ops.removeIfExists(ELYTRON_SECURITY_DOMAIN_ADDRESS);
ops.removeIfExists(ELYTRON_PROPERTIES_REALM_ADDRESS);
administration.reloadIfRequired();
} finally {
managementClient.close();
}
}
/**
* Reverts all configuration done for PicketBox
* @throws Exception
*/
private void cleanUpPicketBox() throws Exception {
try {
ops.removeIfExists(PICKETBOX_SECURITY_DOMAIN_ADDRESS);
administration.reloadIfRequired();
} finally {
managementClient.close();
}
}
}