| @@ -0,0 +1,25 @@ | ||
| <?xml version="1.0"?> | ||
| <web-app xmlns="http://java.sun.com/xml/ns/javaee" | ||
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
| xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" | ||
| version="3.0"> | ||
|
|
||
| <login-config> | ||
| <auth-method>BASIC</auth-method> | ||
| <realm-name>Test realm</realm-name> | ||
| </login-config> | ||
|
|
||
| <security-constraint> | ||
| <web-resource-collection> | ||
| <web-resource-name>secured-area</web-resource-name> | ||
| <url-pattern>/*</url-pattern> | ||
| </web-resource-collection> | ||
| <auth-constraint> | ||
| <role-name>*</role-name> | ||
| </auth-constraint> | ||
| </security-constraint> | ||
|
|
||
| <security-role> | ||
| <role-name>*</role-name> | ||
| </security-role> | ||
| </web-app> |
| @@ -0,0 +1,67 @@ | ||
| /* | ||
| * Copyright 2019 Red Hat, Inc. | ||
| * | ||
| * Licensed 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.wildfly.test.security.common.elytron; | ||
|
|
||
| import org.jboss.as.controller.PathAddress; | ||
| import org.jboss.as.controller.PathElement; | ||
| import org.jboss.as.controller.client.ModelControllerClient; | ||
| import org.jboss.as.controller.operations.common.Util; | ||
| import org.jboss.as.test.integration.management.util.CLIWrapper; | ||
| import org.jboss.as.test.integration.security.common.Utils; | ||
| import org.jboss.dmr.ModelNode; | ||
|
|
||
| /** | ||
| * A {@link ConfigurableElement} to define a constant realm mapper resource. | ||
| * | ||
| * @author <a href="mailto:darran.lofthouse@jboss.com">Darran Lofthouse</a> | ||
| */ | ||
| public class ConstantRealmMapper implements ConfigurableElement { | ||
|
|
||
| private final PathAddress address; | ||
| private final String name; | ||
| private final String realm; | ||
|
|
||
| ConstantRealmMapper(String name, String realm) { | ||
| this.name = name; | ||
| this.address = PathAddress.pathAddress(PathElement.pathElement("subsystem", "elytron"), PathElement.pathElement("constant-realm-mapper", name)); | ||
| this.realm = realm; | ||
| } | ||
|
|
||
| @Override | ||
| public String getName() { | ||
| return name; | ||
| } | ||
|
|
||
| @Override | ||
| public void create(ModelControllerClient client, CLIWrapper cli) throws Exception { | ||
| ModelNode addOperation = Util.createAddOperation(address); | ||
| addOperation.get("realm-name").set(realm); | ||
| Utils.applyUpdate(addOperation, client); | ||
| } | ||
|
|
||
| @Override | ||
| public void remove(ModelControllerClient client, CLIWrapper cli) throws Exception { | ||
| ModelNode removeOperation = Util.createRemoveOperation(address); | ||
| Utils.applyUpdate(removeOperation, client); | ||
| } | ||
|
|
||
| public static ConfigurableElement newInstance(final String name, final String realm) { | ||
| return new ConstantRealmMapper(name, realm); | ||
| } | ||
|
|
||
|
|
||
| } |
| @@ -0,0 +1,166 @@ | ||
| /* | ||
| * Copyright 2019 Red Hat, Inc. | ||
| * | ||
| * Licensed 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.wildfly.test.security.common.elytron; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.LinkedHashMap; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.Map.Entry; | ||
|
|
||
| import org.jboss.as.controller.PathAddress; | ||
| import org.jboss.as.controller.PathElement; | ||
| import org.jboss.as.controller.client.ModelControllerClient; | ||
| import org.jboss.as.controller.operations.common.Util; | ||
| import org.jboss.as.test.integration.management.util.CLIWrapper; | ||
| import org.jboss.as.test.integration.security.common.Utils; | ||
| import org.jboss.dmr.ModelNode; | ||
|
|
||
| /** | ||
| * A {@link ConfigurableElement} to define a JDBC SecurityRealm resource. | ||
| * | ||
| * @author <a href="mailto:darran.lofthouse@jboss.com">Darran Lofthouse</a> | ||
| */ | ||
| public class JdbcSecurityRealm implements SecurityRealm { | ||
|
|
||
| private final PathAddress address; | ||
| private final String name; | ||
| private final List<ModelNode> principalQueries; | ||
|
|
||
| JdbcSecurityRealm(final String name, final List<ModelNode> principalQueries) { | ||
| this.name = name; | ||
| this.address = PathAddress.pathAddress(PathElement.pathElement("subsystem", "elytron"), PathElement.pathElement("jdbc-realm", name)); | ||
| this.principalQueries = principalQueries; | ||
| } | ||
|
|
||
| @Override | ||
| public String getName() { | ||
| return name; | ||
| } | ||
|
|
||
| public ModelNode getAddOperation() { | ||
| ModelNode addOperation = Util.createAddOperation(address); | ||
| addOperation.get("principal-query").set(principalQueries); | ||
|
|
||
| return addOperation; | ||
| } | ||
|
|
||
| public ModelNode getRemoveOperation() { | ||
| return Util.createRemoveOperation(address); | ||
| } | ||
|
|
||
| @Override | ||
| public void create(ModelControllerClient client, CLIWrapper cli) throws Exception { | ||
| Utils.applyUpdate(getAddOperation(), client); | ||
| } | ||
|
|
||
| @Override | ||
| public void remove(ModelControllerClient client, CLIWrapper cli) throws Exception { | ||
| Utils.applyUpdate(getRemoveOperation(), client); | ||
| } | ||
|
|
||
| public static Builder builder(final String name) { | ||
| return new Builder(name); | ||
| } | ||
|
|
||
| public static class PrincipalQueryBuilder { | ||
|
|
||
| private final Builder builder; | ||
| private final String datasource; | ||
| private final String sql; | ||
|
|
||
| private Map<String, ModelNode> passwordMappers = new LinkedHashMap<>(); | ||
| private List<ModelNode> attributeMappers = new ArrayList<>(); | ||
|
|
||
| PrincipalQueryBuilder(final Builder builder, final String datasource, final String sql) { | ||
| this.builder = builder; | ||
| this.datasource = datasource; | ||
| this.sql = sql; | ||
| } | ||
|
|
||
| public PrincipalQueryBuilder withPasswordMapper(final String passwordType, final String algorithm, final int passwordIndex, final int saltIndex, final int iteractionCountIndex) { | ||
| ModelNode passwordMapper = new ModelNode(); | ||
| if (algorithm != null) { | ||
| passwordMapper.get("algorithm").set(algorithm); | ||
| } | ||
| passwordMapper.get("password-index").set(passwordIndex); | ||
| if (saltIndex > 0) { | ||
| passwordMapper.get("salt-index").set(saltIndex); | ||
| } | ||
| if (iteractionCountIndex > 0) { | ||
| passwordMapper.get("iteration-count-index").set(iteractionCountIndex); | ||
| } | ||
| passwordMappers.put(passwordType, passwordMapper); | ||
|
|
||
| return this; | ||
| } | ||
|
|
||
| public PrincipalQueryBuilder withAttributeMapper(final String attributeName, final int attributeIndex) { | ||
| ModelNode attributeMapper = new ModelNode(); | ||
| attributeMapper.get("index").set(attributeIndex); | ||
| attributeMapper.get("to").set(attributeName); | ||
| attributeMappers.add(attributeMapper); | ||
|
|
||
| return this; | ||
| } | ||
|
|
||
|
|
||
| public Builder build() { | ||
| ModelNode principalQuery = new ModelNode(); | ||
| principalQuery.get("data-source").set(datasource); | ||
| principalQuery.get("sql").set(sql); | ||
| for (Entry<String, ModelNode> mapper : passwordMappers.entrySet()) { | ||
| principalQuery.get(mapper.getKey()).set(mapper.getValue()); | ||
| } | ||
| if (attributeMappers.size() > 0) { | ||
| principalQuery.get("attribute-mapping").set(attributeMappers); | ||
| } | ||
|
|
||
| return builder.addPrincipalQuery(principalQuery); | ||
| } | ||
|
|
||
| } | ||
|
|
||
| public static class Builder { | ||
|
|
||
| private final String name; | ||
| private List<ModelNode> queries = new ArrayList<>(); | ||
|
|
||
| Builder(final String name) { | ||
| this.name = name; | ||
| } | ||
|
|
||
| public PrincipalQueryBuilder withPrincipalQuery(final String datasource, final String sql) { | ||
| return new PrincipalQueryBuilder(this, datasource, sql); | ||
| } | ||
|
|
||
| Builder addPrincipalQuery(final ModelNode principalQuery) { | ||
| queries.add(principalQuery); | ||
|
|
||
| return this; | ||
| } | ||
|
|
||
| public SecurityRealm build() { | ||
| return new JdbcSecurityRealm(name, queries); | ||
| } | ||
|
|
||
| } | ||
|
|
||
|
|
||
|
|
||
|
|
||
| } |
| @@ -0,0 +1,117 @@ | ||
| /* | ||
| * Copyright 2019 Red Hat, Inc. | ||
| * | ||
| * Licensed 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.wildfly.test.security.common.elytron; | ||
|
|
||
| import java.util.HashMap; | ||
| import java.util.Map; | ||
| import java.util.Map.Entry; | ||
|
|
||
| import org.jboss.as.controller.PathAddress; | ||
| import org.jboss.as.controller.PathElement; | ||
| import org.jboss.as.controller.client.ModelControllerClient; | ||
| import org.jboss.as.controller.operations.common.Util; | ||
| import org.jboss.as.test.integration.management.util.CLIWrapper; | ||
| import org.jboss.as.test.integration.security.common.Utils; | ||
| import org.jboss.dmr.ModelNode; | ||
|
|
||
| /** | ||
| * A {@link ConfigurableElement} to create a mapped regex realm mapper resource. | ||
| * | ||
| * @author <a href="mailto:darran.lofthouse@jboss.com">Darran Lofthouse</a> | ||
| */ | ||
| public class MappedRegexRealmMapper implements ConfigurableElement { | ||
|
|
||
| private final PathAddress address; | ||
| private final String name; | ||
| private final String pattern; | ||
| private final String delegateRealmMapper; | ||
| private final Map<String, String> realmMapping; | ||
|
|
||
| MappedRegexRealmMapper(final String name, final String pattern, final String delegateRealmMapper, final Map<String, String> realmMapping) { | ||
| this.name = name; | ||
| this.address = PathAddress.pathAddress(PathElement.pathElement("subsystem", "elytron"), PathElement.pathElement("mapped-regex-realm-mapper", name)); | ||
| this.pattern = pattern; | ||
| this.delegateRealmMapper = delegateRealmMapper; | ||
| this.realmMapping = realmMapping; | ||
| } | ||
|
|
||
| @Override | ||
| public String getName() { | ||
| return name; | ||
| } | ||
|
|
||
| @Override | ||
| public void create(ModelControllerClient client, CLIWrapper cli) throws Exception { | ||
| ModelNode addOperation = Util.createAddOperation(address); | ||
| addOperation.get("pattern").set(pattern); | ||
| if (delegateRealmMapper != null) { | ||
| addOperation.get("delegate-realm-mapper").set(delegateRealmMapper); | ||
| } | ||
| if (realmMapping.size() > 0) { | ||
| ModelNode realmMapping = new ModelNode(); | ||
| for (Entry<String, String> entry : this.realmMapping.entrySet()) { | ||
| realmMapping.get(entry.getKey()).set(entry.getValue()); | ||
| } | ||
| addOperation.get("realm-map").set(realmMapping); | ||
| } | ||
| Utils.applyUpdate(addOperation, client); | ||
| } | ||
|
|
||
| @Override | ||
| public void remove(ModelControllerClient client, CLIWrapper cli) throws Exception { | ||
| ModelNode removeOperation = Util.createRemoveOperation(address); | ||
| Utils.applyUpdate(removeOperation, client); | ||
| } | ||
|
|
||
| public static Builder builder(final String name) { | ||
| return new Builder(name); | ||
| } | ||
|
|
||
| public static class Builder { | ||
|
|
||
| private final String name; | ||
| private String pattern; | ||
| private String delegateRealmMapper; | ||
| private Map<String, String> realmMapping = new HashMap<>(); | ||
|
|
||
| Builder(final String name) { | ||
| this.name = name; | ||
| } | ||
|
|
||
| public Builder withPattern(final String pattern) { | ||
| this.pattern = pattern; | ||
|
|
||
| return this; | ||
| } | ||
|
|
||
| public Builder withDelegateRealmMapper(final String delegateRealmMapper) { | ||
| this.delegateRealmMapper = delegateRealmMapper; | ||
|
|
||
| return this; | ||
| } | ||
|
|
||
| public Builder withRealmMapping(final String from, final String to) { | ||
| realmMapping.put(from, to); | ||
|
|
||
| return this; | ||
| } | ||
|
|
||
| public MappedRegexRealmMapper build() { | ||
| return new MappedRegexRealmMapper(name, pattern, delegateRealmMapper, realmMapping); | ||
| } | ||
| } | ||
| } |
| @@ -0,0 +1,108 @@ | ||
| /* | ||
| * Copyright 2019 Red Hat, Inc. | ||
| * | ||
| * Licensed 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.wildfly.test.security.common.elytron; | ||
|
|
||
| import org.jboss.as.controller.PathAddress; | ||
| import org.jboss.as.controller.PathElement; | ||
| import org.jboss.as.controller.client.ModelControllerClient; | ||
| import org.jboss.as.controller.operations.common.Util; | ||
| import org.jboss.as.test.integration.management.util.CLIWrapper; | ||
| import org.jboss.as.test.integration.security.common.Utils; | ||
| import org.jboss.dmr.ModelNode; | ||
|
|
||
| /** | ||
| * A {@link ConfigurableElement} to define a regex principal transformer. | ||
| * | ||
| * @author <a href="mailto:darran.lofthouse@jboss.com">Darran Lofthouse</a> | ||
| */ | ||
| public class RegexPrincipalTransformer implements ConfigurableElement { | ||
|
|
||
| private final PathAddress address; | ||
| private final String name; | ||
| private final String pattern; | ||
| private final String replacement; | ||
| private final boolean replaceAll; | ||
|
|
||
|
|
||
| RegexPrincipalTransformer(String name, String pattern, String replacement, boolean replaceAll) { | ||
| this.name = name; | ||
| this.address = PathAddress.pathAddress(PathElement.pathElement("subsystem", "elytron"), PathElement.pathElement("regex-principal-transformer", name)); | ||
| this.pattern = pattern; | ||
| this.replacement = replacement; | ||
| this.replaceAll = replaceAll; | ||
| } | ||
|
|
||
| @Override | ||
| public String getName() { | ||
| return name; | ||
| } | ||
|
|
||
| @Override | ||
| public void create(ModelControllerClient client, CLIWrapper cli) throws Exception { | ||
| ModelNode addOperation = Util.createAddOperation(address); | ||
| addOperation.get("pattern").set(pattern); | ||
| addOperation.get("replacement").set(replacement); | ||
| addOperation.get("replace-all").set(replaceAll); | ||
| Utils.applyUpdate(addOperation, client); | ||
| } | ||
|
|
||
| @Override | ||
| public void remove(ModelControllerClient client, CLIWrapper cli) throws Exception { | ||
| ModelNode removeOperation = Util.createRemoveOperation(address); | ||
| Utils.applyUpdate(removeOperation, client); | ||
| } | ||
|
|
||
| public static Builder builder(final String name) { | ||
| return new Builder(name); | ||
| } | ||
|
|
||
| public static class Builder { | ||
|
|
||
| private final String name; | ||
| private String pattern; | ||
| private String replacement; | ||
| private boolean replaceAll; | ||
|
|
||
| Builder(final String name) { | ||
| this.name = name; | ||
| } | ||
|
|
||
| public Builder withPattern(final String pattern) { | ||
| this.pattern = pattern; | ||
|
|
||
| return this; | ||
| } | ||
|
|
||
| public Builder withReplacement(final String replacement) { | ||
| this.replacement = replacement; | ||
|
|
||
| return this; | ||
| } | ||
|
|
||
| public Builder replaceAll(final boolean replaceAll) { | ||
| this.replaceAll = replaceAll; | ||
|
|
||
| return this; | ||
| } | ||
|
|
||
| public RegexPrincipalTransformer build() { | ||
| return new RegexPrincipalTransformer(name, pattern, replacement, replaceAll); | ||
| } | ||
|
|
||
| } | ||
|
|
||
| } |