diff --git a/feature-pack/src/main/resources/feature_groups/elytron-with-tls.xml b/feature-pack/src/main/resources/feature_groups/elytron-with-tls.xml
deleted file mode 100644
index dfc7e07..0000000
--- a/feature-pack/src/main/resources/feature_groups/elytron-with-tls.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/feature-pack/src/main/resources/modules/system/layers/base/org/wildfly/extension/elytron-tls/main/module.xml b/feature-pack/src/main/resources/modules/system/layers/base/org/wildfly/extension/elytron-tls/main/module.xml
index 5115aed..2751183 100644
--- a/feature-pack/src/main/resources/modules/system/layers/base/org/wildfly/extension/elytron-tls/main/module.xml
+++ b/feature-pack/src/main/resources/modules/system/layers/base/org/wildfly/extension/elytron-tls/main/module.xml
@@ -38,6 +38,7 @@
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 2cac87a..d66403f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -46,6 +46,8 @@
+ 4.1.71.Final
+ 2.3
1.1.6
1.69
1.1.6
@@ -325,6 +327,68 @@
+
+
+ io.netty
+ netty-buffer
+ ${version.io.netty}
+ test
+
+
+ io.netty
+ netty-codec
+ ${version.io.netty}
+ test
+
+
+ io.netty
+ netty-codec-http
+ ${version.io.netty}
+ test
+
+
+ io.netty
+ netty-codec-socks
+ ${version.io.netty}
+ test
+
+
+ io.netty
+ netty-common
+ ${version.io.netty}
+ test
+
+
+ io.netty
+ netty-handler
+ ${version.io.netty}
+ test
+
+
+ io.netty
+ netty-handler-proxy
+ ${version.io.netty}
+ test
+
+
+ io.netty
+ netty-transport
+ ${version.io.netty}
+ test
+
+
+
+ org.apache.velocity
+ velocity-engine-core
+ ${version.org.apache.velocity}
+ test
+
+
+ org.apache.velocity
+ velocity-engine-scripting
+ ${version.org.apache.velocity}
+ test
+
org.bouncycastle
bcpkix-jdk15on
@@ -353,6 +417,36 @@
mockserver-netty
${version.org.mockserver}
test
+
+
+ com.google.code.findbugs
+ jsr305
+
+
+ org.apache.commons
+ commons-lang3
+
+
+ com.google.guava
+ guava
+
+
+ org.bouncycastle
+ bcmail-jdk15on
+
+
+ org.bouncycastle
+ bcprov-jdk15on
+
+
+ org.bouncycastle
+ bcpkix-jdk15on
+
+
+ org.bouncycastle
+ bcutil-jdk15on
+
+
org.wildfly.core
diff --git a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/Capabilities.java b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/Capabilities.java
index 8ff9bbf..fd27f48 100644
--- a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/Capabilities.java
+++ b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/Capabilities.java
@@ -57,12 +57,22 @@
*/
class Capabilities {
+ // This has to be at this position, and must not be a lambda, to avoid an init circularity problem on IBM
+ @SuppressWarnings("Convert2Lambda")
+ static final Consumer COMMON_REQUIREMENTS = new Consumer() {
+ // unchecked because ServiceBuilder is a raw type
+ @SuppressWarnings("unchecked")
+ public void accept(final ServiceBuilder serviceBuilder) {
+ ElytronTlsSubsystemDefinition.commonRequirements(serviceBuilder);
+ }
+ };
+
private static final String WILDFLY_SECURITY_CAPABILITY_BASE = "org.wildfly.security.";
static final String ELYTRON_TLS_SUBSYSTEM_CAPABILITY_NAME = "org.wildfly.extras.elytron-tls";
- static final RuntimeCapability ELYTRON_TLS_RUNTIME_CAPABILITY = RuntimeCapability.Builder
- .of(ELYTRON_TLS_SUBSYSTEM_CAPABILITY_NAME)
+ static final RuntimeCapability> ELYTRON_TLS_RUNTIME_CAPABILITY = RuntimeCapability.Builder
+ .of(ELYTRON_TLS_SUBSYSTEM_CAPABILITY_NAME, COMMON_REQUIREMENTS)
.addRequirements(ElytronTlsExtension.WELD_CAPABILITY_NAME)
.build();
@@ -104,24 +114,6 @@ class Capabilities {
static final String DIR_CONTEXT_CAPABILITY = WILDFLY_SECURITY_CAPABILITY_BASE + "dir-context";
- // This has to be at this position, and must not be a lambda, to avoid an init circularity problem on IBM
- @SuppressWarnings("Convert2Lambda")
- static final Consumer COMMON_DEPENDENCIES = new Consumer() {
- // unchecked because ServiceBuilder is a raw type
- @SuppressWarnings("unchecked")
- public void accept(final ServiceBuilder serviceBuilder) {
- //ElytronDefinition.commonDependencies(serviceBuilder);
- //TODO:
- }
- };
-
- static final String ELYTRON_CAPABILITY = WILDFLY_SECURITY_CAPABILITY_BASE + "elytron";
-
-
- static final RuntimeCapability> ELYTRON_RUNTIME_CAPABILITY = RuntimeCapability
- .Builder.of(ELYTRON_CAPABILITY, COMMON_DEPENDENCIES)
- .build();
-
static final String EVIDENCE_DECODER_CAPABILITY = WILDFLY_SECURITY_CAPABILITY_BASE + "evidence-decoder";
static final RuntimeCapability EVIDENCE_DECODER_RUNTIME_CAPABILITY = RuntimeCapability
diff --git a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/SSLContextDefinitions.java b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/SSLContextDefinitions.java
index 0148492..1311bae 100644
--- a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/SSLContextDefinitions.java
+++ b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/SSLContextDefinitions.java
@@ -69,7 +69,6 @@
import org.jboss.as.controller.AbstractAddStepHandler;
import org.jboss.as.controller.AttributeDefinition;
-import org.jboss.as.controller.MapAttributeDefinition;
import org.jboss.as.controller.ModelVersion;
import org.jboss.as.controller.ObjectListAttributeDefinition;
import org.jboss.as.controller.ObjectTypeAttributeDefinition;
@@ -80,7 +79,6 @@
import org.jboss.as.controller.ResourceDefinition;
import org.jboss.as.controller.SimpleAttributeDefinition;
import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
-import org.jboss.as.controller.SimpleMapAttributeDefinition;
import org.jboss.as.controller.SimpleOperationDefinitionBuilder;
import org.jboss.as.controller.StringListAttributeDefinition;
import org.jboss.as.controller.capability.RuntimeCapability;
@@ -445,7 +443,8 @@ public class SSLContextDefinitions {
/* SSL Context definitions */
- static final SimpleAttributeDefinition DEFAULT_SSL_CONTEXT = new SimpleAttributeDefinitionBuilder(Constants.DEFAULT_SSL_CONTEXT, ModelType.STRING)
+ // TODO implement SNI
+ /* static final SimpleAttributeDefinition DEFAULT_SSL_CONTEXT = new SimpleAttributeDefinitionBuilder(Constants.DEFAULT_SSL_CONTEXT, ModelType.STRING)
.setRequired(true)
.setCapabilityReference(SSL_CONTEXT_CAPABILITY)
.setRestartAllServices()
@@ -457,7 +456,7 @@ public class SSLContextDefinitions {
.setMapValidator(new Validators.HostContextMapValidator())
.setAllowExpression(false)
.setRestartAllServices()
- .build();
+ .build(); */
/* Runtime Attributes */
@@ -1011,9 +1010,9 @@ protected ValueSupplier getValueSupplier(ServiceBuilder
final String cipherSuiteFilter = CIPHER_SUITE_FILTER.resolveModelAttribute(context, model).asString();
final String cipherSuiteNames = CIPHER_SUITE_NAMES.resolveModelAttribute(context, model).asStringOrNull();
- final InjectedValue providersInjector = addSSLContextDependency(PROVIDERS_CAPABILITY, providersDefinition, Provider[].class, serviceBuilder, context, model);
- final InjectedValue keyManagerInjector = addSSLContextDependency(KEY_MANAGER_CAPABILITY, KEY_MANAGER, KeyManager.class, serviceBuilder, context, model);
- final InjectedValue trustManagerInjector = addSSLContextDependency(TRUST_MANAGER_CAPABILITY, TRUST_MANAGER, TrustManager.class, serviceBuilder, context, model);;
+ final InjectedValue providersInjector = addDependency(PROVIDERS_CAPABILITY, providersDefinition, Provider[].class, serviceBuilder, context, model);
+ final InjectedValue keyManagerInjector = addDependency(KEY_MANAGER_CAPABILITY, KEY_MANAGER, KeyManager.class, serviceBuilder, context, model);
+ final InjectedValue trustManagerInjector = addDependency(TRUST_MANAGER_CAPABILITY, TRUST_MANAGER, TrustManager.class, serviceBuilder, context, model);
// final ModelNode keyManagerObject = KEY_MANAGER_OBJECT.resolveModelAttribute(context, model);
// final ModelNode trustManagerObject = TRUST_MANAGER_OBJECT.resolveModelAttribute(context, model);
@@ -1136,9 +1135,9 @@ protected ValueSupplier getValueSupplier(ServiceBuilder
final int sessionTimeout = SESSION_TIMEOUT.resolveModelAttribute(context, model).asInt();
final boolean wrap = WRAP.resolveModelAttribute(context, model).asBoolean();
- final InjectedValue providersInjector = addSSLContextDependency(PROVIDERS_CAPABILITY, providersDefinition, Provider[].class, serviceBuilder, context, model);
- InjectedValue keyManagerInjector = addSSLContextDependency(KEY_MANAGER_CAPABILITY, KEY_MANAGER, KeyManager.class, serviceBuilder, context, model);
- InjectedValue trustManagerInjector = addSSLContextDependency(TRUST_MANAGER_CAPABILITY, TRUST_MANAGER, TrustManager.class, serviceBuilder, context, model);;
+ final InjectedValue providersInjector = addDependency(PROVIDERS_CAPABILITY, providersDefinition, Provider[].class, serviceBuilder, context, model);
+ InjectedValue keyManagerInjector = addDependency(KEY_MANAGER_CAPABILITY, KEY_MANAGER, KeyManager.class, serviceBuilder, context, model);
+ InjectedValue trustManagerInjector = addDependency(TRUST_MANAGER_CAPABILITY, TRUST_MANAGER, TrustManager.class, serviceBuilder, context, model);;
// final ModelNode keyManagerObject = KEY_MANAGER_OBJECT.resolveModelAttribute(context, model);
// final ModelNode trustManagerObject = TRUST_MANAGER_OBJECT.resolveModelAttribute(context, model);
@@ -1812,7 +1811,7 @@ private static X509ExtendedTrustManager getX509TrustManager(TrustManager trustMa
if (trustManager == null) {
return null;
}
- if (trustManager instanceof X509ExtendedKeyManager) {
+ if (trustManager instanceof X509ExtendedTrustManager) {
X509ExtendedTrustManager x509TrustManager = (X509ExtendedTrustManager) trustManager;
// TODO: add FIPS
/* if (x509TrustManager instanceof DelegatingTrustManager && IS_FIPS.getAsBoolean()) {
@@ -1926,7 +1925,7 @@ private static ExceptionSupplier createKeyStore(ServiceBuil
ModelNode model, InjectedValue providersInjector) throws OperationFailedException { return null; }
// Derives dynamic name from provided attribute
- private static InjectedValue addSSLContextDependency(String baseName, SimpleAttributeDefinition attribute,
+ private static InjectedValue addDependency(String baseName, SimpleAttributeDefinition attribute,
Class type, ServiceBuilder serviceBuilder, OperationContext context, ModelNode model) throws OperationFailedException {
String dynamicNameElement = attribute.resolveModelAttribute(context, model).asStringOrNull();
InjectedValue injectedValue = new InjectedValue<>();
@@ -1938,32 +1937,6 @@ private static InjectedValue addSSLContextDependency(String baseName, Sim
return injectedValue;
}
- private static InjectedValue addKeyManagerDependency(String baseName, SimpleAttributeDefinition attribute,
- Class type, ServiceBuilder serviceBuilder, OperationContext context, ModelNode model) throws OperationFailedException {
- String dynamicNameElement = attribute.resolveModelAttribute(context, model).asStringOrNull();
- InjectedValue injectedValue = new InjectedValue<>();
-
- if (dynamicNameElement != null) {
- serviceBuilder.addDependency(context.getCapabilityServiceName(
- buildDynamicCapabilityName(baseName, dynamicNameElement), type),
- type, injectedValue);
- }
- return injectedValue;
- }
-
- private static InjectedValue addTrustManagerDependency(String baseName, SimpleAttributeDefinition attribute,
- Class type, ServiceBuilder serviceBuilder, OperationContext context, ModelNode model) throws OperationFailedException {
- String dynamicNameElement = attribute.resolveModelAttribute(context, model).asStringOrNull();
- InjectedValue injectedValue = new InjectedValue<>();
-
- if (dynamicNameElement != null) {
- serviceBuilder.addDependency(context.getCapabilityServiceName(
- buildDynamicCapabilityName(baseName, dynamicNameElement), type),
- type, injectedValue);
- }
- return injectedValue;
- }
-
private static Provider[] filterProviders(Provider[] all, String provider) {
if (provider == null || all == null) return all;
List list = new ArrayList<>();
diff --git a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/TrivialService.java b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/TrivialService.java
index 43a4f68..80de780 100644
--- a/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/TrivialService.java
+++ b/subsystem/src/main/java/org/wildfly/extension/elytron/tls/subsystem/TrivialService.java
@@ -32,7 +32,7 @@
*
* @author Darran Lofthouse
*/
-class TrivialService implements Service, org.jboss.msc.Service {
+class TrivialService implements Service {
private volatile ValueSupplier valueSupplier;
private final Consumer valueConsumer;
diff --git a/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/CertificateAuthoritiesTestCase.java b/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/CertificateAuthoritiesTestCase.java
index a5059af..e92c321 100644
--- a/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/CertificateAuthoritiesTestCase.java
+++ b/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/CertificateAuthoritiesTestCase.java
@@ -131,7 +131,7 @@ public void init() throws Exception {
} else {
subsystemXml = JdkUtils.getJavaSpecVersion() <= 12 ? "tls-sun.xml" : "tls-oracle13plus.xml";
}
- services = super.createKernelServicesBuilder(TestEnvironment.asNormal()).setSubsystemXmlResource(subsystemXml).build();
+ services = super.createKernelServicesBuilder(new TestEnvironment()).setSubsystemXmlResource(subsystemXml).build();
if (!services.isSuccessfulBoot()) {
Assert.fail(services.getBootError().toString());
}
diff --git a/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/CredentialStoreTestCase.java b/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/CredentialStoreTestCase.java
new file mode 100644
index 0000000..20bca63
--- /dev/null
+++ b/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/CredentialStoreTestCase.java
@@ -0,0 +1,527 @@
+/*
+ * 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.extension.elytron.tls.subsystem;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.FAILED;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OUTCOME;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUCCESS;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.wildfly.security.encryption.SecretKeyUtil.importSecretKey;
+
+import java.security.AccessController;
+import java.security.GeneralSecurityException;
+import java.security.PrivilegedAction;
+import java.security.Provider;
+import java.security.Security;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.crypto.SecretKey;
+
+import org.jboss.as.controller.client.helpers.ClientConstants;
+import org.jboss.as.subsystem.test.AbstractSubsystemTest;
+import org.jboss.as.subsystem.test.KernelServices;
+import org.jboss.dmr.ModelNode;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.wildfly.security.WildFlyElytronProvider;
+import org.wildfly.security.credential.SecretKeyCredential;
+import org.wildfly.security.encryption.CipherUtil;
+
+/**
+ * Test case testing operations against a credential store using the management operations.
+ *
+ * @author Darran Lofthouse
+ */
+public class CredentialStoreTestCase extends AbstractSubsystemTest {
+
+ private static final Provider PROVIDER = new WildFlyElytronProvider();
+
+ private static final String CLEAR_TEXT = "Lorem ipsum dolor sit amet";
+ private static final String CONFIGURATION = "credential-store.xml";
+
+ private KernelServices services = null;
+
+ public CredentialStoreTestCase() {
+ super(ElytronTlsExtension.SUBSYSTEM_NAME, new ElytronTlsExtension());
+ }
+
+ @Before
+ public void init() throws Exception {
+ services = super.createKernelServicesBuilder(new TestEnvironment()).setSubsystemXmlResource(CONFIGURATION).build();
+ if (!services.isSuccessfulBoot()) {
+ Assert.fail(services.getBootError().toString());
+ }
+
+ }
+
+ @BeforeClass
+ public static void initTests() throws Exception {
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Integer run() {
+ return Security.insertProviderAt(PROVIDER, 1);
+ }
+ });
+ }
+
+ @AfterClass
+ public static void cleanUpTests() {
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Void run() {
+ Security.removeProvider(PROVIDER.getName());
+
+ return null;
+ }
+ });
+ }
+
+ // Test Contents of dynamically initialised credential stores
+
+ @Test
+ public void testDefaultContentTest() throws GeneralSecurityException {
+ testDefaultContent("credential-store", "test", null, -1);
+ }
+
+ @Test
+ public void testDefaultContentTestEmpty() throws GeneralSecurityException {
+ testDefaultContent("secret-key-credential-store", "testEmpty", null, -1);
+ }
+
+ @Test
+ public void testDefaultContentTest128() throws GeneralSecurityException {
+ testDefaultContent("secret-key-credential-store", "test128", "key", 128);
+ }
+
+ @Test
+ public void testDefaultContentTest192() throws GeneralSecurityException {
+ testDefaultContent("secret-key-credential-store", "test192", "192", 192);
+ }
+
+ @Test
+ public void testDefaultContentTest256() throws GeneralSecurityException {
+ testDefaultContent("secret-key-credential-store", "test256", "key", 256);
+ }
+
+ private void testDefaultContent(final String storeType, final String storeName, String expectedAlias, int expectedKeySize) throws GeneralSecurityException {
+ // First Check The Default Aliases
+ ModelNode readAliases = new ModelNode();
+ readAliases.get(ClientConstants.OP_ADDR).add("subsystem", "elytron-tls").add(storeType, storeName);
+ readAliases.get(ClientConstants.OP).set("read-aliases");
+
+ ModelNode aliases = assertSuccess(services.executeOperation(readAliases)).get("result");
+ System.out.println(aliases.toString());
+ List aliasValues = aliases.asList();
+ assertEquals("Expected alias count", expectedAlias != null ? 1 : 0, aliasValues.size());
+ if (expectedAlias != null) {
+ assertEquals("Expected alias name", expectedAlias, aliasValues.get(0).asString());
+
+ // Export the generated SecretKey
+ ModelNode export = new ModelNode();
+ export.get(ClientConstants.OP_ADDR).add("subsystem", "elytron-tls").add(storeType, storeName);
+ export.get(ClientConstants.OP).set("export-secret-key");
+ export.get(Constants.ALIAS).set(expectedAlias);
+ ModelNode exportResult = assertSuccess(services.executeOperation(export));
+
+ final String key = exportResult.get(ClientConstants.RESULT).get(Constants.KEY).asString();
+ SecretKey secretKey = importSecretKey(key);
+ // Key Sizes are in bits.
+ assertEquals("Expected Key Size", expectedKeySize, secretKey.getEncoded().length * 8);
+ }
+ }
+
+ // Add SecretKey Flow for secret-key-credential-store but take into account the resource also has a default key size.
+
+ @Test
+ public void testSecretKeyFlowDefault() throws GeneralSecurityException {
+ testSecretKeyGenerateExportImport("credential-store", "test", 256, true, true);
+ testSecretKeyGenerateExportImport("secret-key-credential-store", "test128", 128, true, false);
+ testSecretKeyGenerateExportImport("secret-key-credential-store", "test192", 192, true, false);
+ testSecretKeyGenerateExportImport("secret-key-credential-store", "test256", 256, true, false);
+ }
+
+ @Test
+ public void testSecretKeyFlow128() throws GeneralSecurityException {
+ testSecretKeyGenerateExportImport("credential-store", "test", 128, false, true);
+ // Use a store which does not default to 128 bits.
+ testSecretKeyGenerateExportImport("secret-key-credential-store", "test256", 128, false, false);
+ }
+
+ @Test
+ public void testSecretKeyFlow192() throws GeneralSecurityException {
+ testSecretKeyGenerateExportImport("credential-store", "test", 192, false, true);
+ // Use a store which does not default to 192 bits.
+ testSecretKeyGenerateExportImport("secret-key-credential-store", "test256", 192, false, false);
+ }
+
+ @Test
+ public void testSecretKeyFlow256() throws GeneralSecurityException {
+ testSecretKeyGenerateExportImport("credential-store", "test", 256, false, true);
+ // Use a store which does not default to 256 bits.
+ testSecretKeyGenerateExportImport("secret-key-credential-store", "test128", 256, false, false);
+ }
+
+ private void testSecretKeyGenerateExportImport(final String storeType, final String storeName, final int keySize,
+ boolean omitKeySize, boolean entryTypeRequired) throws GeneralSecurityException {
+ final String alias = "test";
+
+ // Generate and store a new SecretKey using the specified keySize.
+ ModelNode generate = new ModelNode();
+ generate.get(ClientConstants.OP_ADDR).add("subsystem", "elytron-tls").add(storeType, storeName);
+ generate.get(ClientConstants.OP).set("generate-secret-key");
+ generate.get(Constants.ALIAS).set(alias);
+ if (!omitKeySize) {
+ if (keySize > 0) {
+ generate.get(Constants.KEY_SIZE).set(keySize);
+ }
+ }
+ assertSuccess(services.executeOperation(generate));
+
+ // Export the generated SecretKey
+ ModelNode export = new ModelNode();
+ export.get(ClientConstants.OP_ADDR).add("subsystem", "elytron-tls").add(storeType, storeName);
+ export.get(ClientConstants.OP).set("export-secret-key");
+ export.get(Constants.ALIAS).set(alias);
+ ModelNode exportResult = assertSuccess(services.executeOperation(export));
+
+ final String key = exportResult.get(ClientConstants.RESULT).get(Constants.KEY).asString();
+
+ SecretKey secretKey = importSecretKey(key);
+ // Key Sizes are in bits.
+ assertEquals("Expected Key Size", keySize, secretKey.getEncoded().length * 8);
+
+
+ String importAlias = alias + "Import";
+ // Import the previously exported SecretKey
+ ModelNode importKey = new ModelNode();
+ importKey.get(ClientConstants.OP_ADDR).add("subsystem", "elytron-tls").add(storeType, storeName);
+ importKey.get(ClientConstants.OP).set("import-secret-key");
+ importKey.get(Constants.ALIAS).set(importAlias);
+ importKey.get(Constants.KEY).set(key);
+ assertSuccess(services.executeOperation(importKey));
+
+ // Re-export so keys can be compared
+ ModelNode export2 = new ModelNode();
+ export2.get(ClientConstants.OP_ADDR).add("subsystem", "elytron-tls").add(storeType, storeName);
+ export2.get(ClientConstants.OP).set("export-secret-key");
+ export2.get(Constants.ALIAS).set(importAlias);
+ ModelNode exportResult2 = assertSuccess(services.executeOperation(export2));
+
+ final String key2 = exportResult2.get(ClientConstants.RESULT).get(Constants.KEY).asString();
+ assertNotNull("Exported SecretKey", key);
+ assertEquals("Matching keys", key, key2);
+
+ // Remove aliases
+ ModelNode remove = new ModelNode();
+ remove.get(ClientConstants.OP_ADDR).add("subsystem", "elytron-tls").add(storeType, storeName);
+ remove.get(ClientConstants.OP).set("remove-alias");
+ if (entryTypeRequired) {
+ remove.get(Constants.ENTRY_TYPE).set(SecretKeyCredential.class.getSimpleName());
+ }
+ remove.get(Constants.ALIAS).set(alias);
+ assertSuccess(services.executeOperation(remove));
+
+ ModelNode remove2 = new ModelNode();
+ remove2.get(ClientConstants.OP_ADDR).add("subsystem", "elytron-tls").add(storeType, storeName);
+ remove2.get(ClientConstants.OP).set("remove-alias");
+ if (entryTypeRequired) {
+ remove2.get(Constants.ENTRY_TYPE).set(SecretKeyCredential.class.getSimpleName());
+ }
+ remove2.get(Constants.ALIAS).set(importAlias);
+ assertSuccess(services.executeOperation(remove2));
+ }
+
+ @Test
+ public void testCreateExpression() throws Exception {
+ // First obtain the generated SecretKey as we will want this to test any expressions can be decrypted.
+ ModelNode export = new ModelNode();
+ export.get(ClientConstants.OP_ADDR).add("subsystem", "elytron-tls").add("secret-key-credential-store", "test256");
+ export.get(ClientConstants.OP).set("export-secret-key");
+ export.get(Constants.ALIAS).set("key");
+ ModelNode exportResult = assertSuccess(services.executeOperation(export));
+
+ final String key = exportResult.get(ClientConstants.RESULT).get(Constants.KEY).asString();
+
+ SecretKey secretKey = importSecretKey(key);
+
+ ModelNode createExpression = new ModelNode();
+ createExpression.get(ClientConstants.OP_ADDR).add("subsystem", "elytron-tls").add("expression", "encryption");
+ createExpression.get(ClientConstants.OP).set("create-expression");
+ createExpression.get(Constants.RESOLVER).set("A");
+ createExpression.get(Constants.CLEAR_TEXT).set(CLEAR_TEXT);
+ ModelNode createExpressionResult = assertSuccess(services.executeOperation(createExpression));
+
+ String expression = createExpressionResult.get(ClientConstants.RESULT).get(Constants.EXPRESSION).asString();
+ assertEquals("Expected Expression Prefix", "${CIPHER::A:", expression.substring(0, 12));
+ String cipherTextToken = expression.substring(12, expression.length() - 1);
+ assertEquals("Decrypted value", CLEAR_TEXT, CipherUtil.decrypt(cipherTextToken, secretKey));
+
+ createExpression = new ModelNode();
+ createExpression.get(ClientConstants.OP_ADDR).add("subsystem", "elytron-tls").add("expression", "encryption");
+ createExpression.get(ClientConstants.OP).set("create-expression");
+ createExpression.get(Constants.CLEAR_TEXT).set(CLEAR_TEXT);
+ createExpressionResult = assertSuccess(services.executeOperation(createExpression));
+
+ expression = createExpressionResult.get(ClientConstants.RESULT).get(Constants.EXPRESSION).asString();
+ assertEquals("Expected Expression Prefix", "${CIPHER::", expression.substring(0, 10));
+ cipherTextToken = expression.substring(10, expression.length() - 1);
+ assertEquals("Decrypted value", CLEAR_TEXT, CipherUtil.decrypt(cipherTextToken, secretKey));
+ }
+
+ @Test
+ public void testErrorsOfDoubleOperationsInFlow() throws GeneralSecurityException {
+ testErrorsOfDoubleOperationsInFlow("credential-store", "test", true);
+ testErrorsOfDoubleOperationsInFlow("secret-key-credential-store", "test128", false);
+ }
+
+ private void testErrorsOfDoubleOperationsInFlow(final String storeType, final String storeName,
+ boolean entryTypeRequired) throws GeneralSecurityException {
+
+ final String alias = "test";
+
+ // Generate and store a new SecretKey.
+ ModelNode generate = new ModelNode();
+ generate.get(ClientConstants.OP_ADDR).add("subsystem", "elytron-tls").add(storeType, storeName);
+ generate.get(ClientConstants.OP).set("generate-secret-key");
+ generate.get(Constants.ALIAS).set(alias);
+ assertSuccess(services.executeOperation(generate));
+
+ ModelNode doubleGenerateResult = assertFailed(services.executeOperation(generate));
+ assertThat(doubleGenerateResult.get(ClientConstants.FAILURE_DESCRIPTION).asString(), containsString("ELYTLS0913:"));
+
+ // Export the generated SecretKey
+ ModelNode export = new ModelNode();
+ export.get(ClientConstants.OP_ADDR).add("subsystem", "elytron-tls").add(storeType, storeName);
+ export.get(ClientConstants.OP).set("export-secret-key");
+ export.get(Constants.ALIAS).set(alias);
+ ModelNode exportResult = assertSuccess(services.executeOperation(export));
+
+ final String key = exportResult.get(ClientConstants.RESULT).get(Constants.KEY).asString();
+
+ String importAlias = alias + "Import";
+ // Import the previously exported SecretKey
+ ModelNode importKey = new ModelNode();
+ importKey.get(ClientConstants.OP_ADDR).add("subsystem", "elytron-tls").add(storeType, storeName);
+ importKey.get(ClientConstants.OP).set("import-secret-key");
+ importKey.get(Constants.ALIAS).set(importAlias);
+ importKey.get(Constants.KEY).set(key);
+ assertSuccess(services.executeOperation(importKey));
+
+ ModelNode doubleImportResult = assertFailed(services.executeOperation(importKey));
+ assertThat(doubleImportResult.get(ClientConstants.FAILURE_DESCRIPTION).asString(), containsString("ELYTLS0913:"));
+
+ // Remove aliases
+ ModelNode remove = new ModelNode();
+ remove.get(ClientConstants.OP_ADDR).add("subsystem", "elytron-tls").add(storeType, storeName);
+ remove.get(ClientConstants.OP).set("remove-alias");
+ if (entryTypeRequired) {
+ remove.get(Constants.ENTRY_TYPE).set(SecretKeyCredential.class.getSimpleName());
+ }
+ remove.get(Constants.ALIAS).set(alias);
+ assertSuccess(services.executeOperation(remove));
+
+ ModelNode remove2 = new ModelNode();
+ remove2.get(ClientConstants.OP_ADDR).add("subsystem", "elytron-tls").add(storeType, storeName);
+ remove2.get(ClientConstants.OP).set("remove-alias");
+ if (entryTypeRequired) {
+ remove2.get(Constants.ENTRY_TYPE).set(SecretKeyCredential.class.getSimpleName());
+ }
+ remove2.get(Constants.ALIAS).set(importAlias);
+ assertSuccess(services.executeOperation(remove2));
+
+ ModelNode doubleRemoveResult = assertFailed(services.executeOperation(remove2));
+ assertThat(doubleRemoveResult.get(ClientConstants.FAILURE_DESCRIPTION).asString(), containsString("ELYTLS0920:"));
+ }
+
+ @Test
+ public void testExportNonExistingAlias() throws GeneralSecurityException {
+ testExportNonExistingAlias("credential-store", "test");
+ testExportNonExistingAlias("secret-key-credential-store", "test192");
+ }
+
+ private void testExportNonExistingAlias(final String storeType, final String storeName) throws GeneralSecurityException {
+ final String alias = "test";
+
+ // Export the generated SecretKey
+ ModelNode export = new ModelNode();
+ export.get(ClientConstants.OP_ADDR).add("subsystem", "elytron-tls").add(storeType, storeName);
+ export.get(ClientConstants.OP).set("export-secret-key");
+ export.get(Constants.ALIAS).set(alias);
+ ModelNode exportResult = assertFailed(services.executeOperation(export));
+ assertThat(exportResult.get(ClientConstants.FAILURE_DESCRIPTION).asString(), containsString("ELYTLS0920:"));
+ }
+
+ @Test
+ public void testImportInvalidSecretKey() throws GeneralSecurityException {
+ testImportInvalidSecretKey("credential-store", "test");
+ testImportInvalidSecretKey("secret-key-credential-store", "test256");
+ }
+
+ private void testImportInvalidSecretKey(final String storeType, final String storeName) throws GeneralSecurityException {
+ final String alias = "test";
+
+ // Generate and store a new SecretKey.
+ ModelNode generate = new ModelNode();
+ generate.get(ClientConstants.OP_ADDR).add("subsystem", "elytron-tls").add(storeType, storeName);
+ generate.get(ClientConstants.OP).set("generate-secret-key");
+ generate.get(Constants.ALIAS).set(alias);
+ assertSuccess(services.executeOperation(generate));
+
+ // Export the generated SecretKey
+ ModelNode export = new ModelNode();
+ export.get(ClientConstants.OP_ADDR).add("subsystem", "elytron-tls").add(storeType, storeName);
+ export.get(ClientConstants.OP).set("export-secret-key");
+ export.get(Constants.ALIAS).set(alias);
+ ModelNode exportResult = assertSuccess(services.executeOperation(export));
+
+ final String key = exportResult.get(ClientConstants.RESULT).get(Constants.KEY).asString();
+ final String truncatedKey = key.substring(0, key.length() - 2);
+
+ String importAlias = alias + "Import";
+ // Import the previously exported and truncated SecretKey
+ ModelNode importKey = new ModelNode();
+ importKey.get(ClientConstants.OP_ADDR).add("subsystem", "elytron-tls").add(storeType, storeName);
+ importKey.get(ClientConstants.OP).set("import-secret-key");
+ importKey.get(Constants.ALIAS).set(importAlias);
+ importKey.get(Constants.KEY).set(truncatedKey);
+ ModelNode importResult = assertFailed(services.executeOperation(importKey));
+ assertThat(importResult.get(ClientConstants.FAILURE_DESCRIPTION).asString(), containsString("ELY19004:"));
+
+ // Remove aliases
+ ModelNode remove = new ModelNode();
+ remove.get(ClientConstants.OP_ADDR).add("subsystem", "elytron-tls").add(storeType, storeName);
+ remove.get(ClientConstants.OP).set("remove-alias");
+ remove.get(Constants.ENTRY_TYPE).set(SecretKeyCredential.class.getSimpleName());
+ remove.get(Constants.ALIAS).set(alias);
+ assertSuccess(services.executeOperation(remove));
+ }
+
+ @Test
+ public void testRemoveAliasOfEntryType() throws GeneralSecurityException {
+ final String alias = "test";
+
+ testExpectedAliases("credential-store", "test");
+
+ // Generate and store a new SecretKey.
+ ModelNode generateSecretKey = new ModelNode();
+ generateSecretKey.get(ClientConstants.OP_ADDR).add("subsystem", "elytron-tls").add("credential-store", "test");
+ generateSecretKey.get(ClientConstants.OP).set("generate-secret-key");
+ generateSecretKey.get(Constants.ALIAS).set(alias);
+ assertSuccess(services.executeOperation(generateSecretKey));
+
+ testExpectedAliases("credential-store", "test", alias);
+
+ // Store a new Password.
+ ModelNode addPassword = new ModelNode();
+ addPassword.get(ClientConstants.OP_ADDR).add("subsystem", "elytron-tls").add("credential-store", "test");
+ addPassword.get(ClientConstants.OP).set("add-alias");
+ addPassword.get(Constants.ALIAS).set(alias);
+ addPassword.get(Constants.SECRET_VALUE).set("password");
+ assertSuccess(services.executeOperation(addPassword));
+
+ testExpectedAliases("credential-store", "test", alias);
+
+ // Remove SecretKeyCredential alias
+ ModelNode removeSecretKey = new ModelNode();
+ removeSecretKey.get(ClientConstants.OP_ADDR).add("subsystem", "elytron-tls").add("credential-store", "test");
+ removeSecretKey.get(ClientConstants.OP).set("remove-alias");
+ removeSecretKey.get(Constants.ENTRY_TYPE).set(SecretKeyCredential.class.getSimpleName());
+ removeSecretKey.get(Constants.ALIAS).set(alias);
+ assertSuccess(services.executeOperation(removeSecretKey));
+
+ testExpectedAliases("credential-store", "test", alias);
+
+ // Generate and store a new SecretKey again.
+ ModelNode generateSecretKeyAgain = new ModelNode();
+ generateSecretKeyAgain.get(ClientConstants.OP_ADDR).add("subsystem", "elytron-tls").add("credential-store", "test");
+ generateSecretKeyAgain.get(ClientConstants.OP).set("generate-secret-key");
+ generateSecretKeyAgain.get(Constants.ALIAS).set(alias);
+ assertSuccess(services.executeOperation(generateSecretKeyAgain));
+
+ testExpectedAliases("credential-store", "test", alias);
+
+ // Remove PasswordCredential alias (default type)
+ ModelNode removePassword = new ModelNode();
+ removePassword.get(ClientConstants.OP_ADDR).add("subsystem", "elytron-tls").add("credential-store", "test");
+ removePassword.get(ClientConstants.OP).set("remove-alias");
+ removePassword.get(Constants.ALIAS).set(alias);
+ assertSuccess(services.executeOperation(removePassword));
+
+ testExpectedAliases("credential-store", "test", alias);
+
+ // Remove SecretKeyCredential alias again
+ ModelNode removeSecretKeyAgain = new ModelNode();
+ removeSecretKeyAgain.get(ClientConstants.OP_ADDR).add("subsystem", "elytron-tls").add("credential-store", "test");
+ removeSecretKeyAgain.get(ClientConstants.OP).set("remove-alias");
+ removeSecretKeyAgain.get(Constants.ENTRY_TYPE).set(SecretKeyCredential.class.getSimpleName());
+ removeSecretKeyAgain.get(Constants.ALIAS).set(alias);
+ assertSuccess(services.executeOperation(removeSecretKeyAgain));
+
+ testExpectedAliases("credential-store", "test");
+ }
+
+ private void testExpectedAliases(String resourceType, String resourceName,
+ String... expectedAliases) throws GeneralSecurityException {
+
+ ModelNode readAliases = new ModelNode();
+ readAliases.get(ClientConstants.OP_ADDR).add("subsystem", "elytron-tls").add(resourceType, resourceName);
+ readAliases.get(ClientConstants.OP).set(Constants.READ_ALIASES);
+
+ ModelNode readAliasesResult = assertSuccess(services.executeOperation(readAliases));
+
+ ModelNode result = readAliasesResult.get(ClientConstants.RESULT);
+ if (expectedAliases.length > 0) {
+ Set expectedSet = new HashSet<>(Arrays.asList(expectedAliases));
+
+ List aliasList = result.asList();
+ for (ModelNode aliasNode : aliasList) {
+ String alias = aliasNode.asString();
+ if (!expectedSet.remove(alias)) {
+ fail("Alias '" + alias + "' not expected.");
+ }
+ }
+
+ assertEquals("All expected aliases found", 0, expectedSet.size());
+ } else {
+ assertTrue("No aliases expected", result.asList().isEmpty());
+ }
+ }
+
+ private static ModelNode assertSuccess(ModelNode response) {
+ if (!response.get(OUTCOME).asString().equals(SUCCESS)) {
+ Assert.fail(response.toJSONString(false));
+ }
+ return response;
+ }
+
+ private static ModelNode assertFailed(ModelNode response) {
+ if (!response.get(OUTCOME).asString().equals(FAILED)) {
+ Assert.fail(response.toJSONString(false));
+ }
+ return response;
+ }
+
+}
diff --git a/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/CredentialStoreUpdatesTestCase.java b/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/CredentialStoreUpdatesTestCase.java
new file mode 100644
index 0000000..8c306bf
--- /dev/null
+++ b/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/CredentialStoreUpdatesTestCase.java
@@ -0,0 +1,782 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2019 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.extension.elytron.tls.subsystem;
+
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.FAILED;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.FAILURE_DESCRIPTION;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.NAME;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OUTCOME;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RESULT;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUCCESS;
+import static org.jboss.as.controller.security.CredentialReference.ALIAS;
+import static org.jboss.as.controller.security.CredentialReference.CLEAR_TEXT;
+import static org.jboss.as.controller.security.CredentialReference.CREDENTIAL_REFERENCE;
+import static org.jboss.as.controller.security.CredentialReference.NEW_ALIAS;
+import static org.jboss.as.controller.security.CredentialReference.STORE;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.Provider;
+import java.security.Security;
+import java.util.Arrays;
+import java.util.Objects;
+
+import org.jboss.as.controller.client.helpers.ClientConstants;
+import org.jboss.as.controller.security.CredentialReference;
+import org.jboss.as.subsystem.test.AbstractSubsystemTest;
+import org.jboss.as.subsystem.test.KernelServices;
+import org.jboss.dmr.ModelNode;
+import org.jboss.msc.service.ServiceName;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.wildfly.security.WildFlyElytronProvider;
+import org.wildfly.security.credential.PasswordCredential;
+import org.wildfly.security.credential.store.CredentialStore;
+import org.wildfly.security.credential.store.CredentialStoreException;
+import org.wildfly.security.password.interfaces.ClearPassword;
+
+/**
+ * Tests for automatic updates of credential stores.
+ *
+ * @author Farah Juma
+ */
+public class CredentialStoreUpdatesTestCase extends AbstractSubsystemTest {
+
+ private static final String EMPTY_CS_PASSWORD = "super_secret1";
+ private static final String NON_EMPTY_CS_PASSWORD = "super_secret2";
+ private static final String EMPTY_CS_NAME = "store1";
+ private static final String EMPTY_CS_PATH = "target/test.credential.store1";
+ private static final String NON_EMPTY_CS_NAME = "store2";
+ private static final String NON_EMPTY_CS_PATH = "target/test.credential.store2";
+ private static final String KS_NAME = "test-keystore";
+ private static final String CLEAR_TEXT_ATTRIBUTE_NAME = CredentialReference.CREDENTIAL_REFERENCE + "." + CLEAR_TEXT;
+ private static final String ALIAS_ATTRIBUTE_NAME = CredentialReference.CREDENTIAL_REFERENCE + "." + ALIAS;
+ private static final String STORE_ATTRIBUTE_NAME = CredentialReference.CREDENTIAL_REFERENCE + "." + STORE;
+ private static final String EXISTING_ALIAS = "existingAlias";
+ private static final String EXISTING_PASSWORD = "existingPassword";
+ private static final Provider wildFlyElytronProvider = new WildFlyElytronProvider();
+ private static CredentialStoreUtility emptyCSUtil = null;
+ private static CredentialStoreUtility nonEmptyCSUtil = null;
+ private KernelServices services = null;
+
+ public CredentialStoreUpdatesTestCase() {
+ super(ElytronTlsExtension.SUBSYSTEM_NAME, new ElytronTlsExtension());
+ }
+
+ @BeforeClass
+ public static void initTests() {
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Integer run() {
+ return Security.insertProviderAt(wildFlyElytronProvider, 1);
+ }
+ });
+ }
+
+ @Before
+ public void init() throws Exception {
+ services = super.createKernelServicesBuilder(new TestEnvironment()).setSubsystemXmlResource("credential-store-updates.xml").build();
+ if (!services.isSuccessfulBoot()) {
+ Assert.fail(services.getBootError().toString());
+ }
+ emptyCSUtil = new CredentialStoreUtility(EMPTY_CS_PATH, EMPTY_CS_PASSWORD);
+ nonEmptyCSUtil = new CredentialStoreUtility(NON_EMPTY_CS_PATH, NON_EMPTY_CS_PASSWORD);
+ }
+
+ @After
+ public void cleanUpCredentialStores() {
+ emptyCSUtil.cleanUp();
+ nonEmptyCSUtil.cleanUp();
+ }
+
+ @AfterClass
+ public static void cleanUpTests() {
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Void run() {
+ Security.removeProvider(wildFlyElytronProvider.getName());
+ return null;
+ }
+ });
+ }
+
+ @Test
+ public void testCredentialReferenceAddNewEntryToEmptyCredentialStore() throws Exception {
+ String alias = "newAlias";
+ String password = "newPassword";
+ try {
+ CredentialStore credentialStore = getCredentialStore(EMPTY_CS_NAME);
+ assertEquals(0, credentialStore.getAliases().size());
+
+ addKeyStoreWithCredentialReference(KS_NAME, EMPTY_CS_NAME, alias, password, false);
+ assertEquals(1, credentialStore.getAliases().size());
+ assertTrue(credentialStore.exists(alias, PasswordCredential.class));
+ PasswordCredential passwordCredential = credentialStore.retrieve(alias, PasswordCredential.class);
+ ClearPassword clearPassword = passwordCredential.getPassword(ClearPassword.class);
+ assertArrayEquals(password.toCharArray(), clearPassword.getPassword());
+
+ assertNull(readAttribute(KS_NAME, CLEAR_TEXT_ATTRIBUTE_NAME));
+ assertEquals(alias, readAttribute(KS_NAME, ALIAS_ATTRIBUTE_NAME));
+ } finally {
+ removeKeyStore(KS_NAME);
+ }
+ }
+
+ @Test
+ public void testCredentialReferenceAddNewEntryWithGeneratedAliasToEmptyCredentialStore() throws Exception {
+ String password = "newPassword";
+ try {
+ CredentialStore credentialStore = getCredentialStore(EMPTY_CS_NAME);
+ assertEquals(0, credentialStore.getAliases().size());
+
+ String generatedAlias = addKeyStoreWithCredentialReference(KS_NAME, EMPTY_CS_NAME,null, password, false);
+ assertEquals(1, credentialStore.getAliases().size());
+ assertTrue(credentialStore.exists(generatedAlias, PasswordCredential.class));
+ PasswordCredential passwordCredential = credentialStore.retrieve(generatedAlias, PasswordCredential.class);
+ ClearPassword clearPassword = passwordCredential.getPassword(ClearPassword.class);
+ assertArrayEquals(password.toCharArray(), clearPassword.getPassword());
+
+ assertNull(readAttribute(KS_NAME, CLEAR_TEXT_ATTRIBUTE_NAME));
+ assertEquals(generatedAlias, readAttribute(KS_NAME, ALIAS_ATTRIBUTE_NAME));
+ } finally {
+ removeKeyStore(KS_NAME);
+ }
+ }
+
+ @Test
+ public void testCredentialReferenceAddNewEntry() throws Exception {
+ String alias = "newAlias";
+ String password = "newPassword";
+ try {
+ CredentialStore credentialStore = getNonEmptyCredentialStore();
+
+ assertFalse(credentialStore.exists(alias, PasswordCredential.class));
+ assertEquals(1, credentialStore.getAliases().size());
+
+ addKeyStoreWithCredentialReference(KS_NAME, NON_EMPTY_CS_NAME, alias, password, false);
+ assertEquals(2, credentialStore.getAliases().size());
+ assertTrue(credentialStore.exists(alias, PasswordCredential.class));
+ PasswordCredential passwordCredential = credentialStore.retrieve(alias, PasswordCredential.class);
+ ClearPassword clearPassword = passwordCredential.getPassword(ClearPassword.class);
+ assertArrayEquals(password.toCharArray(), clearPassword.getPassword());
+
+ assertNull(readAttribute(KS_NAME, CLEAR_TEXT_ATTRIBUTE_NAME));
+ assertEquals(alias, readAttribute(KS_NAME, ALIAS_ATTRIBUTE_NAME));
+ } finally {
+ removeKeyStore(KS_NAME);
+ }
+ }
+
+ @Test
+ public void testCredentialReferenceAddNewEntryWithGeneratedAlias() throws Exception {
+ String password = "newPassword";
+ try {
+ CredentialStore credentialStore = getNonEmptyCredentialStore();
+
+ assertEquals(1, credentialStore.getAliases().size());
+
+ String generatedAlias = addKeyStoreWithCredentialReference(KS_NAME, NON_EMPTY_CS_NAME, null, password, false);
+ assertEquals(2, credentialStore.getAliases().size());
+ assertTrue(credentialStore.exists(generatedAlias, PasswordCredential.class));
+ PasswordCredential passwordCredential = credentialStore.retrieve(generatedAlias, PasswordCredential.class);
+ ClearPassword clearPassword = passwordCredential.getPassword(ClearPassword.class);
+ assertArrayEquals(password.toCharArray(), clearPassword.getPassword());
+
+ assertNull(readAttribute(KS_NAME, CLEAR_TEXT_ATTRIBUTE_NAME));
+ assertEquals(generatedAlias, readAttribute(KS_NAME, ALIAS_ATTRIBUTE_NAME));
+ } finally {
+ removeKeyStore(KS_NAME);
+ }
+ }
+
+ @Test
+ public void testCredentialReferenceUpdateExistingEntry() throws Exception {
+ String newPassword = "newPassword";
+ try {
+ CredentialStore credentialStore = getNonEmptyCredentialStore();
+
+ assertTrue(credentialStore.exists(EXISTING_ALIAS, PasswordCredential.class));
+ PasswordCredential passwordCredential = credentialStore.retrieve(EXISTING_ALIAS, PasswordCredential.class);
+ ClearPassword clearPassword = passwordCredential.getPassword(ClearPassword.class);
+ assertArrayEquals(EXISTING_PASSWORD.toCharArray(), clearPassword.getPassword());
+ assertEquals(1, credentialStore.getAliases().size());
+
+ addKeyStoreWithCredentialReference(KS_NAME, NON_EMPTY_CS_NAME, EXISTING_ALIAS, newPassword, true);
+ assertEquals(1, credentialStore.getAliases().size());
+ assertTrue(credentialStore.exists(EXISTING_ALIAS, PasswordCredential.class));
+ passwordCredential = credentialStore.retrieve(EXISTING_ALIAS, PasswordCredential.class);
+ clearPassword = passwordCredential.getPassword(ClearPassword.class);
+ assertArrayEquals(newPassword.toCharArray(), clearPassword.getPassword());
+
+ assertNull(readAttribute(KS_NAME, CLEAR_TEXT_ATTRIBUTE_NAME));
+ assertEquals(EXISTING_ALIAS, readAttribute(KS_NAME, ALIAS_ATTRIBUTE_NAME));
+ } finally {
+ removeKeyStore(KS_NAME);
+ }
+ }
+
+ @Test
+ public void testCredentialReferenceAddNewEntryFromOperation() throws Exception {
+ try {
+ CredentialStore credentialStore = getNonEmptyCredentialStore();
+ addKeyStoreWithCredentialReference(KS_NAME, NON_EMPTY_CS_NAME, EXISTING_ALIAS, null, true, false);
+
+ String alias = "newAlias";
+ String password = "newPassword";
+ assertFalse(credentialStore.exists(alias, PasswordCredential.class));
+ assertEquals(1, credentialStore.getAliases().size());
+
+ // specify a credential-reference when executing a key-store operation
+ generateKeyPairWithCredentialStoreUpdate(KS_NAME, NON_EMPTY_CS_NAME, alias, password, false);
+ assertEquals(2, credentialStore.getAliases().size());
+ assertTrue(credentialStore.exists(alias, PasswordCredential.class));
+ PasswordCredential passwordCredential = credentialStore.retrieve(alias, PasswordCredential.class);
+ ClearPassword clearPassword = passwordCredential.getPassword(ClearPassword.class);
+ assertArrayEquals(password.toCharArray(), clearPassword.getPassword());
+
+ assertNull(readAttribute(KS_NAME, CLEAR_TEXT_ATTRIBUTE_NAME));
+ assertEquals(EXISTING_ALIAS, readAttribute(KS_NAME, ALIAS_ATTRIBUTE_NAME));
+ } finally {
+ removeKeyStore(KS_NAME);
+ }
+ }
+
+ @Test
+ public void testCredentialReferenceAddNewEntryWithGeneratedAliasFromOperation() throws Exception {
+ try {
+ CredentialStore credentialStore = getNonEmptyCredentialStore();
+ addKeyStoreWithCredentialReference(KS_NAME, NON_EMPTY_CS_NAME, EXISTING_ALIAS, null, true, false);
+
+ String password = "newPassword";
+ assertEquals(1, credentialStore.getAliases().size());
+
+ // specify a credential-reference when executing a key-store operation
+ String generatedAlias = generateKeyPairWithCredentialStoreUpdate(KS_NAME, NON_EMPTY_CS_NAME, null, password, false);
+ assertEquals(2, credentialStore.getAliases().size());
+ assertTrue(credentialStore.exists(generatedAlias, PasswordCredential.class));
+ PasswordCredential passwordCredential = credentialStore.retrieve(generatedAlias, PasswordCredential.class);
+ ClearPassword clearPassword = passwordCredential.getPassword(ClearPassword.class);
+ assertArrayEquals(password.toCharArray(), clearPassword.getPassword());
+
+ assertNull(readAttribute(KS_NAME, CLEAR_TEXT_ATTRIBUTE_NAME));
+ assertEquals(EXISTING_ALIAS, readAttribute(KS_NAME, ALIAS_ATTRIBUTE_NAME));
+ } finally {
+ removeKeyStore(KS_NAME);
+ }
+ }
+
+ @Test
+ public void testCredentialReferenceUpdateExistingEntryFromOperation() throws Exception {
+ try {
+ addKeyStoreWithCredentialReference(KS_NAME, EMPTY_CS_NAME, "alias1", "secret", false, false);
+
+ CredentialStore credentialStore = getNonEmptyCredentialStore();
+ assertEquals(1, credentialStore.getAliases().size());
+ assertTrue(credentialStore.exists(EXISTING_ALIAS, PasswordCredential.class));
+ PasswordCredential passwordCredential = credentialStore.retrieve(EXISTING_ALIAS, PasswordCredential.class);
+ ClearPassword clearPassword = passwordCredential.getPassword(ClearPassword.class);
+ assertArrayEquals(EXISTING_PASSWORD.toCharArray(), clearPassword.getPassword());
+
+ // specify a credential-reference when executing a key-store operation
+ String password = "newPassword";
+ generateKeyPairWithCredentialStoreUpdate(KS_NAME, NON_EMPTY_CS_NAME, EXISTING_ALIAS, password, true);
+
+ assertEquals(1, credentialStore.getAliases().size());
+ assertTrue(credentialStore.exists(EXISTING_ALIAS, PasswordCredential.class));
+ passwordCredential = credentialStore.retrieve(EXISTING_ALIAS, PasswordCredential.class);
+ clearPassword = passwordCredential.getPassword(ClearPassword.class);
+ assertArrayEquals(password.toCharArray(), clearPassword.getPassword());
+
+ assertNull(readAttribute(KS_NAME, CLEAR_TEXT_ATTRIBUTE_NAME));
+ assertEquals("alias1", readAttribute(KS_NAME, ALIAS_ATTRIBUTE_NAME));
+ } finally {
+ removeKeyStore(KS_NAME);
+ }
+ }
+
+ @Test
+ public void testCredentialReferenceUpdateExistingEntryFromWriteAttributeOperation() throws Exception {
+ try {
+ CredentialStore credentialStore = getNonEmptyCredentialStore();
+
+ assertTrue(credentialStore.exists(EXISTING_ALIAS, PasswordCredential.class));
+ PasswordCredential passwordCredential = credentialStore.retrieve(EXISTING_ALIAS, PasswordCredential.class);
+ ClearPassword clearPassword = passwordCredential.getPassword(ClearPassword.class);
+ assertArrayEquals(EXISTING_PASSWORD.toCharArray(), clearPassword.getPassword());
+ assertEquals(1, credentialStore.getAliases().size());
+ addKeyStoreWithCredentialReference(KS_NAME, NON_EMPTY_CS_NAME, EXISTING_ALIAS, null, true);
+
+ String password = "newPassword";
+ writeClearTextAttribute("key-store", KS_NAME, password);
+
+ assertEquals(1, credentialStore.getAliases().size());
+ assertTrue(credentialStore.exists(EXISTING_ALIAS, PasswordCredential.class));
+ passwordCredential = credentialStore.retrieve(EXISTING_ALIAS, PasswordCredential.class);
+ clearPassword = passwordCredential.getPassword(ClearPassword.class);
+ assertArrayEquals(password.toCharArray(), clearPassword.getPassword());
+
+ assertNull(readAttribute(KS_NAME, CLEAR_TEXT_ATTRIBUTE_NAME));
+ assertEquals(EXISTING_ALIAS, readAttribute(KS_NAME, ALIAS_ATTRIBUTE_NAME));
+ } finally {
+ removeKeyStore(KS_NAME);
+ }
+ }
+
+ @Test
+ public void testCredentialReferenceNoUpdate() throws Exception {
+ try {
+ CredentialStore credentialStore = getNonEmptyCredentialStore();
+
+ assertTrue(credentialStore.exists(EXISTING_ALIAS, PasswordCredential.class));
+ PasswordCredential passwordCredential = credentialStore.retrieve(EXISTING_ALIAS, PasswordCredential.class);
+ ClearPassword clearPassword = passwordCredential.getPassword(ClearPassword.class);
+ assertArrayEquals(EXISTING_PASSWORD.toCharArray(), clearPassword.getPassword());
+ assertEquals(1, credentialStore.getAliases().size());
+
+ addKeyStoreWithCredentialReference(KS_NAME, NON_EMPTY_CS_NAME, EXISTING_ALIAS, null, true);
+ assertEquals(1, credentialStore.getAliases().size());
+ assertTrue(credentialStore.exists(EXISTING_ALIAS, PasswordCredential.class));
+ passwordCredential = credentialStore.retrieve(EXISTING_ALIAS, PasswordCredential.class);
+ clearPassword = passwordCredential.getPassword(ClearPassword.class);
+ assertArrayEquals(EXISTING_PASSWORD.toCharArray(), clearPassword.getPassword());
+
+ assertNull(readAttribute(KS_NAME, CLEAR_TEXT_ATTRIBUTE_NAME));
+ assertEquals(EXISTING_ALIAS, readAttribute(KS_NAME, ALIAS_ATTRIBUTE_NAME));
+ } finally {
+ removeKeyStore(KS_NAME);
+ }
+ }
+
+ @Test
+ public void testCredentialReferenceRollbackOfNewlyAddedCredentialDuringAddOperation() throws Exception {
+ String alias = "newAlias";
+ String password = "newPassword";
+
+ CredentialStore credentialStore = getNonEmptyCredentialStore();
+
+ assertFalse(credentialStore.exists(alias, PasswordCredential.class));
+ assertEquals(1, credentialStore.getAliases().size());
+
+
+ // Add an invalid key-store, specify a credential-reference attribute that will result in a new entry being added
+ // to the credential store. The new entry will be rolled back when the key-store add operation fails
+ addKeyStoreWithCredentialReference(KS_NAME, NON_EMPTY_CS_NAME, alias, password, "InvalidType", false, true, true);
+ assertEquals(1, credentialStore.getAliases().size());
+ assertFalse(credentialStore.exists(alias, PasswordCredential.class));
+
+ }
+
+ @Test
+ public void testCredentialReferenceRollbackOfUpdatedExistingCredentialDuringAddOperation() throws Exception {
+ String password = "newPassword";
+
+ CredentialStore credentialStore = getNonEmptyCredentialStore();
+
+ assertTrue(credentialStore.exists(EXISTING_ALIAS, PasswordCredential.class));
+ PasswordCredential passwordCredential = credentialStore.retrieve(EXISTING_ALIAS, PasswordCredential.class);
+ ClearPassword clearPassword = passwordCredential.getPassword(ClearPassword.class);
+ assertArrayEquals(EXISTING_PASSWORD.toCharArray(), clearPassword.getPassword());
+ assertEquals(1, credentialStore.getAliases().size());
+
+ // Add an invalid key-store, specify a credential-reference attribute that will result in an existing entry being updated
+ // in the credential store. The updated entry will be rolled back to its previous value when the key-store add operation fails
+ addKeyStoreWithCredentialReference(KS_NAME, NON_EMPTY_CS_NAME, EXISTING_ALIAS, password, "InvalidType", false, true, true);
+ assertEquals(1, credentialStore.getAliases().size());
+ assertTrue(credentialStore.exists(EXISTING_ALIAS, PasswordCredential.class));
+ passwordCredential = credentialStore.retrieve(EXISTING_ALIAS, PasswordCredential.class);
+ clearPassword = passwordCredential.getPassword(ClearPassword.class);
+ assertArrayEquals(EXISTING_PASSWORD.toCharArray(), clearPassword.getPassword()); // password should remain unchanged
+ }
+
+ @Test
+ public void testFailedAddOperationWithClearTextAttributeOnly() throws Exception {
+ String password = "secret";
+ addKeyStoreWithCredentialReference(KS_NAME, null, null, password, "InvalidType", false, false, true);
+ }
+
+ @Test
+ public void testCredentialReferenceRollbackOfNewlyAddedCredentialDuringRuntimeOperation() throws Exception {
+ String alias = "newAlias";
+ String password = "newPassword";
+ addKeyStore();
+ CredentialStore credentialStore = getNonEmptyCredentialStore();
+
+ assertFalse(credentialStore.exists(alias, PasswordCredential.class));
+ assertEquals(1, credentialStore.getAliases().size());
+ try {
+ ModelNode operation = new ModelNode();
+ operation.get(ClientConstants.OP_ADDR).add("subsystem", "elytron-tls").add("key-store", KS_NAME);
+ operation.get(ClientConstants.OP).set(Constants.GENERATE_KEY_PAIR);
+ operation.get(Constants.ALIAS).set("bsmith");
+ operation.get(Constants.ALGORITHM).set("Invalid");
+ operation.get(Constants.DISTINGUISHED_NAME).set("CN=bob smith, OU=jboss, O=red hat, L=raleigh, ST=north carolina, C=us");
+ operation.get(CredentialReference.CREDENTIAL_REFERENCE).get(STORE).set(NON_EMPTY_CS_NAME);
+ operation.get(CredentialReference.CREDENTIAL_REFERENCE).get(ALIAS).set(alias);
+ operation.get(CredentialReference.CREDENTIAL_REFERENCE).get(CLEAR_TEXT).set(password);
+ ModelNode response = assertFailed(services.executeOperation(operation)).get(RESULT);
+ validateFailedResponse(response);
+
+ assertEquals(1, credentialStore.getAliases().size());
+ assertFalse(credentialStore.exists(alias, PasswordCredential.class));
+ } finally {
+ removeKeyStore(KS_NAME);
+ }
+ }
+
+ @Test
+ public void testCredentialReferenceRollbackOfUpdatedExistingCredentialDuringRuntimeOperation() throws Exception {
+ String password = "newPassword";
+ addKeyStore();
+
+ CredentialStore credentialStore = getNonEmptyCredentialStore();
+
+ assertTrue(credentialStore.exists(EXISTING_ALIAS, PasswordCredential.class));
+ PasswordCredential passwordCredential = credentialStore.retrieve(EXISTING_ALIAS, PasswordCredential.class);
+ ClearPassword clearPassword = passwordCredential.getPassword(ClearPassword.class);
+ assertArrayEquals(EXISTING_PASSWORD.toCharArray(), clearPassword.getPassword());
+ assertEquals(1, credentialStore.getAliases().size());
+ try {
+ ModelNode operation = new ModelNode();
+ operation.get(ClientConstants.OP_ADDR).add("subsystem", "elytron-tls").add("key-store", KS_NAME);
+ operation.get(ClientConstants.OP).set(Constants.GENERATE_KEY_PAIR);
+ operation.get(Constants.ALIAS).set("bsmith");
+ operation.get(Constants.ALGORITHM).set("Invalid");
+ operation.get(Constants.DISTINGUISHED_NAME).set("CN=bob smith, OU=jboss, O=red hat, L=raleigh, ST=north carolina, C=us");
+ operation.get(CredentialReference.CREDENTIAL_REFERENCE).get(STORE).set(NON_EMPTY_CS_NAME);
+ operation.get(CredentialReference.CREDENTIAL_REFERENCE).get(ALIAS).set(EXISTING_ALIAS);
+ operation.get(CredentialReference.CREDENTIAL_REFERENCE).get(CLEAR_TEXT).set(password);
+ ModelNode response = assertFailed(services.executeOperation(operation)).get(RESULT);
+ validateFailedResponse(response);
+
+ assertEquals(1, credentialStore.getAliases().size());
+ assertTrue(credentialStore.exists(EXISTING_ALIAS, PasswordCredential.class));
+ passwordCredential = credentialStore.retrieve(EXISTING_ALIAS, PasswordCredential.class);
+ clearPassword = passwordCredential.getPassword(ClearPassword.class);
+ assertArrayEquals(EXISTING_PASSWORD.toCharArray(), clearPassword.getPassword()); // password should remain unchanged
+ } finally {
+ removeKeyStore(KS_NAME);
+ }
+ }
+
+ @Test
+ public void testFailedRuntimeOperationWithClearTextAttributeOnly() throws Exception {
+ addKeyStore();
+ try {
+ ModelNode operation = new ModelNode();
+ operation.get(ClientConstants.OP_ADDR).add("subsystem", "elytron-tls").add("key-store", KS_NAME);
+ operation.get(ClientConstants.OP).set(Constants.GENERATE_KEY_PAIR);
+ operation.get(Constants.ALIAS).set("bsmith");
+ operation.get(Constants.ALGORITHM).set("Invalid");
+ operation.get(Constants.DISTINGUISHED_NAME).set("CN=bob smith, OU=jboss, O=red hat, L=raleigh, ST=north carolina, C=us");
+ operation.get(CredentialReference.CREDENTIAL_REFERENCE).get(CLEAR_TEXT).set("secret");
+ assertFailed(services.executeOperation(operation)).get(RESULT);
+ } finally {
+ removeKeyStore(KS_NAME);
+ }
+ }
+
+ @Test
+ public void testAddOperationWithCredentialReferenceWithStoreOnly() throws Exception {
+ testAddKeyStoreWithInvalidCredentialReference(KS_NAME, NON_EMPTY_CS_NAME, null, null);
+ }
+
+ @Test
+ public void testAddOperationWithCredentialReferenceWithAliasOnly() throws Exception {
+ testAddKeyStoreWithInvalidCredentialReference(KS_NAME, null, EXISTING_ALIAS, null);
+ }
+
+ @Test
+ public void testAddOperationWithCredentialReferenceWithClearTextOnly() throws Exception {
+ try {
+ String password = "secret";
+ addKeyStoreWithCredentialReference(KS_NAME, null, null, password, false, false);
+ assertEquals(password, readAttribute(KS_NAME, CLEAR_TEXT_ATTRIBUTE_NAME));
+ assertNull(readAttribute(KS_NAME, ALIAS_ATTRIBUTE_NAME));
+ } finally {
+ removeKeyStore(KS_NAME);
+ }
+ }
+
+ @Test
+ public void testWriteAttributeWithCredentialReferenceWithStoreOnly() throws Exception {
+ try {
+ getNonEmptyCredentialStore();
+ addKeyStoreWithCredentialReference(KS_NAME, NON_EMPTY_CS_NAME, EXISTING_ALIAS, null, true);
+ testWriteCredentialReferenceAttribute("key-store", KS_NAME, NON_EMPTY_CS_NAME, null, null, true);
+
+ // no changes to credential-reference attribute
+ assertNull(readAttribute(KS_NAME, CLEAR_TEXT_ATTRIBUTE_NAME));
+ assertEquals(EXISTING_ALIAS, readAttribute(KS_NAME, ALIAS_ATTRIBUTE_NAME));
+ assertEquals(NON_EMPTY_CS_NAME, readAttribute(KS_NAME, STORE_ATTRIBUTE_NAME));
+ } finally {
+ removeKeyStore(KS_NAME);
+ }
+ }
+
+ @Test
+ public void testWriteAttributeWithCredentialReferenceWithAliasOnly() throws Exception {
+ try {
+ getNonEmptyCredentialStore();
+ addKeyStoreWithCredentialReference(KS_NAME, NON_EMPTY_CS_NAME, EXISTING_ALIAS, null, true);
+ testWriteCredentialReferenceAttribute("key-store", KS_NAME, null, NEW_ALIAS, null, true);
+
+ // no changes to credential-reference attribute
+ assertNull(readAttribute(KS_NAME, CLEAR_TEXT_ATTRIBUTE_NAME));
+ assertEquals(EXISTING_ALIAS, readAttribute(KS_NAME, ALIAS_ATTRIBUTE_NAME));
+ assertEquals(NON_EMPTY_CS_NAME, readAttribute(KS_NAME, STORE_ATTRIBUTE_NAME));
+ } finally {
+ removeKeyStore(KS_NAME);
+ }
+ }
+
+ @Test
+ public void testWriteAttributeWithCredentialReferenceWithClearTextOnly() throws Exception {
+ try {
+ String newPassword = "newPassword";
+ getNonEmptyCredentialStore();
+ addKeyStoreWithCredentialReference(KS_NAME, NON_EMPTY_CS_NAME, EXISTING_ALIAS, null, true);
+ testWriteCredentialReferenceAttribute("key-store", KS_NAME, null, null, newPassword, false);
+
+ // changes to credential-reference attribute
+ assertEquals(newPassword, readAttribute(KS_NAME, CLEAR_TEXT_ATTRIBUTE_NAME));
+ assertNull(readAttribute(KS_NAME, ALIAS_ATTRIBUTE_NAME));
+ assertNull(readAttribute(KS_NAME, STORE_ATTRIBUTE_NAME));
+ } finally {
+ removeKeyStore(KS_NAME);
+ }
+ }
+
+ private String addKeyStoreWithCredentialReference(String keyStoreName, String store, String alias, String secret, boolean exists) throws Exception {
+ return addKeyStoreWithCredentialReference(keyStoreName, store, alias, secret, "JKS", exists, true, false);
+ }
+
+ private String addKeyStoreWithCredentialReference(String keyStoreName, String store, String alias, String secret, boolean exists, boolean validateResponse) throws Exception {
+ return addKeyStoreWithCredentialReference(keyStoreName, store, alias, secret, "JKS", exists, validateResponse, false);
+ }
+
+ private String addKeyStoreWithCredentialReference(String keyStoreName, String store, String alias, String secret, String type, boolean exists, boolean validateResponse) throws Exception {
+ return addKeyStoreWithCredentialReference(keyStoreName, store, alias, secret, type, exists, validateResponse, false);
+ }
+
+ private String addKeyStoreWithCredentialReference(String keyStoreName, String store, String alias, String secret, String type, boolean exists, boolean validateResponse, boolean assertFailed) throws Exception {
+ Path resources = Paths.get(Objects.requireNonNull(KeyStoresTestCase.class.getResource(".")).toURI());
+ ModelNode operation = new ModelNode();
+ operation.get(ClientConstants.OPERATION_HEADERS).get("allow-resource-service-restart").set(Boolean.TRUE);
+ operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron-tls").add("key-store", keyStoreName);
+ operation.get(ClientConstants.OP).set(ClientConstants.ADD);
+ operation.get(Constants.PATH).set(resources + "/test.keystore");
+ operation.get(Constants.TYPE).set(type);
+ if (store != null) {
+ operation.get(CredentialReference.CREDENTIAL_REFERENCE).get(STORE).set(store);
+ }
+ boolean autoGeneratedAlias = false;
+ if (alias != null) {
+ operation.get(CredentialReference.CREDENTIAL_REFERENCE).get(ALIAS).set(alias);
+ } else {
+ autoGeneratedAlias = true;
+ }
+ if (secret != null) {
+ operation.get(CredentialReference.CREDENTIAL_REFERENCE).get(CLEAR_TEXT).set(secret);
+ }
+ if (assertFailed) {
+ ModelNode response = assertFailed(services.executeOperation(operation)).get(RESULT);
+ if (validateResponse) {
+ return validateFailedResponse(response);
+ } else {
+ return null;
+ }
+ } else {
+ ModelNode response = assertSuccess(services.executeOperation(operation)).get(RESULT);
+ if (validateResponse) {
+ return validateResponse(response, secret, autoGeneratedAlias, exists);
+ } else {
+ return null;
+ }
+ }
+ }
+
+ private void testAddKeyStoreWithInvalidCredentialReference(String keyStoreName, String store, String alias, String secret) throws Exception {
+ Path resources = Paths.get(Objects.requireNonNull(KeyStoresTestCase.class.getResource(".")).toURI());
+ ModelNode operation = new ModelNode();
+ operation.get(ClientConstants.OPERATION_HEADERS).get("allow-resource-service-restart").set(Boolean.TRUE);
+ operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron-tls").add("key-store", keyStoreName);
+ operation.get(ClientConstants.OP).set(ClientConstants.ADD);
+ operation.get(Constants.PATH).set(resources + "/test.keystore");
+ operation.get(Constants.TYPE).set("JKS");
+ if (store != null) {
+ operation.get(CredentialReference.CREDENTIAL_REFERENCE).get(STORE).set(store);
+ }
+ if (alias != null) {
+ operation.get(CredentialReference.CREDENTIAL_REFERENCE).get(ALIAS).set(alias);
+ }
+ if (secret != null) {
+ operation.get(CredentialReference.CREDENTIAL_REFERENCE).get(CLEAR_TEXT).set(secret);
+ }
+
+ ModelNode response = services.executeOperation(operation);
+ assertEquals(FAILED, response.get(OUTCOME).asString());
+ assertTrue(response.get(FAILURE_DESCRIPTION).asString().contains(CREDENTIAL_REFERENCE));
+ }
+
+ private void testWriteCredentialReferenceAttribute(String resource, String resourceName, String store, String alias, String secret, boolean assertFailed) {
+ ModelNode operation = new ModelNode();
+ operation.get(ClientConstants.OP_ADDR).add("subsystem", "elytron-tls").add(resource, resourceName);
+ operation.get(ClientConstants.OP).set(ClientConstants.WRITE_ATTRIBUTE_OPERATION);
+ operation.get(ClientConstants.NAME).set(CREDENTIAL_REFERENCE);
+ ModelNode credentialReference = new ModelNode();
+ if (store != null) {
+ credentialReference.get(STORE).set(store);
+ }
+ if (alias != null) {
+ credentialReference.get(ALIAS).set(alias);
+ }
+ if (secret != null) {
+ credentialReference.get(CLEAR_TEXT).set(secret);
+ }
+ operation.get(ClientConstants.VALUE).set(credentialReference);
+ ModelNode response = services.executeOperation(operation);
+ if (assertFailed) {
+ assertEquals(FAILED, response.get(OUTCOME).asString());
+ assertTrue(response.get(FAILURE_DESCRIPTION).asString().contains(CREDENTIAL_REFERENCE));
+ } else {
+ assertSuccess(response);
+ }
+ }
+
+ private void writeClearTextAttribute(String resource, String resourceName, String secret) {
+ ModelNode operation = new ModelNode();
+ operation.get(ClientConstants.OP_ADDR).add("subsystem", "elytron-tls").add(resource, resourceName);
+ operation.get(ClientConstants.OP).set(ClientConstants.WRITE_ATTRIBUTE_OPERATION);
+ operation.get(ClientConstants.NAME).set(CLEAR_TEXT_ATTRIBUTE_NAME);
+ operation.get(ClientConstants.VALUE).set(secret);
+ ModelNode response = assertSuccess(services.executeOperation(operation)).get(RESULT);
+ validateResponse(response, secret, false, true);
+ }
+
+ private String generateKeyPairWithCredentialStoreUpdate(String keyStoreName, String store, String alias, String secret, boolean exists) {
+ ModelNode operation = new ModelNode();
+ operation.get(ClientConstants.OP_ADDR).add("subsystem", "elytron-tls").add("key-store", keyStoreName);
+ operation.get(ClientConstants.OP).set(Constants.GENERATE_KEY_PAIR);
+ operation.get(Constants.ALIAS).set("bsmith");
+ operation.get(Constants.DISTINGUISHED_NAME).set("CN=bob smith");
+ operation.get(CredentialReference.CREDENTIAL_REFERENCE).get(STORE).set(store);
+ boolean autoGeneratedAlias = false;
+ if (alias != null) {
+ operation.get(CredentialReference.CREDENTIAL_REFERENCE).get(CredentialReference.ALIAS).set(alias);
+ } else {
+ autoGeneratedAlias = true;
+ }
+ if (secret != null) {
+ operation.get(CredentialReference.CREDENTIAL_REFERENCE).get(CredentialReference.CLEAR_TEXT).set(secret);
+ }
+ ModelNode response = assertSuccess(services.executeOperation(operation)).get(RESULT);
+ return validateResponse(response, secret, autoGeneratedAlias, exists);
+ }
+
+ private String validateResponse(ModelNode response, String secret, boolean autoGeneratedAlias, boolean exists) {
+ if (secret == null) {
+ assertFalse(response.isDefined());
+ return null;
+ }
+ ModelNode credentialStoreUpdate = response.get(CredentialReference.CREDENTIAL_STORE_UPDATE);
+ if (! exists) {
+ assertEquals(CredentialReference.NEW_ENTRY_ADDED, credentialStoreUpdate.get(CredentialReference.STATUS).asString());
+ } else {
+ assertEquals(CredentialReference.EXISTING_ENTRY_UPDATED, credentialStoreUpdate.get(CredentialReference.STATUS).asString());
+ }
+ if (autoGeneratedAlias) {
+ String generatedAlias = credentialStoreUpdate.get(CredentialReference.NEW_ALIAS).asString();
+ assertTrue(generatedAlias != null && ! generatedAlias.isEmpty());
+ return generatedAlias;
+ }
+ return null;
+ }
+
+ private String validateFailedResponse(ModelNode response) {
+ ModelNode credentialStoreUpdate = response.get(CredentialReference.CREDENTIAL_STORE_UPDATE);
+ assertEquals(CredentialReference.UPDATE_ROLLED_BACK, credentialStoreUpdate.get(CredentialReference.STATUS).asString());
+ return null;
+ }
+
+ private String readAttribute(String keyStoreName, String attributeName) {
+ ModelNode operation = new ModelNode();
+ operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron-tls").add("key-store", keyStoreName);
+ operation.get(ClientConstants.OP).set(ClientConstants.READ_ATTRIBUTE_OPERATION);
+ operation.get(NAME).set(attributeName);
+ return assertSuccess(services.executeOperation(operation)).get(RESULT).asStringOrNull();
+ }
+
+ private void removeKeyStore(String keyStoreName) {
+ ModelNode operation = new ModelNode();
+ operation.get(ClientConstants.OPERATION_HEADERS).get("allow-resource-service-restart").set(Boolean.TRUE);
+ operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron-tls").add("key-store", keyStoreName);
+ operation.get(ClientConstants.OP).set(ClientConstants.REMOVE_OPERATION);
+ assertSuccess(services.executeOperation(operation));
+ }
+
+ private CredentialStore getNonEmptyCredentialStore() throws CredentialStoreException {
+ CredentialStore credentialStore = getCredentialStore(NON_EMPTY_CS_NAME);
+ credentialStore.store(EXISTING_ALIAS, new PasswordCredential(ClearPassword.createRaw(ClearPassword.ALGORITHM_CLEAR, EXISTING_PASSWORD.toCharArray())));
+ credentialStore.flush();
+ return credentialStore;
+ }
+
+ private CredentialStore getCredentialStore(String store) {
+ ServiceName serviceName = Capabilities.CREDENTIAL_STORE_RUNTIME_CAPABILITY.getCapabilityServiceName(store);
+ return (CredentialStore) services.getContainer().getService(serviceName).getValue();
+ }
+
+ private ModelNode assertSuccess(ModelNode response) {
+ if (!response.get(OUTCOME).asString().equals(SUCCESS)) {
+ Assert.fail(response.toJSONString(false));
+ }
+ return response;
+ }
+
+ private ModelNode assertFailed(ModelNode response) {
+ if (! response.get(OUTCOME).asString().equals(FAILED)) {
+ Assert.fail(response.toJSONString(false));
+ }
+ return response;
+ }
+
+ private void addKeyStore() throws Exception {
+ addKeyStore("test.keystore", KS_NAME, "Elytron");
+ }
+
+ private void addKeyStore(String keyStoreFile, String keyStoreName, String keyStorePassword) throws Exception {
+ Path resources = Paths.get(Objects.requireNonNull(KeyStoresTestCase.class.getResource(".")).toURI());
+ ModelNode operation = new ModelNode();
+ operation.get(ClientConstants.OPERATION_HEADERS).get("allow-resource-service-restart").set(Boolean.TRUE);
+ operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron-tls").add("key-store", keyStoreName);
+ operation.get(ClientConstants.OP).set(ClientConstants.ADD);
+ operation.get(Constants.PATH).set(resources + "/test.keystore");
+ operation.get(Constants.TYPE).set("JKS");
+ operation.get(CredentialReference.CREDENTIAL_REFERENCE).get(CredentialReference.CLEAR_TEXT).set(keyStorePassword);
+ assertSuccess(services.executeOperation(operation));
+ }
+}
diff --git a/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/ElytronTlsSubsystemTestCase.java b/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/ElytronTlsSubsystem1_0TestCase.java
similarity index 50%
rename from subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/ElytronTlsSubsystemTestCase.java
rename to subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/ElytronTlsSubsystem1_0TestCase.java
index 5abd401..6e21b7c 100644
--- a/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/ElytronTlsSubsystemTestCase.java
+++ b/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/ElytronTlsSubsystem1_0TestCase.java
@@ -1,11 +1,13 @@
/*
- * Copyright 2019 Red Hat, Inc.
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2021 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
*
* 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
+ * 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,
@@ -17,51 +19,31 @@
package org.wildfly.extension.elytron.tls.subsystem;
import java.io.IOException;
-import java.util.List;
+import org.jboss.as.controller.RunningMode;
import org.jboss.as.subsystem.test.AbstractSubsystemBaseTest;
import org.jboss.as.subsystem.test.AdditionalInitialization;
-import org.jboss.as.subsystem.test.KernelServices;
-import org.jboss.dmr.ModelNode;
-import org.junit.Assert;
-import org.junit.Test;
/**
- * @author Kabir Khan
+ *
+ * @author Farah Juma
* @author Cameron Rodriguez
*/
-public class ElytronTlsSubsystemTestCase extends AbstractSubsystemBaseTest {
+public class ElytronTlsSubsystem1_0TestCase extends AbstractSubsystemBaseTest {
- public ElytronTlsSubsystemTestCase() {
+ public ElytronTlsSubsystem1_0TestCase() {
super(ElytronTlsExtension.SUBSYSTEM_NAME, new ElytronTlsExtension());
}
@Override
protected String getSubsystemXml() throws IOException {
- return readResource("elytron-tls-subsystem-test.xml");
+ return readResource("elytron-tls-subsystem-1.0.xml");
}
@Override
- protected String getSubsystemXsdPath() {
- return ElytronTlsExtension.getCurrentXsdPath();
- }
-
- @Test
- public void testParseAndMarshalModel_TLS() throws Exception {
- standardSubsystemTest("tls.xml");
- }
-
- @Test
- public void testDisallowedProviders() throws Exception {
- KernelServices services = standardSubsystemTest("providers.xml", true);
- List disallowedProviders = services.readWholeModel().get("subsystem", "elytron-tls", "disallowed-providers").asList();
- Assert.assertNotNull(disallowedProviders);
- Assert.assertEquals(3, disallowedProviders.size());
- }
-
protected AdditionalInitialization createAdditionalInitialization() {
// Our use of the expression=encryption resource requires kernel capability setup that TestEnvironment provides
- return TestEnvironment.asAdmin();
+ return new TestEnvironment(RunningMode.ADMIN_ONLY);
}
}
diff --git a/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/ExpressionResolutionTestCase.java b/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/ExpressionResolutionTestCase.java
index b069b04..beedcc3 100644
--- a/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/ExpressionResolutionTestCase.java
+++ b/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/ExpressionResolutionTestCase.java
@@ -107,7 +107,7 @@ public void testPreConfiguredHierarchy() throws Exception {
csTwo = createCredentialStoreTwo();
csThree = createCredentialStoreThree();
- KernelServices services = super.createKernelServicesBuilder(TestEnvironment.asNormal())
+ KernelServices services = super.createKernelServicesBuilder(new TestEnvironment())
.setSubsystemXmlResource("expression-encryption.xml").build();
if (!services.isSuccessfulBoot()) {
Assert.fail(services.getBootError().toString());
@@ -128,7 +128,7 @@ public void testPreConfiguredHierarchy() throws Exception {
protected AdditionalInitialization createAdditionalInitialization() {
// Our use of the expression=encryption resource requires kernel capability setup that TestEnvironment provides
- return TestEnvironment.asAdmin();
+ return new TestEnvironment(RunningMode.ADMIN_ONLY);
}
private static void cleanUp(CredentialStoreUtility csUtil) {
@@ -185,7 +185,7 @@ private void testExpectedAliases(KernelServices services, String resourceType, S
@Test
public void testExpressionEncryptionOperations() throws Exception {
- KernelServices services = super.createKernelServicesBuilder(TestEnvironment.asNormal()).setSubsystemXml(emptySubsystemXml()).build();
+ KernelServices services = super.createKernelServicesBuilder(new TestEnvironment()).setSubsystemXml(emptySubsystemXml()).build();
if (!services.isSuccessfulBoot()) {
Assert.fail(services.getBootError().toString());
}
@@ -203,9 +203,6 @@ public void testExpressionEncryptionOperations() throws Exception {
add.get(Constants.PATH).set(testStorePath);
add.get(Constants.POPULATE).set(false);
- System.out.println("string is");
- System.out.println(add.get(ClientConstants.OP_ADDR));
-
assertSuccess(services.executeOperation(add));
// Generate one and export it.
@@ -357,7 +354,7 @@ public void testExpressionEncryptionCycle() throws Exception {
addEE.get(Constants.RESOLVERS).set(resolvers);
steps.add(addEE);
- KernelServices services = super.createKernelServicesBuilder(TestEnvironment.asNormal()).setSubsystemXml(emptySubsystemXml()).build();
+ KernelServices services = super.createKernelServicesBuilder(new TestEnvironment()).setSubsystemXml(emptySubsystemXml()).build();
if (!services.isSuccessfulBoot()) {
Assert.fail(services.getBootError().toString());
}
diff --git a/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/KeyStoresTestCase.java b/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/KeyStoresTestCase.java
index 579a4af..5fb12a0 100644
--- a/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/KeyStoresTestCase.java
+++ b/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/KeyStoresTestCase.java
@@ -70,6 +70,7 @@
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
+import org.junit.Ignore;
import org.junit.Test;
import org.mockserver.integration.ClientAndServer;
import org.wildfly.security.WildFlyElytronProvider;
@@ -363,7 +364,7 @@ public void init() throws Exception {
} else {
subsystemXml = JdkUtils.getJavaSpecVersion() <= 12 ? "tls-sun.xml" : "tls-oracle13plus.xml";
}
- services = super.createKernelServicesBuilder(TestEnvironment.asNormal()).setSubsystemXmlResource(subsystemXml).build();
+ services = super.createKernelServicesBuilder(new TestEnvironment()).setSubsystemXmlResource(subsystemXml).build();
if (!services.isSuccessfulBoot()) {
Assert.fail(services.getBootError().toString());
}
@@ -522,6 +523,7 @@ private void checkCertificate(final ModelNode certificate, final boolean verbose
}
}
+ @Ignore("Filtering keystores not implemented yet")
@Test
public void testFilteringKeystoreService() throws Exception {
ServiceName serviceName = Capabilities.KEY_STORE_RUNTIME_CAPABILITY.getCapabilityServiceName("FilteringKeyStore");
@@ -539,6 +541,26 @@ public void testFilteringKeystoreService() throws Exception {
assertFalse(keyStore.isCertificateEntry("ca"));
}
+ @Ignore("Filtering keystores not implemented yet")
+ @Test
+ public void testFilteringKeystoreCli() throws Exception {
+ ModelNode operation = new ModelNode();
+ operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron").add(Constants.FILTERING_KEY_STORE,"FilteringKeyStore");
+ operation.get(ClientConstants.OP).set(Constants.READ_ALIASES);
+ List nodes = assertSuccess(services.executeOperation(operation)).get(ClientConstants.RESULT).asList();
+ assertEquals(1, nodes.size());
+ assertEquals("firefly", nodes.get(0).asString());
+
+ operation = new ModelNode();
+ operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron").add(Constants.FILTERING_KEY_STORE,"FilteringKeyStore");
+ operation.get(ClientConstants.OP).set(Constants.READ_ALIAS);
+ operation.get(Constants.ALIAS).set("firefly");
+ ModelNode firefly = assertSuccess(services.executeOperation(operation)).get(ClientConstants.RESULT);
+ assertEquals("firefly", firefly.get(Constants.ALIAS).asString());
+ assertEquals(KeyStore.PrivateKeyEntry.class.getSimpleName(), firefly.get(Constants.ENTRY_TYPE).asString());
+ assertTrue(firefly.get(Constants.CERTIFICATE_CHAIN).isDefined());
+ }
+
@Test
public void testAutomaticKeystoreService() throws Exception {
ServiceName serviceName = Capabilities.KEY_STORE_RUNTIME_CAPABILITY.getCapabilityServiceName("AutomaticKeystore");
@@ -1328,7 +1350,7 @@ private void addOriginalKeyStore() throws Exception {
private List readAliases() {
ModelNode operation = new ModelNode();
- operation.get(ClientConstants.OP_ADDR).add("subsystem","`elytron-tls").add("key-store", KEYSTORE_NAME);
+ operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron-tls").add("key-store", KEYSTORE_NAME);
operation.get(ClientConstants.OP).set(Constants.READ_ALIASES);
return assertSuccess(services.executeOperation(operation)).get(ClientConstants.RESULT).asList();
}
@@ -1414,7 +1436,7 @@ private void removeCertificateAuthority() {
private void removeCertificateAuthorityAccount() {
ModelNode operation = new ModelNode();
operation.get(ClientConstants.OPERATION_HEADERS).get("allow-resource-service-restart").set(Boolean.TRUE);
- operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron-tls`").add("certificate-authority-account", CERTIFICATE_AUTHORITY_ACCOUNT_NAME);
+ operation.get(ClientConstants.OP_ADDR).add("subsystem","elytron-tls").add("certificate-authority-account", CERTIFICATE_AUTHORITY_ACCOUNT_NAME);
operation.get(ClientConstants.OP).set(ClientConstants.REMOVE_OPERATION);
assertSuccess(services.executeOperation(operation));
}
diff --git a/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/ResolveExpressionAttributesTestCase.java b/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/ResolveExpressionAttributesTestCase.java
index 94a6734..4db6864 100644
--- a/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/ResolveExpressionAttributesTestCase.java
+++ b/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/ResolveExpressionAttributesTestCase.java
@@ -68,7 +68,7 @@ protected String getSubsystemXml() throws IOException {
@Override
protected AdditionalInitialization createAdditionalInitialization() {
// Our use of the expression=encryption resource requires kernel capability setup that TestEnvironment provides
- return TestEnvironment.asAdmin();
+ return new TestEnvironment(RunningMode.ADMIN_ONLY);
}
@Test
@@ -82,6 +82,7 @@ public void testExpressionAttributesResolved() {
testKeyStore();
// testLdapKeyStore();
testProvider();
+ // testSaslServer();
testTLSComponents();
}
@@ -126,6 +127,7 @@ private void testCustomComponent() {
private void testElytronTlsDefinition() {
assertEquals(Arrays.asList("test"), getValue(serverModel, Constants.DISALLOWED_PROVIDERS, true));
+ // assertEquals("false", getValue(serverModel, Constants.REGISTER_JASPI_FACTORY));
}
private void testFilteringKeyStoreDefinition() {
@@ -133,6 +135,19 @@ private void testFilteringKeyStoreDefinition() {
assertEquals("NONE:+firefly", getValue(keystore, Constants.ALIAS_FILTER));
}
+ private void testJaspiConfiguration() {
+ ModelNode jaspi = serverModel.get(Constants.JASPI_CONFIGURATION).get("test");
+ assertEquals("HttpServlet", getValue(jaspi, Constants.LAYER));
+ assertEquals("default /test", getValue(jaspi, Constants.APPLICATION_CONTEXT));
+ assertEquals("Test Definition", getValue(jaspi, Constants.DESCRIPTION));
+
+ ModelNode testModule = jaspi.get(Constants.SERVER_AUTH_MODULES).get(0);
+ assertEquals("REQUISITE", getValue(testModule, Constants.FLAG));
+
+ ModelNode options = testModule.get(Constants.OPTIONS);
+ assertEquals("b", getValue(options, "a"));
+ }
+
private void testKeyStore() {
ModelNode keystore = serverModel.get(Constants.KEY_STORE).get("jks_store");
assertEquals("jks", getValue(keystore, Constants.TYPE));
@@ -173,10 +188,17 @@ private void testLdapKeyStore() {
private void testProvider() {
ModelNode provider = serverModel.get(Constants.PROVIDER_LOADER).get("openssl");
assertEquals("val", getValue(provider.get(Constants.CONFIGURATION), "prop"));
- provider = serverModel.get(Constants.PROVIDER_LOADER).get("elytron-tls");
+ provider = serverModel.get(Constants.PROVIDER_LOADER).get("elytron");
assertEquals("arg", getValue(provider, Constants.ARGUMENT));
}
+ private void testSaslServer() {
+ ModelNode factory = serverModel.get(Constants.SASL_AUTHENTICATION_FACTORY).get("SaslAuthenticationDefinition").get(Constants.MECHANISM_CONFIGURATIONS).get(0);
+ assertEquals("PLAIN", getValue(factory, Constants.MECHANISM_NAME));
+ assertEquals("host", getValue(factory, Constants.HOST_NAME));
+ assertEquals("protocol", getValue(factory, Constants.PROTOCOL));
+ }
+
private void testTLSComponents() {
// SSL Context
ModelNode context = serverModel.get(Constants.SERVER_SSL_CONTEXT).get("server");
diff --git a/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/SecurityPropertiesTestCase.java b/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/SecurityPropertiesTestCase.java
new file mode 100644
index 0000000..3a6d49c
--- /dev/null
+++ b/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/SecurityPropertiesTestCase.java
@@ -0,0 +1,96 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2017, Red Hat, Inc., and individual contributors as indicated
+ * by the @authors tag.
+ *
+ * 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.extension.elytron.tls.subsystem;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author Tomaz Cerar (c) 2017 Red Hat Inc.
+ */
+public class SecurityPropertiesTestCase {
+
+ @Test
+ public void testPropertyDiff(){
+ Map newMap = new HashMap<>();
+ Map oldMap = new HashMap<>();
+
+ Map updated = new HashMap<>();
+ Map added = new HashMap<>();
+ Map removed = new HashMap<>();
+
+ newMap.put("key1","value");
+ newMap.put("key2","value");
+ newMap.put("key3","value");
+
+ SecurityPropertiesWriteHandler.doDifference(newMap, oldMap, added, removed, updated );
+ Assert.assertEquals(0, updated.size());
+ Assert.assertEquals(3, added.size());
+ Assert.assertEquals(0, removed.size());
+
+ oldMap.put("key1","value2");
+
+ updated.clear();
+ removed.clear();
+ added.clear();
+
+ SecurityPropertiesWriteHandler.doDifference(newMap, oldMap, added, removed, updated);
+ Assert.assertEquals(1, updated.size());
+ Assert.assertEquals(2, added.size());
+ Assert.assertEquals(0, removed.size());
+
+
+ oldMap.put("key1", "value1");
+ oldMap.put("key2", "value2");
+ oldMap.put("key3", "value3");
+
+ updated.clear();
+ removed.clear();
+ added.clear();
+
+ SecurityPropertiesWriteHandler.doDifference(newMap, oldMap, added, removed, updated);
+ Assert.assertEquals(3, updated.size());
+ Assert.assertEquals(0, added.size());
+ Assert.assertEquals(0, removed.size());
+
+
+ newMap.clear();
+ newMap.put("key1", "value");
+ newMap.put("key2", "value");
+ newMap.put("key4", "value");
+
+ oldMap.clear();
+ oldMap.put("key1", "value1");
+ oldMap.put("key2", "value2");
+ oldMap.put("key3", "value3");
+
+ updated.clear();
+ removed.clear();
+ added.clear();
+
+ SecurityPropertiesWriteHandler.doDifference(newMap, oldMap, added, removed, updated);
+ Assert.assertEquals(2, updated.size());
+ Assert.assertEquals(1, added.size());
+ Assert.assertEquals(1, removed.size());
+
+ }
+}
diff --git a/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/SubsystemParsingTestCase.java b/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/SubsystemParsingTestCase.java
new file mode 100644
index 0000000..3311957
--- /dev/null
+++ b/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/SubsystemParsingTestCase.java
@@ -0,0 +1,98 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2014 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * 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.extension.elytron.tls.subsystem;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.jboss.as.subsystem.test.AbstractSubsystemBaseTest;
+import org.jboss.as.subsystem.test.AdditionalInitialization;
+import org.jboss.as.subsystem.test.KernelServices;
+import org.jboss.dmr.ModelNode;
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * Tests all management expects for subsystem, parsing, marshaling, model definition and other
+ * Here is an example that allows you a fine grained controller over what is tested and how. So it can give you ideas what can be done and tested.
+ * If you have no need for advanced testing of subsystem you look at {@link ElytronTlsSubsystem1_0TestCase} that tests same stuff but most of the code
+ * is hidden inside of test harness
+ *
+ * @author Kabir Khan
+ * @author Cameron Rodriguez
+ */
+public class SubsystemParsingTestCase extends AbstractSubsystemBaseTest {
+
+ public SubsystemParsingTestCase() {
+ super(ElytronTlsExtension.SUBSYSTEM_NAME, new ElytronTlsExtension());
+ }
+
+ @Override
+ protected String getSubsystemXml() throws IOException {
+ return readResource("elytron-tls-subsystem-1.0.xml");
+ }
+
+ @Test
+ public void testParseAndMarshalModel_TLS() throws Exception {
+ standardSubsystemTest("tls.xml");
+ }
+
+ @Test
+ public void testParseAndMarshalModel_ProviderLoader() throws Exception {
+ standardSubsystemTest("providers.xml");
+ }
+
+ @Test
+ public void testDisallowedProviders() throws Exception {
+ KernelServices services = standardSubsystemTest("providers.xml", true);
+ List disallowedProviders = services.readWholeModel().get("subsystem", "elytron-tls", "disallowed-providers").asList();
+ Assert.assertNotNull(disallowedProviders);
+ Assert.assertEquals(3, disallowedProviders.size());
+ }
+
+ @Ignore("to be determined if needed")
+ @Test
+ public void testParseAndMarshalModel_Sasl() throws Exception {
+ standardSubsystemTest("sasl.xml");
+ }
+
+ @Test
+ public void testParseAndMarshalModel_SecurityProperties() throws Exception {
+ standardSubsystemTest("security-properties.xml");
+ }
+
+ @Test
+ public void testParseAndMarshalModel_CredentialStores() throws Exception {
+ standardSubsystemTest("credential-stores.xml");
+ }
+
+ @Ignore("to be determined if needed")
+ @Test
+ public void testParseAndMarshalModel_JASPI() throws Exception {
+ standardSubsystemTest("jaspi.xml");
+ }
+
+ @Override
+ protected AdditionalInitialization createAdditionalInitialization() {
+ return AdditionalInitialization.withCapabilities(ElytronTlsExtension.WELD_CAPABILITY_NAME);
+ }
+
+
+}
diff --git a/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/TestEnvironment.java b/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/TestEnvironment.java
index 7cea212..079da33 100644
--- a/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/TestEnvironment.java
+++ b/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/TestEnvironment.java
@@ -17,39 +17,222 @@
*/
package org.wildfly.extension.elytron.tls.subsystem;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.net.URL;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.KeyStore;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
+
+import javax.security.auth.x500.X500Principal;
+
+import org.jboss.as.controller.RunningMode;
+import org.jboss.as.controller.capability.RuntimeCapability;
import org.jboss.as.controller.capability.registry.RuntimeCapabilityRegistry;
import org.jboss.as.controller.extension.ExtensionRegistry;
import org.jboss.as.controller.registry.ManagementResourceRegistration;
import org.jboss.as.controller.registry.Resource;
import org.jboss.as.subsystem.test.AdditionalInitialization;
+import org.jboss.as.subsystem.test.ControllerInitializer;
+import org.jboss.as.subsystem.test.KernelServices;
+import org.jboss.msc.service.ServiceController;
+import org.jboss.msc.service.ServiceName;
+import org.wildfly.security.x500.cert.BasicConstraintsExtension;
+import org.wildfly.security.x500.cert.SelfSignedX509CertificateAndSigningKey;
+import org.wildfly.security.x500.cert.X509CertificateBuilder;
+
+class TestEnvironment extends AdditionalInitialization {
+ // TODO reenable tests after LDAP is added
+
+ static final int LDAPS1_PORT = 11391;
+ static final int LDAPS2_PORT = 11392;
+
+ private static final String WORKING_DIRECTORY_LOCATION = "./target/test-classes/org/wildfly/extension/elytron/tls/subsystem";
+ private static final char[] GENERATED_KEYSTORE_PASSWORD = "Elytron".toCharArray();
+ private static final X500Principal ISSUER_DN = new X500Principal("O=Root Certificate Authority, EMAILADDRESS=elytron@wildfly.org, C=UK, ST=Elytron, CN=Elytron CA");
+ private static final X500Principal LOCALHOST_DN = new X500Principal("OU=Elytron, O=Elytron, C=CZ, ST=Elytron, CN=localhost");
+
+ private static KeyStore loadKeyStore() throws Exception{
+ KeyStore ks = KeyStore.getInstance("JKS");
+ ks.load(null, null);
+ return ks;
+ }
+
+ private static SelfSignedX509CertificateAndSigningKey createIssuer() {
+ return SelfSignedX509CertificateAndSigningKey.builder()
+ .setDn(ISSUER_DN)
+ .setKeyAlgorithmName("RSA")
+ .setSignatureAlgorithmName("SHA256withRSA")
+ .addExtension(false, "BasicConstraints", "CA:true,pathlen:2147483647")
+ .build();
+ }
+
+ private static KeyStore createTrustStore(SelfSignedX509CertificateAndSigningKey issuerSelfSignedX509CertificateAndSigningKey) throws Exception {
+ KeyStore trustStore = loadKeyStore();
+
+ X509Certificate issuerCertificate = issuerSelfSignedX509CertificateAndSigningKey.getSelfSignedCertificate();
+ trustStore.setCertificateEntry("mykey", issuerCertificate);
+
+ return trustStore;
+ }
+
+ private static KeyStore createLocalhostKeyStore(SelfSignedX509CertificateAndSigningKey issuerSelfSignedX509CertificateAndSigningKey) throws Exception {
+ KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
+ KeyPair localhostKeys = keyPairGenerator.generateKeyPair();
+ PrivateKey localhostSigningKey = localhostKeys.getPrivate();
+ PublicKey localhostPublicKey = localhostKeys.getPublic();
+
+ KeyStore localhostKeyStore = loadKeyStore();
+
+ X509Certificate issuerCertificate = issuerSelfSignedX509CertificateAndSigningKey.getSelfSignedCertificate();
+ localhostKeyStore.setCertificateEntry("ca", issuerCertificate);
+
+ X509Certificate localhostCertificate = new X509CertificateBuilder()
+ .setIssuerDn(ISSUER_DN)
+ .setSubjectDn(LOCALHOST_DN)
+ .setSignatureAlgorithmName("SHA256withRSA")
+ .setSigningKey(issuerSelfSignedX509CertificateAndSigningKey.getSigningKey())
+ .setPublicKey(localhostPublicKey)
+ .setSerialNumber(new BigInteger("3"))
+ .addExtension(new BasicConstraintsExtension(false, false, -1))
+ .build();
+ localhostKeyStore.setKeyEntry("localhost", localhostSigningKey, GENERATED_KEYSTORE_PASSWORD, new X509Certificate[]{localhostCertificate,issuerCertificate});
+
+ return localhostKeyStore;
+ }
+
+ private static void createTemporaryKeyStoreFile(KeyStore keyStore, File outputFile) throws Exception {
+ try (FileOutputStream fos = new FileOutputStream(outputFile)){
+ keyStore.store(fos, GENERATED_KEYSTORE_PASSWORD);
+ }
+ }
+
+ public static void setUpKeyStores() throws Exception {
+ File workingDir = new File(WORKING_DIRECTORY_LOCATION);
+ if (workingDir.exists() == false) {
+ workingDir.mkdirs();
+ }
+
+ SelfSignedX509CertificateAndSigningKey issuerSelfSignedX509CertificateAndSigningKey = createIssuer();
+ File trustFile = new File(workingDir, "ca.truststore");
+ KeyStore trustStore = createTrustStore(issuerSelfSignedX509CertificateAndSigningKey);
+ File localhostFile = new File(workingDir, "localhost.keystore");
+ KeyStore localhostKeyStore = createLocalhostKeyStore(issuerSelfSignedX509CertificateAndSigningKey);
+
+ createTemporaryKeyStoreFile(trustStore, trustFile);
+ createTemporaryKeyStoreFile(localhostKeyStore, localhostFile);
+ }
+
+ private final RunningMode runningMode;
+
+ TestEnvironment() {
+ this(RunningMode.NORMAL);
+ }
+
+ TestEnvironment(RunningMode runningMode) {
+ this.runningMode = runningMode;
+
+ }
+
+ @Override
+ protected RunningMode getRunningMode() {
+ return runningMode;
+ }
+
+ @Override
+ protected ControllerInitializer createControllerInitializer() {
+ ControllerInitializer initializer = new ControllerInitializer();
+
+ // TODO perform check without realms
+ try {
+ URL fsr = getClass().getResource("keystore.jceks");
+ if (fsr != null) emptyDirectory(new File(fsr.getFile()).toPath());
+ } catch (Exception e) {
+ throw new RuntimeException("Could ensure empty testing filesystem directory", e);
+ }
+
+ try {
+ initializer.addPath("jboss.server.config.dir", getClass().getResource(".").getFile(), null);
+ initializer.addPath("jboss.server.data.dir", "target", null);
+ } catch (Exception e) {
+ throw new RuntimeException("Could not create test config directory", e);
+ }
+
+ return initializer;
+ }
+
+ @Override
+ protected void initializeExtraSubystemsAndModel(ExtensionRegistry extensionRegistry, Resource rootResource, ManagementResourceRegistration rootRegistration, RuntimeCapabilityRegistry capabilityRegistry) {
+ super.initializeExtraSubystemsAndModel(extensionRegistry, rootResource, rootRegistration, capabilityRegistry);
+ registerCapabilities(capabilityRegistry, ElytronTlsExtension.WELD_CAPABILITY_NAME);
+ }
+
+ /* public static void startLdapService() {
+ try {
+ setUpKeyStores();
+ LdapService.builder()
+ .setWorkingDir(new File("./target/apache-ds/working1"))
+ .createDirectoryService("TestService1")
+ .addPartition("Elytron", "dc=elytron,dc=wildfly,dc=org", 5, "uid")
+ .importLdif(TestEnvironment.class.getResourceAsStream("ldap-schemas.ldif"))
+ .importLdif(TestEnvironment.class.getResourceAsStream("ldap-data.ldif"))
+ .addTcpServer("Default TCP", "localhost", LDAPS1_PORT, "localhost.keystore", "Elytron")
+ .start();
+ LdapService.builder()
+ .setWorkingDir(new File("./target/apache-ds/working2"))
+ .createDirectoryService("TestService2")
+ .addPartition("Elytron", "dc=elytron,dc=wildfly,dc=org", 5, "uid")
+ .importLdif(TestEnvironment.class.getResourceAsStream("ldap-schemas.ldif"))
+ .importLdif(TestEnvironment.class.getResourceAsStream("ldap-referred.ldif"))
+ .addTcpServer("Default TCP", "localhost", LDAPS2_PORT, "localhost.keystore", "Elytron")
+ .start();
+ } catch (Exception e) {
+ throw new RuntimeException("Could not start LDAP embedded server.", e);
+ }
+ } */
+
+ private void emptyDirectory(Path directory) throws IOException {
+ Files.walkFileTree(directory, new SimpleFileVisitor() {
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+ Files.delete(file);
+ return FileVisitResult.CONTINUE;
+ }
-class TestEnvironment {
- // TODO: Re-add LDAP configuration
-
- /**
- * Creates an {@link AdditionalInitialization} with the Weld {@link org.jboss.as.controller.capability.RuntimeCapability capability},
- * operating in {@link org.jboss.as.controller.RunningMode#ADMIN_ONLY RunningMode.ADMIN_ONLY}.
- *
- * @author Cameron Rodriguez
- */
- static AdditionalInitialization asAdmin() {
- return AdditionalInitialization.withCapabilities(ElytronTlsExtension.WELD_CAPABILITY_NAME);
- }
-
- /**
- * Creates an {@link AdditionalInitialization} with the Weld {@link org.jboss.as.controller.capability.RuntimeCapability capability},
- * operating in {@link org.jboss.as.controller.RunningMode#NORMAL RunningMode.NORMAL}.
- *
- * @author Cameron Rodriguez
- */
- static AdditionalInitialization asNormal() {
- return new AdditionalInitialization() {
@Override
- protected void initializeExtraSubystemsAndModel(ExtensionRegistry extensionRegistry, Resource rootResource,
- ManagementResourceRegistration rootRegistration, RuntimeCapabilityRegistry capabilityRegistry) {
- super.initializeExtraSubystemsAndModel(extensionRegistry, rootResource, rootRegistration, capabilityRegistry);
- registerCapabilities(capabilityRegistry, ElytronTlsExtension.WELD_CAPABILITY_NAME);
+ public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
+ Files.delete(dir);
+ return FileVisitResult.CONTINUE;
}
- };
+ });
+ }
+
+ // classloader obtaining mock to load classes from testsuite
+ /* private static class ClassLoadingAttributeDefinitionsMock extends MockUp {
+ @Mock
+ static ClassLoader resolveClassLoader(String module) {
+ return SaslTestCase.class.getClassLoader();
+ }
+ }
+
+ static void mockCallerModuleClassloader() {
+ new ClassLoadingAttributeDefinitionsMock();
+ } */
+
+ static void activateService(KernelServices services, RuntimeCapability capability, String... dynamicNameElements) throws InterruptedException {
+ ServiceName serviceName = capability.getCapabilityServiceName(dynamicNameElements);
+ ServiceController> serviceController = services.getContainer().getService(serviceName);
+ serviceController.setMode(ServiceController.Mode.ACTIVE);
+ serviceController.awaitValue();
}
}
diff --git a/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/TlsTestCase.java b/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/TlsTestCase.java
index 88e7c48..d8c0b3c 100644
--- a/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/TlsTestCase.java
+++ b/subsystem/src/test/java/org/wildfly/extension/elytron/tls/subsystem/TlsTestCase.java
@@ -1,3 +1,21 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.extension.elytron.tls.subsystem;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.FAILED;
@@ -78,6 +96,7 @@
import org.wildfly.security.x500.cert.X509CertificateBuilder;
/**
+ * @author Jan Kalina
* @author Cameron Rodriguez
*/
public class TlsTestCase extends AbstractSubsystemTest {
@@ -99,7 +118,7 @@ public class TlsTestCase extends AbstractSubsystemTest {
private static final String INIT_TEST_TRUSTSTORE = "myTS";
private static final String INIT_TEST_TRUSTMANAGER = "myTM";
- private static final char[] GENERATED_KEYSTORE_PASSWORD = "ElytronTLS".toCharArray();
+ private static final char[] GENERATED_KEYSTORE_PASSWORD = "Elytron".toCharArray();
private static final String PROTOCOLS_SERVER = "enabledProtocolsServer";
private static final String PROTOCOLS_CLIENT = "enabledProtocolsClient";
private static final String NEGOTIATED_PROTOCOL = "negotiatedProtocol";
@@ -249,7 +268,7 @@ private static void createTemporaryKeyStoreFile(KeyStore keyStore, File outputFi
private static void setUpKeyStores() throws Exception {
File workingDir = new File(WORKING_DIRECTORY_LOCATION);
if (!workingDir.exists()) {
- Assert.assertTrue(workingDir.mkdirs());
+ workingDir.mkdirs();
}
SelfSignedX509CertificateAndSigningKey issuerSelfSignedX509CertificateAndSigningKey = createIssuer(ISSUER_DN);
@@ -284,7 +303,7 @@ private static void deleteKeyStoreFiles() {
};
for (File file : testFiles) {
if (file.exists()) {
- Assert.assertTrue(file.delete());
+ file.delete();
}
}
}
@@ -332,7 +351,7 @@ public void prepare() throws Throwable {
} else {
subsystemXml = JdkUtils.getJavaSpecVersion() <= 12 ? "tls-sun.xml" : "tls-oracle13plus.xml";
}
- services = super.createKernelServicesBuilder(TestEnvironment.asNormal()).setSubsystemXmlResource(subsystemXml).build();
+ services = super.createKernelServicesBuilder(new TestEnvironment()).setSubsystemXmlResource(subsystemXml).build();
if (!services.isSuccessfulBoot()) {
Assert.fail(services.getBootError().toString());
}
@@ -398,9 +417,13 @@ public void testSslServiceAuthSSLv2HelloOneWay() throws Throwable {
public void testSslServiceAuthProtocolMismatchSSLv2Hello() throws Throwable {
Assume.assumeFalse("Skipping testSslServiceAuthSSLv2Hello as IBM JDK does not support enabling SSLv2Hello " +
"in the client", JdkUtils.isIbmJdk());
- testCommunication("ServerSslContextTLS12Only", "ClientSslContextSSLv2Hello", false, "OU=Elytron,O=Elytron,C=CZ,ST=Elytron,CN=localhost",
- "OU=Elytron,O=Elytron,C=UK,ST=Elytron,CN=Firefly");
- fail("Excepted SSLHandshakeException not thrown");
+ try {
+ testCommunication("ServerSslContextTLS12Only", "ClientSslContextSSLv2Hello", false, "OU=Elytron,O=Elytron,C=CZ,ST=Elytron,CN=localhost",
+ "OU=Elytron,O=Elytron,C=UK,ST=Elytron,CN=Firefly");
+ fail("Excepted SSLHandshakeException not thrown");
+ } catch (SSLHandshakeException ignored) {
+
+ }
}
@Test
@@ -765,6 +788,7 @@ private void checkProtocolConfiguration(Map protocolChecker, S
// Check negotiated protocol is the one we expected
assertEquals(protocolChecker.get(NEGOTIATED_PROTOCOL)[0], serverSocket.getSession().getProtocol());
+ assertEquals(protocolChecker.get(NEGOTIATED_PROTOCOL)[0], clientSocket.getSession().getProtocol());
}
private void testSessionsReading(String serverContextName, String clientContextName, String expectedServerPrincipal, String expectedClientPrincipal) {
diff --git a/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/credential-store-updates.xml b/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/credential-store-updates.xml
new file mode 100644
index 0000000..360409b
--- /dev/null
+++ b/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/credential-store-updates.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/credential-store.xml b/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/credential-store.xml
new file mode 100644
index 0000000..6d36283
--- /dev/null
+++ b/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/credential-store.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/credential-stores.xml b/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/credential-stores.xml
new file mode 100644
index 0000000..59e6f5c
--- /dev/null
+++ b/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/credential-stores.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/elytron-tls-expressions.xml b/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/elytron-tls-expressions.xml
index 6c70784..eafc85a 100644
--- a/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/elytron-tls-expressions.xml
+++ b/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/elytron-tls-expressions.xml
@@ -24,7 +24,7 @@
-
+
diff --git a/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/elytron-tls-subsystem-1.0.xml b/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/elytron-tls-subsystem-1.0.xml
new file mode 100644
index 0000000..2a0caa2
--- /dev/null
+++ b/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/elytron-tls-subsystem-1.0.xml
@@ -0,0 +1,206 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/elytron-tls-subsystem-test.xml b/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/elytron-tls-subsystem-test.xml
index 9b93892..8442a81 100644
--- a/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/elytron-tls-subsystem-test.xml
+++ b/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/elytron-tls-subsystem-test.xml
@@ -15,29 +15,36 @@
-->
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -84,6 +91,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/jaspi.xml b/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/jaspi.xml
new file mode 100644
index 0000000..cfe77eb
--- /dev/null
+++ b/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/jaspi.xml
@@ -0,0 +1,26 @@
+
+
diff --git a/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/security-properties.xml b/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/security-properties.xml
new file mode 100644
index 0000000..1e13f51
--- /dev/null
+++ b/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/security-properties.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/tls-ibm.xml b/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/tls-ibm.xml
index 448656a..cff1ea0 100644
--- a/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/tls-ibm.xml
+++ b/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/tls-ibm.xml
@@ -16,7 +16,7 @@
-
+
@@ -46,32 +46,32 @@
-
-
-
-
+
+
+
+
-
+
-
+
-
+
-
+
-
+
-
+
diff --git a/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/tls-oracle13plus.xml b/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/tls-oracle13plus.xml
index df5b0b1..1de525d 100644
--- a/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/tls-oracle13plus.xml
+++ b/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/tls-oracle13plus.xml
@@ -16,7 +16,7 @@
-
+
@@ -45,32 +45,32 @@
-
-
-
-
+
+
+
+
-
+
-
+
-
+
-
+
-
+
-
+
diff --git a/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/tls-sun.xml b/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/tls-sun.xml
index 928a3c4..10e5943 100644
--- a/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/tls-sun.xml
+++ b/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/tls-sun.xml
@@ -16,7 +16,7 @@
-
+
@@ -45,32 +45,32 @@
-
-
-
-
+
+
+
+
-
+
-
+
-
+
-
+
-
+
-
+
diff --git a/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/tls.xml b/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/tls.xml
index cacb7cc..746fd57 100644
--- a/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/tls.xml
+++ b/subsystem/src/test/resources/org/wildfly/extension/elytron/tls/subsystem/tls.xml
@@ -3,7 +3,6 @@
-
@@ -62,7 +61,6 @@
-
@@ -85,24 +83,5 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/testsuite/integration/pom.xml b/testsuite/integration/pom.xml
index c797446..a4ec780 100644
--- a/testsuite/integration/pom.xml
+++ b/testsuite/integration/pom.xml
@@ -88,6 +88,10 @@
wildfly-arquillian-protocol-jmx
test
+
+ org.wildfly.core
+ wildfly-core-test-runner
+
\ No newline at end of file
diff --git a/testsuite/integration/subsystem/src/test/java/org/wildfly/test/feature/pack/elytron/tls/subsystem/common/ModelNodeConvertable.java b/testsuite/integration/subsystem/src/test/java/org/jboss/as/test/shared/CliUtils.java
similarity index 54%
rename from testsuite/integration/subsystem/src/test/java/org/wildfly/test/feature/pack/elytron/tls/subsystem/common/ModelNodeConvertable.java
rename to testsuite/integration/subsystem/src/test/java/org/jboss/as/test/shared/CliUtils.java
index 663bce3..3690729 100644
--- a/testsuite/integration/subsystem/src/test/java/org/wildfly/test/feature/pack/elytron/tls/subsystem/common/ModelNodeConvertable.java
+++ b/testsuite/integration/subsystem/src/test/java/org/jboss/as/test/shared/CliUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 Red Hat, Inc.
+ * Copyright 2016 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.
@@ -14,17 +14,24 @@
* limitations under the License.
*/
-package org.wildfly.test.feature.pack.elytron.tls.subsystem.common;
+package org.jboss.as.test.shared;
-import org.jboss.dmr.ModelNode;
+import static org.wildfly.common.Assert.checkNotNullParamWithNullPointerException;
/**
- * Represents objects which are convertable to ModelNode instances.
+ * CLI helper methods.
*
* @author Josef Cacek
*/
-public interface ModelNodeConvertable {
-
- ModelNode toModelNode();
+public class CliUtils {
+ /**
+ * Escapes given path String for CLI.
+ *
+ * @param path path string to escape (must be not-null
)
+ * @return escaped path
+ */
+ public static String escapePath(String path) {
+ return checkNotNullParamWithNullPointerException("path", path).replace("\\", "\\\\");
+ }
}
diff --git a/testsuite/integration/subsystem/src/test/java/org/wildfly/test/feature/pack/elytron/tls/subsystem/common/AbstractConfigurableElement.java b/testsuite/integration/subsystem/src/test/java/org/wildfly/test/feature/pack/elytron/tls/subsystem/common/AbstractConfigurableElement.java
deleted file mode 100644
index fe51f83..0000000
--- a/testsuite/integration/subsystem/src/test/java/org/wildfly/test/feature/pack/elytron/tls/subsystem/common/AbstractConfigurableElement.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2017 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.feature.pack.elytron.tls.subsystem.common;
-
-import static org.wildfly.common.Assert.checkNotNullParamWithNullPointerException;
-
-/**
- * Abstract parent for {@link ConfigurableElement} implementations. It just holds common fields and provides parent for
- * builders.
- *
- * @author Josef Cacek
- */
-public abstract class AbstractConfigurableElement implements ConfigurableElement {
-
- protected final String name;
-
- protected AbstractConfigurableElement(Builder> builder) {
- checkNotNullParamWithNullPointerException("builder", builder);
- this.name = checkNotNullParamWithNullPointerException("builder.name", builder.name);
- }
-
- @Override
- public final String getName() {
- return name;
- }
-
- /**
- * Builder to build {@link AbstractConfigurableElement}.
- */
- public abstract static class Builder> {
- private String name;
-
- protected Builder() {
- }
-
- protected abstract T self();
-
- public final T withName(String name) {
- this.name = name;
- return self();
- }
-
- }
-
-}
diff --git a/testsuite/integration/subsystem/src/test/java/org/wildfly/test/feature/pack/elytron/tls/subsystem/common/ConfigurableElement.java b/testsuite/integration/subsystem/src/test/java/org/wildfly/test/feature/pack/elytron/tls/subsystem/common/ConfigurableElement.java
deleted file mode 100644
index 326c606..0000000
--- a/testsuite/integration/subsystem/src/test/java/org/wildfly/test/feature/pack/elytron/tls/subsystem/common/ConfigurableElement.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2017 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.feature.pack.elytron.tls.subsystem.common;
-
-import org.jboss.as.controller.client.ModelControllerClient;
-import org.jboss.as.test.integration.management.util.CLIWrapper;
-
-/**
- * Interface representing a configurable object in domain model. The implementation has to override at least one of the
- * {@code create(...)} methods and one of the {@code remove(...)} methods.
- *
- * @author Josef Cacek
- */
-public interface ConfigurableElement {
-
- /**
- * Returns name of this element.
- */
- String getName();
-
- /**
- * Creates this element in domain model and it also may create other resources if needed (e.g. external files).
- * Implementation can choose if controller client is used or provided CLI wrapper.
- */
- void create(ModelControllerClient client, CLIWrapper cli) throws Exception;
-
- /**
- * Reverts the changes introdued by {@code create(...)} method(s).
- */
- void remove(ModelControllerClient client, CLIWrapper cli) throws Exception;
-}
diff --git a/testsuite/integration/subsystem/src/test/java/org/wildfly/test/feature/pack/elytron/tls/subsystem/common/CredentialReference.java b/testsuite/integration/subsystem/src/test/java/org/wildfly/test/feature/pack/elytron/tls/subsystem/common/CredentialReference.java
deleted file mode 100644
index b68ad67..0000000
--- a/testsuite/integration/subsystem/src/test/java/org/wildfly/test/feature/pack/elytron/tls/subsystem/common/CredentialReference.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright 2017 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.feature.pack.elytron.tls.subsystem.common;
-
-import static org.apache.commons.lang3.StringUtils.isNotBlank;
-import static org.wildfly.test.security.common.ModelNodeUtil.setIfNotNull;
-
-import org.jboss.dmr.ModelNode;
-import org.wildfly.test.security.common.elytron.CliFragment;
-
-/**
- * Helper class for adding "credential-reference" attributes into CLI commands.
- *
- * @author Josef Cacek
- */
-public class CredentialReference implements CliFragment, ModelNodeConvertable {
-
- public static final CredentialReference EMPTY = CredentialReference.builder().build();
-
- private final String store;
- private final String alias;
- private final String type;
- private final String clearText;
-
- private CredentialReference(Builder builder) {
- this.store = builder.store;
- this.alias = builder.alias;
- this.type = builder.type;
- this.clearText = builder.clearText;
- }
-
- @Override
- public String asString() {
- StringBuilder sb = new StringBuilder();
- if (isNotBlank(alias) || isNotBlank(clearText) || isNotBlank(store) || isNotBlank(type)) {
- sb.append("credential-reference={ ");
- if (isNotBlank(alias)) {
- sb.append(String.format("alias=\"%s\", ", alias));
- }
- if (isNotBlank(store)) {
- sb.append(String.format("store=\"%s\", ", store));
- }
- if (isNotBlank(type)) {
- sb.append(String.format("type=\"%s\", ", type));
- }
- if (isNotBlank(clearText)) {
- sb.append(String.format("clear-text=\"%s\"", clearText));
- }
- sb.append("}, ");
- }
- return sb.toString();
- }
-
- @Override
- public ModelNode toModelNode() {
- if (this == EMPTY) {
- return null;
- }
- final ModelNode node= new ModelNode();
- setIfNotNull(node, "store", store);
- setIfNotNull(node, "alias", alias);
- setIfNotNull(node, "type", type);
- setIfNotNull(node, "clear-text", clearText);
- return node;
- }
-
- /**
- * Creates builder to build {@link CredentialReference}.
- *
- * @return created builder
- */
- public static Builder builder() {
- return new Builder();
- }
-
- /**
- * Builder to build {@link CredentialReference}.
- */
- public static final class Builder {
- private String store;
- private String alias;
- private String type;
- private String clearText;
-
- private Builder() {
- }
-
- public Builder withStore(String store) {
- this.store = store;
- return this;
- }
-
- public Builder withAlias(String alias) {
- this.alias = alias;
- return this;
- }
-
- public Builder withType(String type) {
- this.type = type;
- return this;
- }
-
- public Builder withClearText(String clearText) {
- this.clearText = clearText;
- return this;
- }
-
- public CredentialReference build() {
- return new CredentialReference(this);
- }
- }
-}
diff --git a/testsuite/integration/subsystem/src/test/java/org/wildfly/test/integration/elytron/tls/subsystem/expression/SystemPropertyExpressionTestCase.java b/testsuite/integration/subsystem/src/test/java/org/wildfly/test/integration/elytron/tls/subsystem/expression/SystemPropertyExpressionTestCase.java
new file mode 100644
index 0000000..4945cc6
--- /dev/null
+++ b/testsuite/integration/subsystem/src/test/java/org/wildfly/test/integration/elytron/tls/subsystem/expression/SystemPropertyExpressionTestCase.java
@@ -0,0 +1,248 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2021 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * 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.integration.elytron.tls.subsystem.expression;
+
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ALLOW_RESOURCE_SERVICE_RESTART;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.COMPOSITE;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.CORE_SERVICE;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OPERATION_HEADERS;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OUTCOME;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.PLATFORM_MBEAN;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RESULT;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.STEPS;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUBSYSTEM;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUCCESS;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SYSTEM_PROPERTY;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.TYPE;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.VALUE;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.jboss.as.controller.PathAddress;
+import org.jboss.as.controller.client.ModelControllerClient;
+import org.jboss.as.controller.client.helpers.ClientConstants;
+import org.jboss.as.controller.operations.common.Util;
+import org.jboss.as.test.integration.management.util.ServerReload;
+import org.jboss.as.test.shared.TestSuiteEnvironment;
+import org.jboss.dmr.ModelNode;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.wildfly.core.testrunner.ManagementClient;
+import org.wildfly.core.testrunner.ServerSetup;
+import org.wildfly.core.testrunner.ServerSetupTask;
+import org.wildfly.core.testrunner.UnsuccessfulOperationException;
+import org.wildfly.core.testrunner.WildflyTestRunner;
+import org.wildfly.security.auth.server.IdentityCredentials;
+import org.wildfly.security.credential.PasswordCredential;
+import org.wildfly.security.credential.SecretKeyCredential;
+import org.wildfly.security.credential.store.CredentialStore;
+import org.wildfly.security.credential.store.impl.KeyStoreCredentialStore;
+import org.wildfly.security.encryption.SecretKeyUtil;
+import org.wildfly.security.password.interfaces.ClearPassword;
+
+@RunWith(WildflyTestRunner.class)
+@ServerSetup(SystemPropertyExpressionTestCase.ServerSetup.class)
+public class SystemPropertyExpressionTestCase {
+
+ private static final String CNAME = SystemPropertyExpressionTestCase.class.getSimpleName();
+ private static final String CS_PATH = "target/" + CNAME + ".cs";
+ private static final PathAddress SUBSYSTEM_ADDRESS = PathAddress.pathAddress(SUBSYSTEM, "elytron");
+ private static final PathAddress ENCRYPTION_ADDRESS = SUBSYSTEM_ADDRESS.append("expression", "encryption");
+ private static final String CREDENTIAL_STORE = "credential-store";
+ private static final PathAddress CREDENTIAL_STORE_ADDRESS = SUBSYSTEM_ADDRESS.append(CREDENTIAL_STORE, CNAME);
+ private static final String SECURE_KEY = "RUxZAUsXHVcDh99zAdxGEzTBK1h2qjW+sZg2+37w7ijhDEiJEw==";
+ private static final PathAddress RUNTIME_ADDRESS = PathAddress.pathAddress(CORE_SERVICE, PLATFORM_MBEAN).append(TYPE, "runtime");
+ private static final String PROP = CNAME;
+ private static final String MISSING_PROP = PROP + "-missing";
+
+ private static final String CLEAR_TEXT = "Lorem ipsum dolor sit amet";
+
+ public static final class ServerSetup implements ServerSetupTask {
+ @Override
+ public void setup(ManagementClient managementClient) throws Exception {
+ addCredentialStore(managementClient);
+ managementClient.executeForResult(getAddExpressionEncyryptionOp());
+ }
+
+ @Override
+ public void tearDown(ManagementClient managementClient) throws Exception {
+ try {
+ safeRemoveSystemProperty(managementClient, PROP);
+ safeRemoveSystemProperty(managementClient, MISSING_PROP);
+ removeExpressionEncryption(managementClient.getControllerClient());
+ } finally {
+ removeCredentialStore(managementClient);
+ }
+ }
+
+ private static void addCredentialStore(ManagementClient managementClient) throws GeneralSecurityException, IOException, UnsuccessfulOperationException {
+ cleanCredentialStoreFile();
+ KeyStore ks = KeyStore.getInstance("JCEKS");
+ ks.load(null, null);
+ ks.store(Files.newOutputStream(Paths.get(CS_PATH)), CNAME.toCharArray());
+
+ Map attributes = new HashMap<>();
+ attributes.put("location", CS_PATH);
+ attributes.put("keyStoreType", "JCEKS");
+ attributes.put("modifiable", "true");
+
+ PasswordCredential credential = new PasswordCredential(ClearPassword.createRaw(ClearPassword.ALGORITHM_CLEAR, CNAME.toCharArray()));
+ CredentialStore credentialStore = CredentialStore.getInstance(KeyStoreCredentialStore.KEY_STORE_CREDENTIAL_STORE);
+
+ credentialStore.initialize(attributes,
+ new CredentialStore.CredentialSourceProtectionParameter(IdentityCredentials.NONE.withCredential(credential)));
+ credentialStore.store("securekey", new SecretKeyCredential(SecretKeyUtil.importSecretKey(SECURE_KEY)));
+ credentialStore.flush();
+
+ ModelNode addOp = Util.createAddOperation(CREDENTIAL_STORE_ADDRESS);
+ addOp.get("location").set(CS_PATH);
+ addOp.get("credential-reference", "clear-text").set(CNAME);
+ addOp.get("providers").set("combined-providers");
+ managementClient.executeForResult(addOp);
+ }
+
+ private static void safeRemoveSystemProperty(ManagementClient managementClient, String prop) {
+ try {
+ managementClient.getControllerClient().execute(Util.createRemoveOperation(PathAddress.pathAddress(SYSTEM_PROPERTY, prop)));
+ } catch (Exception e) {
+ e.printStackTrace(System.out);
+ }
+ }
+
+ private static void removeCredentialStore(ManagementClient managementClient) throws UnsuccessfulOperationException {
+ try {
+ ModelNode removeOp = Util.createRemoveOperation(CREDENTIAL_STORE_ADDRESS);
+ managementClient.executeForResult(removeOp);
+ ServerReload.executeReloadAndWaitForCompletion(managementClient.getControllerClient());
+ } finally {
+ cleanCredentialStoreFile();
+ }
+ }
+
+ private static void cleanCredentialStoreFile() {
+ File f = new File(CS_PATH);
+ assert !f.exists() || f.delete();
+ }
+ }
+
+ private static ModelNode getAddExpressionEncyryptionOp() {
+ ModelNode encAdd = Util.createAddOperation(ENCRYPTION_ADDRESS);
+ encAdd.get("default-resolver").set("Default");
+ ModelNode resolvers = encAdd.get("resolvers");
+ ModelNode resolver = new ModelNode();
+ resolver.get("name").set("Default");
+ resolver.get(CREDENTIAL_STORE).set(CNAME);
+ resolver.get("secret-key").set("securekey");
+ resolvers.add(resolver);
+ return encAdd;
+ }
+
+ private static void removeExpressionEncryption(ModelControllerClient modelControllerClient) throws IOException {
+ ModelNode removeOp = Util.createRemoveOperation(ENCRYPTION_ADDRESS);
+ removeOp.get(OPERATION_HEADERS, ALLOW_RESOURCE_SERVICE_RESTART).set(true);
+ assertSuccess(modelControllerClient.execute(removeOp));
+ }
+
+ @Test
+ public void testEncryptedSystemProperties() throws Exception {
+
+ PathAddress propAddress = PathAddress.pathAddress(SYSTEM_PROPERTY, PROP);
+ try (ModelControllerClient client = TestSuiteEnvironment.getModelControllerClient()) {
+
+ assertNull(getSystemProperty(client, PROP));
+ assertNull(getSystemProperty(client, MISSING_PROP));
+
+ ModelNode response = createExpression(client);
+ assertSuccess(response);
+ String expression = response.get(ClientConstants.RESULT).get("expression").asString();
+
+ ModelNode addOp = Util.createAddOperation(propAddress);
+ addOp.get(VALUE).set(expression);
+
+ response = client.execute(addOp);
+ assertSuccess(response);
+
+ assertEquals(CLEAR_TEXT, getSystemProperty(client, PROP));
+
+ removeExpressionEncryption(client);
+
+ // Removing the resolver doesn't affect the system property
+ assertEquals(CLEAR_TEXT, getSystemProperty(client, PROP));
+
+ ModelNode missingAddOp = Util.createAddOperation(PathAddress.pathAddress(SYSTEM_PROPERTY, MISSING_PROP));
+ missingAddOp.get(VALUE).set(expression);
+ // The add should succeed, but the expression would be resolved as if it were a standard expression with a default
+ assertSuccess(client.execute(missingAddOp));
+ assertEquals(expression.substring(expression.indexOf(":Default:"), expression.length() - 1), getSystemProperty(client, MISSING_PROP));
+
+ // Clean up
+ assertSuccess(client.execute(Util.createRemoveOperation(PathAddress.pathAddress(SYSTEM_PROPERTY, MISSING_PROP))));
+ assertNull(getSystemProperty(client, MISSING_PROP));
+
+ // If the prop and the resolver are added in a composite, then proper resolution can occur during op execution
+ ModelNode composite = Util.createEmptyOperation(COMPOSITE, PathAddress.EMPTY_ADDRESS);
+ ModelNode steps = composite.get(STEPS);
+ steps.add(missingAddOp);
+
+ steps.add(getAddExpressionEncyryptionOp());
+
+ assertSuccess(client.execute(composite));
+
+ assertEquals(CLEAR_TEXT, getSystemProperty(client, MISSING_PROP));
+
+ // Test boot behavior. Reload and confirm the property is set.
+ ServerReload.executeReloadAndWaitForCompletion(client);
+
+ assertEquals(CLEAR_TEXT, getSystemProperty(client, PROP));
+
+ }
+ }
+
+ private static ModelNode createExpression(ModelControllerClient client) throws IOException {
+ ModelNode createExpression = Util.createEmptyOperation("create-expression", ENCRYPTION_ADDRESS);
+ createExpression.get("resolver").set("Default");
+ createExpression.get("clear-text").set(CLEAR_TEXT);
+
+ return client.execute(createExpression);
+ }
+
+ private static void assertSuccess(ModelNode response) {
+ if (!response.get(OUTCOME).asString().equals(SUCCESS)) {
+ Assert.fail(response.toJSONString(false));
+ }
+ }
+
+ private static String getSystemProperty(ModelControllerClient client, String property) throws IOException {
+ ModelNode response = client.execute(Util.getReadAttributeOperation(RUNTIME_ADDRESS, "system-properties"));
+ assertSuccess(response);
+ ModelNode val = response.get(RESULT, property);
+ return val.isDefined() ? val.asString() : null;
+ }
+}
diff --git a/testsuite/integration/subsystem/src/test/java/org/wildfly/test/feature/pack/elytron/tls/subsystem/sanity/SubsystemSanityTestCase.java b/testsuite/integration/subsystem/src/test/java/org/wildfly/test/integration/elytron/tls/subsystem/sanity/ElytronTlsSanityTestCase.java
similarity index 90%
rename from testsuite/integration/subsystem/src/test/java/org/wildfly/test/feature/pack/elytron/tls/subsystem/sanity/SubsystemSanityTestCase.java
rename to testsuite/integration/subsystem/src/test/java/org/wildfly/test/integration/elytron/tls/subsystem/sanity/ElytronTlsSanityTestCase.java
index 82ebc79..c12bb23 100644
--- a/testsuite/integration/subsystem/src/test/java/org/wildfly/test/feature/pack/elytron/tls/subsystem/sanity/SubsystemSanityTestCase.java
+++ b/testsuite/integration/subsystem/src/test/java/org/wildfly/test/integration/elytron/tls/subsystem/sanity/ElytronTlsSanityTestCase.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.wildfly.test.feature.pack.elytron.tls.subsystem.sanity;
+package org.wildfly.test.integration.elytron.tls.subsystem.sanity;
import javax.inject.Inject;
@@ -33,7 +33,7 @@
* @author Kabir Khan
*/
@RunWith(Arquillian.class)
-public class SubsystemSanityTestCase {
+public class ElytronTlsSanityTestCase {
@Inject
@ExampleQualifier
@@ -43,7 +43,7 @@ public class SubsystemSanityTestCase {
public static WebArchive getDeployment() {
final WebArchive webArchive = ShrinkWrap.create(WebArchive.class, "sanity-test.war")
.addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml")
- .addPackage(SubsystemSanityTestCase.class.getPackage());
+ .addPackage(ElytronTlsSanityTestCase.class.getPackage());
return webArchive;
}
diff --git a/testsuite/integration/subsystem/src/test/java/org/wildfly/test/feature/pack/elytron/tls/subsystem/tls/OpenSslTlsTestCase.java b/testsuite/integration/subsystem/src/test/java/org/wildfly/test/integration/elytron/tls/subsystem/tls/OpenSslTlsTestCase.java
similarity index 94%
rename from testsuite/integration/subsystem/src/test/java/org/wildfly/test/feature/pack/elytron/tls/subsystem/tls/OpenSslTlsTestCase.java
rename to testsuite/integration/subsystem/src/test/java/org/wildfly/test/integration/elytron/tls/subsystem/tls/OpenSslTlsTestCase.java
index 2e47ca1..7832219 100644
--- a/testsuite/integration/subsystem/src/test/java/org/wildfly/test/feature/pack/elytron/tls/subsystem/tls/OpenSslTlsTestCase.java
+++ b/testsuite/integration/subsystem/src/test/java/org/wildfly/test/integration/elytron/tls/subsystem/tls/OpenSslTlsTestCase.java
@@ -15,7 +15,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
-package org.wildfly.test.feature.pack.elytron.tls.subsystem.tls;
+package org.wildfly.test.integration.elytron.tls.subsystem.tls;
import static org.jboss.as.controller.client.helpers.ClientConstants.CONTENT;
import static org.jboss.as.controller.client.helpers.ClientConstants.DEPLOYMENT;
@@ -74,21 +74,21 @@
import org.wildfly.core.testrunner.ManagementClient;
import org.wildfly.core.testrunner.ServerSetupTask;
import org.wildfly.core.testrunner.WildflyTestRunner;
-import org.wildfly.extension.elytron.ElytronExtension;
+import org.wildfly.extension.elytron.tls.subsystem.ElytronTlsExtension;
import org.wildfly.openssl.OpenSSLProvider;
import org.wildfly.security.ssl.CipherSuiteSelector;
import org.wildfly.security.ssl.ProtocolSelector;
import org.wildfly.security.ssl.SSLContextBuilder;
import org.wildfly.security.ssl.test.util.CAGenerationTool;
import org.wildfly.security.ssl.test.util.CAGenerationTool.Identity;
-import org.wildfly.test.feature.pack.elytron.tls.subsystem.common.TestRunnerConfigSetupTask;
-import org.wildfly.test.feature.pack.elytron.tls.subsystem.common.CliPath;
-import org.wildfly.test.feature.pack.elytron.tls.subsystem.common.ConfigurableElement;
-import org.wildfly.test.feature.pack.elytron.tls.subsystem.common.SimpleServerSslContext;
-import org.wildfly.test.feature.pack.elytron.tls.subsystem.common.CredentialReference;
-import org.wildfly.test.feature.pack.elytron.tls.subsystem.common.SimpleKeyManager;
-import org.wildfly.test.feature.pack.elytron.tls.subsystem.common.SimpleKeyStore;
-import org.wildfly.test.feature.pack.elytron.tls.subsystem.common.SimpleTrustManager;
+import org.wildfly.test.security.common.TestRunnerConfigSetupTask;
+import org.wildfly.test.security.common.elytron.ConfigurableElement;
+import org.wildfly.test.security.common.elytron.CredentialReference;
+import org.wildfly.test.security.common.elytron.tls.subsystem.SimpleTlsKeyManager;
+import org.wildfly.test.security.common.elytron.tls.subsystem.SimpleTlsKeyStore;
+import org.wildfly.test.security.common.elytron.tls.subsystem.SimpleTlsServerSslContext;
+import org.wildfly.test.security.common.elytron.tls.subsystem.SimpleTlsTrustManager;
+import org.wildfly.test.security.common.elytron.tls.subsystem.CliPath;
import org.wildfly.test.undertow.UndertowSSLService;
import org.wildfly.test.undertow.UndertowSSLServiceActivator;
import org.wildfly.test.undertow.UndertowServiceActivator;
@@ -113,7 +113,7 @@ public class OpenSslTlsTestCase {
private static final String SERVER_TRUST_MANAGER_NAME = "serverTM";
private static final String SERVER_SSL_CONTEXT_NAME = "test-context";
- private static final PathAddress ROOT_ADDRESS = PathAddress.pathAddress(SUBSYSTEM, ElytronExtension.SUBSYSTEM_NAME);
+ private static final PathAddress ROOT_ADDRESS = PathAddress.pathAddress(SUBSYSTEM, ElytronTlsExtension.SUBSYSTEM_NAME);
private static final PathAddress SERVER_SSL_CONTEXT_ADDRESS = ROOT_ADDRESS.append("server-ssl-context", SERVER_SSL_CONTEXT_NAME);
private static final Pattern OPENSSL_TLSv13_PATTERN = Pattern.compile("^(TLS_AES_128_GCM_SHA256|TLS_AES_256_GCM_SHA384|TLS_CHACHA20_POLY1305_SHA256|TLS_AES_128_CCM_SHA256|TLS_AES_128_CCM_8_SHA256)$");
@@ -199,7 +199,7 @@ protected ConfigurableElement[] getConfigurableElements() {
.build();
// KeyStores
- final SimpleKeyStore.Builder ksCommon = SimpleKeyStore.builder()
+ final SimpleTlsKeyStore.Builder ksCommon = SimpleTlsKeyStore.builder()
.withType("JKS")
.withCredentialReference(credentialReference);
elements.add(ksCommon.withName(SERVER_KEY_STORE_NAME)
@@ -214,19 +214,19 @@ protected ConfigurableElement[] getConfigurableElements() {
.build());
// Key and Trust Managers
- elements.add(SimpleKeyManager.builder()
+ elements.add(SimpleTlsKeyManager.builder()
.withName(SERVER_KEY_MANAGER_NAME)
.withCredentialReference(credentialReference)
.withKeyStore(SERVER_KEY_STORE_NAME)
.build());
elements.add(
- SimpleTrustManager.builder()
+ SimpleTlsTrustManager.builder()
.withName(SERVER_TRUST_MANAGER_NAME)
.withKeyStore(SERVER_TRUST_STORE_NAME)
.build());
// SSLContext with OpenSSL provider
- elements.add(SimpleServerSslContext.builder()
+ elements.add(SimpleTlsServerSslContext.builder()
.withName(SERVER_SSL_CONTEXT_NAME)
.withKeyManagers(SERVER_KEY_MANAGER_NAME)
.withTrustManagers(SERVER_TRUST_MANAGER_NAME)
@@ -235,7 +235,7 @@ protected ConfigurableElement[] getConfigurableElements() {
.withCipherSuiteNames("TLS_AES_256_GCM_SHA384:TLS_AES_128_CCM_8_SHA256")
.build());
- return elements.toArray(new ConfigurableElement[elements.size()]);
+ return elements.toArray(new ConfigurableElement[0]);
}
@Override
diff --git a/testsuite/integration/subsystem/src/test/java/org/wildfly/test/integration/elytron/tls/subsystem/tls/ServerSslSniContextTestCase.java b/testsuite/integration/subsystem/src/test/java/org/wildfly/test/integration/elytron/tls/subsystem/tls/ServerSslSniContextTestCase.java
new file mode 100644
index 0000000..bf894a1
--- /dev/null
+++ b/testsuite/integration/subsystem/src/test/java/org/wildfly/test/integration/elytron/tls/subsystem/tls/ServerSslSniContextTestCase.java
@@ -0,0 +1,90 @@
+/*
+ * 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.integration.elytron.tls.subsystem.tls;
+
+import static org.hamcrest.CoreMatchers.containsString;
+
+import org.hamcrest.MatcherAssert;
+import org.jboss.as.test.integration.management.util.CLIWrapper;
+import org.jboss.as.test.integration.management.util.ServerReload;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.wildfly.core.testrunner.ServerSetup;
+import org.wildfly.core.testrunner.WildflyTestRunner;
+
+@Ignore("SNI is not implemented yet")
+@ServerSetup(ServerReload.SetupTask.class)
+@RunWith(WildflyTestRunner.class)
+public class ServerSslSniContextTestCase {
+ CLIWrapper cli;
+
+ @Before
+ public void setup() throws Exception {
+ cli = new CLIWrapper(true);
+ // add server-ssl-sni-context
+ cli.sendLine("/subsystem=elytron-tls/key-store=exampleKeyStore:add(path=server.keystore,relative-to=jboss.server.config.dir,credential-reference={clear-text=\"keystore_password\"},type=JKS)");
+ cli.sendLine("/subsystem=elytron-tls/key-manager=exampleKeyManager:add(key-store=exampleKeyStore,alias-filter=server,credential-reference={clear-text=\"key_password\"})");
+ cli.sendLine("/subsystem=elytron-tls/server-ssl-context=exampleSslContext:add(key-manager=exampleKeyManager)");
+ cli.sendLine("/subsystem=elytron-tls/server-ssl-sni-context=exampleSslSniContext:add(default-ssl-context=exampleSslContext");
+ }
+
+ @After
+ public void cleanup() throws Exception {
+ removeTestResources();
+ cli.close();
+ }
+
+ @Test
+ public void testInvalidHostContextMapValue() {
+ boolean success = cli.sendLine("/subsystem=elytron-tls/server-ssl-sni-context=exampleSslSniContext:write-attribute(name=host-context-map,value={\"\\\\?.invalid.com\"=exampleSslContext})", true);
+ Assert.assertFalse(success);
+ MatcherAssert.assertThat("Wrong error message", cli.readOutput(), containsString("Invalid value of host context map"));
+ success = cli.sendLine("/subsystem=elytron-tls/server-ssl-sni-context=exampleSslSniContext:write-attribute(name=host-context-map,value={\"invalid\\\\.\\\\.example.com\"=exampleSslContext})", true);
+ Assert.assertFalse(success);
+ MatcherAssert.assertThat("Wrong error message", cli.readOutput(), containsString("Invalid value of host context map"));
+ success = cli.sendLine("/subsystem=elytron-tls/server-ssl-sni-context=exampleSslSniContext:write-attribute(name=host-context-map,value={\"*\\.invalid.com\"=exampleSslContext})", true);
+ Assert.assertFalse(success);
+ MatcherAssert.assertThat("Wrong error message", cli.readOutput(), containsString("Invalid value of host context map"));
+ success = cli.sendLine("/subsystem=elytron-tls/server-ssl-sni-context=exampleSslSniContext:write-attribute(name=host-context-map,value={\"invalid.com-\"=exampleSslContext})", true);
+ Assert.assertFalse(success);
+ MatcherAssert.assertThat("Wrong error message", cli.readOutput(), containsString("Invalid value of host context map"));
+ success = cli.sendLine("/subsystem=elytron-tls/server-ssl-sni-context=exampleSslSniContext:write-attribute(name=host-context-map,value={\"invalid.com\\\\.\"=exampleSslContext})", true);
+ Assert.assertFalse(success);
+ MatcherAssert.assertThat("Wrong error message", cli.readOutput(), containsString("Invalid value of host context map"));
+ }
+
+ @Test
+ public void testValidHostContextMapValue() {
+ boolean success = cli.sendLine("/subsystem=elytron-tls/server-ssl-sni-context=exampleSslSniContext:write-attribute(name=host-context-map,value={\"..valid\\\\.example\\\\.com\"=exampleSslContext})", true);
+ Assert.assertTrue(success);
+ success = cli.sendLine("/subsystem=elytron-tls/server-ssl-sni-context=exampleSslSniContext:write-attribute(name=host-context-map,value={\"valid\\\\.example\\\\.com\"=exampleSslContext})", true);
+ Assert.assertTrue(success);
+ success = cli.sendLine("/subsystem=elytron-tls/server-ssl-sni-context=exampleSslSniContext:write-attribute(name=host-context-map,value={\"[^.]*\\\\.example\\\\.com\"=exampleSslContext})", true);
+ Assert.assertTrue(success);
+ }
+
+ private void removeTestResources() {
+ cli.sendLine("/subsystem=elytron-tls/server-ssl-sni-context=exampleSslSniContext:remove");
+ cli.sendLine("/subsystem=elytron-tls/server-ssl-context=exampleSslContext:remove");
+ cli.sendLine("/subsystem=elytron-tls/key-manager=exampleKeyManager:remove");
+ cli.sendLine("/subsystem=elytron-tls/key-store=exampleKeyStore:remove");
+ }
+}
diff --git a/testsuite/integration/subsystem/src/test/java/org/wildfly/test/feature/pack/elytron/tls/subsystem/common/TestRunnerConfigSetupTask.java b/testsuite/integration/subsystem/src/test/java/org/wildfly/test/security/common/TestRunnerConfigSetupTask.java
similarity index 95%
rename from testsuite/integration/subsystem/src/test/java/org/wildfly/test/feature/pack/elytron/tls/subsystem/common/TestRunnerConfigSetupTask.java
rename to testsuite/integration/subsystem/src/test/java/org/wildfly/test/security/common/TestRunnerConfigSetupTask.java
index 6d629cd..92cb327 100644
--- a/testsuite/integration/subsystem/src/test/java/org/wildfly/test/feature/pack/elytron/tls/subsystem/common/TestRunnerConfigSetupTask.java
+++ b/testsuite/integration/subsystem/src/test/java/org/wildfly/test/security/common/TestRunnerConfigSetupTask.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.wildfly.test.feature.pack.elytron.tls.subsystem.common;
+package org.wildfly.test.security.common;
import java.util.Arrays;
import java.util.ListIterator;
@@ -25,6 +25,7 @@
import org.jboss.logging.Logger;
import org.wildfly.core.testrunner.ManagementClient;
import org.wildfly.core.testrunner.ServerSetupTask;
+import org.wildfly.test.security.common.elytron.ConfigurableElement;
/**
* WildFly TestRunner ServerSetupTask version of AbstractConfigSetupTask.
@@ -49,7 +50,7 @@ public void tearDown(final ManagementClient managementClient) throws Exception {
/**
* Creates configuration elements (provided by implementation of {@link #getConfigurableElements()} method) and calls
- * {@link ConfigurableElement#create(ModelControllerClient, CLIWrapper)} for them.
+ * {@link ConfigurableElement#create(CLIWrapper)} for them.
*/
protected void setup(final ModelControllerClient modelControllerClient) throws Exception {
configurableElements = getConfigurableElements();
@@ -70,7 +71,7 @@ protected void setup(final ModelControllerClient modelControllerClient) throws E
}
/**
- * Reverts configuration changes done by {@link #setup(ModelControllerClient)} method - i.e. calls {@link ConfigurableElement#remove(ModelControllerClient, CLIWrapper)} method
+ * Reverts configuration changes done by {@link #setup(ModelControllerClient)} method - i.e. calls {@link ConfigurableElement#remove(CLIWrapper)} method
* on instances provided by {@link #getConfigurableElements()} (in reverse order).
*/
protected void tearDown(ModelControllerClient modelControllerClient) throws Exception {
diff --git a/testsuite/integration/subsystem/src/test/java/org/wildfly/test/feature/pack/elytron/tls/subsystem/common/CliPath.java b/testsuite/integration/subsystem/src/test/java/org/wildfly/test/security/common/elytron/tls/subsystem/CliPath.java
similarity index 97%
rename from testsuite/integration/subsystem/src/test/java/org/wildfly/test/feature/pack/elytron/tls/subsystem/common/CliPath.java
rename to testsuite/integration/subsystem/src/test/java/org/wildfly/test/security/common/elytron/tls/subsystem/CliPath.java
index 0aeb2ce..e2af5ca 100644
--- a/testsuite/integration/subsystem/src/test/java/org/wildfly/test/feature/pack/elytron/tls/subsystem/common/CliPath.java
+++ b/testsuite/integration/subsystem/src/test/java/org/wildfly/test/security/common/elytron/tls/subsystem/CliPath.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.wildfly.test.feature.pack.elytron.tls.subsystem.common;
+package org.wildfly.test.security.common.elytron.tls.subsystem;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.jboss.as.test.shared.CliUtils.escapePath;
diff --git a/testsuite/integration/subsystem/src/test/java/org/wildfly/test/feature/pack/elytron/tls/subsystem/common/SimpleKeyManager.java b/testsuite/integration/subsystem/src/test/java/org/wildfly/test/security/common/elytron/tls/subsystem/SimpleTlsKeyManager.java
similarity index 70%
rename from testsuite/integration/subsystem/src/test/java/org/wildfly/test/feature/pack/elytron/tls/subsystem/common/SimpleKeyManager.java
rename to testsuite/integration/subsystem/src/test/java/org/wildfly/test/security/common/elytron/tls/subsystem/SimpleTlsKeyManager.java
index cd3a75b..7d29d52 100644
--- a/testsuite/integration/subsystem/src/test/java/org/wildfly/test/feature/pack/elytron/tls/subsystem/common/SimpleKeyManager.java
+++ b/testsuite/integration/subsystem/src/test/java/org/wildfly/test/security/common/elytron/tls/subsystem/SimpleTlsKeyManager.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.wildfly.test.feature.pack.elytron.tls.subsystem.common;
+package org.wildfly.test.security.common.elytron.tls.subsystem;
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
import static org.wildfly.common.Assert.checkNotNullParamWithNullPointerException;
@@ -22,18 +22,21 @@
import org.jboss.as.controller.client.ModelControllerClient;
import org.jboss.as.test.integration.management.util.CLIWrapper;
+import org.wildfly.test.security.common.elytron.AbstractConfigurableElement;
+import org.wildfly.test.security.common.elytron.CredentialReference;
/**
- * Elytron key-manager configuration implementation.
+ * Elytron TLS key-manager configuration implementation.
*
* @author Josef Cacek
+ * @author Cameron Rodriguez
*/
-public class SimpleKeyManager extends AbstractConfigurableElement {
+public class SimpleTlsKeyManager extends AbstractConfigurableElement {
private final String keyStore;
private final CredentialReference credentialReference;
- private SimpleKeyManager(Builder builder) {
+ private SimpleTlsKeyManager(Builder builder) {
super(builder);
this.keyStore = checkNotNullParamWithNullPointerException("builder.keyStore", builder.keyStore);
this.credentialReference = defaultIfNull(builder.credentialReference, CredentialReference.EMPTY);
@@ -41,19 +44,19 @@ private SimpleKeyManager(Builder builder) {
@Override
public void create(ModelControllerClient client, CLIWrapper cli) throws Exception {
- // /subsystem=elytron/key-manager=httpsKM:add(key-store=httpsKS,algorithm="SunX509",credential-reference={clear-text=secret})
+ // /subsystem=elytron-tls/key-manager=httpsKM:add(key-store=httpsKS,algorithm="SunX509",credential-reference={clear-text=secret})
- cli.sendLine(String.format("/subsystem=elytron/key-manager=%s:add(key-store=\"%s\",algorithm=\"%s\", %s)", name,
+ cli.sendLine(String.format("/subsystem=elytron-tls/key-manager=%s:add(key-store=\"%s\",algorithm=\"%s\", %s)", name,
keyStore, KeyManagerFactory.getDefaultAlgorithm(), credentialReference.asString()));
}
@Override
public void remove(ModelControllerClient client, CLIWrapper cli) throws Exception {
- cli.sendLine(String.format("/subsystem=elytron/key-manager=%s:remove()", name));
+ cli.sendLine(String.format("/subsystem=elytron-tls/key-manager=%s:remove()", name));
}
/**
- * Creates builder to build {@link SimpleKeyManager}.
+ * Creates builder to build {@link SimpleTlsKeyManager}.
*
* @return created builder
*/
@@ -62,7 +65,7 @@ public static Builder builder() {
}
/**
- * Builder to build {@link SimpleKeyManager}.
+ * Builder to build {@link SimpleTlsKeyManager}.
*/
public static final class Builder extends AbstractConfigurableElement.Builder {
private String keyStore;
@@ -81,8 +84,8 @@ public Builder withCredentialReference(CredentialReference credentialReference)
return this;
}
- public SimpleKeyManager build() {
- return new SimpleKeyManager(this);
+ public SimpleTlsKeyManager build() {
+ return new SimpleTlsKeyManager(this);
}
@Override
diff --git a/testsuite/integration/subsystem/src/test/java/org/wildfly/test/feature/pack/elytron/tls/subsystem/common/SimpleKeyStore.java b/testsuite/integration/subsystem/src/test/java/org/wildfly/test/security/common/elytron/tls/subsystem/SimpleTlsKeyStore.java
similarity index 71%
rename from testsuite/integration/subsystem/src/test/java/org/wildfly/test/feature/pack/elytron/tls/subsystem/common/SimpleKeyStore.java
rename to testsuite/integration/subsystem/src/test/java/org/wildfly/test/security/common/elytron/tls/subsystem/SimpleTlsKeyStore.java
index 934ff58..a002974 100644
--- a/testsuite/integration/subsystem/src/test/java/org/wildfly/test/feature/pack/elytron/tls/subsystem/common/SimpleKeyStore.java
+++ b/testsuite/integration/subsystem/src/test/java/org/wildfly/test/security/common/elytron/tls/subsystem/SimpleTlsKeyStore.java
@@ -13,26 +13,29 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.wildfly.test.feature.pack.elytron.tls.subsystem.common;
+package org.wildfly.test.security.common.elytron.tls.subsystem;
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
import org.jboss.as.controller.client.ModelControllerClient;
import org.jboss.as.test.integration.management.util.CLIWrapper;
+import org.wildfly.test.security.common.elytron.AbstractConfigurableElement;
+import org.wildfly.test.security.common.elytron.CredentialReference;
/**
- * Elytron key-store configuration implementation.
+ * Elytron TLS key-store configuration implementation.
*
* @author Josef Cacek
+ * @author Cameron Rodriguez
*/
-public class SimpleKeyStore extends AbstractConfigurableElement {
+public class SimpleTlsKeyStore extends AbstractConfigurableElement {
private final CliPath path;
private final CredentialReference credentialReference;
private final String type;
private final boolean required;
- private SimpleKeyStore(Builder builder) {
+ private SimpleTlsKeyStore(Builder builder) {
super(builder);
this.path = defaultIfNull(builder.path, CliPath.EMPTY);
this.credentialReference = defaultIfNull(builder.credentialReference, CredentialReference.EMPTY);
@@ -42,19 +45,19 @@ private SimpleKeyStore(Builder builder) {
@Override
public void create(ModelControllerClient client, CLIWrapper cli) throws Exception {
- // /subsystem=elytron/key-store=httpsKS:add(path=keystore.jks,relative-to=jboss.server.config.dir,
+ // /subsystem=elytron-tls/key-store=httpsKS:add(path=keystore.jks,relative-to=jboss.server.config.dir,
// credential-reference={clear-text=secret},type=JKS,required=false)
- cli.sendLine(String.format("/subsystem=elytron/key-store=%s:add(%s%stype=\"%s\",required=%s)", name, path.asString(),
- credentialReference.asString(), type, Boolean.toString(required)));
+ cli.sendLine(String.format("/subsystem=elytron-tls/key-store=%s:add(%s%stype=\"%s\",required=%s)", name, path.asString(),
+ credentialReference.asString(), type, required));
}
@Override
public void remove(ModelControllerClient client, CLIWrapper cli) throws Exception {
- cli.sendLine(String.format("/subsystem=elytron/key-store=%s:remove()", name));
+ cli.sendLine(String.format("/subsystem=elytron-tls/key-store=%s:remove()", name));
}
/**
- * Creates builder to build {@link SimpleKeyStore}.
+ * Creates builder to build {@link SimpleTlsKeyStore}.
*
* @return created builder
*/
@@ -63,7 +66,7 @@ public static Builder builder() {
}
/**
- * Builder to build {@link SimpleKeyStore}.
+ * Builder to build {@link SimpleTlsKeyStore}.
*/
public static final class Builder extends AbstractConfigurableElement.Builder {
private CliPath path;
@@ -94,8 +97,8 @@ public Builder withRequired(boolean required) {
return this;
}
- public SimpleKeyStore build() {
- return new SimpleKeyStore(this);
+ public SimpleTlsKeyStore build() {
+ return new SimpleTlsKeyStore(this);
}
@Override
diff --git a/testsuite/integration/subsystem/src/test/java/org/wildfly/test/feature/pack/elytron/tls/subsystem/common/SimpleServerSslContext.java b/testsuite/integration/subsystem/src/test/java/org/wildfly/test/security/common/elytron/tls/subsystem/SimpleTlsServerSslContext.java
similarity index 79%
rename from testsuite/integration/subsystem/src/test/java/org/wildfly/test/feature/pack/elytron/tls/subsystem/common/SimpleServerSslContext.java
rename to testsuite/integration/subsystem/src/test/java/org/wildfly/test/security/common/elytron/tls/subsystem/SimpleTlsServerSslContext.java
index 74c98b8..def7934 100644
--- a/testsuite/integration/subsystem/src/test/java/org/wildfly/test/feature/pack/elytron/tls/subsystem/common/SimpleServerSslContext.java
+++ b/testsuite/integration/subsystem/src/test/java/org/wildfly/test/security/common/elytron/tls/subsystem/SimpleTlsServerSslContext.java
@@ -13,35 +13,35 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.wildfly.test.feature.pack.elytron.tls.subsystem.common;
+package org.wildfly.test.security.common.elytron.tls.subsystem;
import java.util.StringJoiner;
import org.apache.commons.lang3.StringUtils;
import org.jboss.as.controller.client.ModelControllerClient;
import org.jboss.as.test.integration.management.util.CLIWrapper;
+import org.wildfly.test.security.common.elytron.AbstractConfigurableElement;
/**
- * Elytron server-ssl-context configuration implementation.
+ * Elytron TLS server-ssl-context configuration implementation.
*
* @author Josef Cacek
+ * @author Cameron Rodriguez
*/
-public class SimpleServerSslContext extends AbstractConfigurableElement {
+public class SimpleTlsServerSslContext extends AbstractConfigurableElement {
private final String keyManager;
private final String trustManager;
- private final String securityDomain;
private final String[] protocols;
private final boolean needClientAuth;
private final Boolean authenticationOptional;
private final String providers;
private final String cipherSuiteNames;
- private SimpleServerSslContext(Builder builder) {
+ private SimpleTlsServerSslContext(Builder builder) {
super(builder);
this.keyManager = builder.keyManager;
this.trustManager = builder.trustManager;
- this.securityDomain = builder.securityDomain;
this.protocols = builder.protocols;
this.needClientAuth = builder.needClientAuth;
this.authenticationOptional = builder.authenticationOptional;
@@ -51,9 +51,9 @@ private SimpleServerSslContext(Builder builder) {
@Override
public void create(ModelControllerClient client, CLIWrapper cli) throws Exception {
- // /subsystem=elytron/server-ssl-context=twoWaySSC:add(key-manager=twoWayKM,protocols=["TLSv1.2"],
+ // /subsystem=elytron-tls/server-ssl-context=twoWaySSC:add(key-manager=twoWayKM,protocols=["TLSv1.2"],
// trust-manager=twoWayTM,security-domain=test,need-client-auth=true)
- StringBuilder sb = new StringBuilder("/subsystem=elytron/server-ssl-context=").append(name).append(":add(");
+ StringBuilder sb = new StringBuilder("/subsystem=elytron-tls/server-ssl-context=").append(name).append(":add(");
if (StringUtils.isNotBlank(keyManager)) {
sb.append("key-manager=\"").append(keyManager).append("\", ");
}
@@ -64,14 +64,11 @@ public void create(ModelControllerClient client, CLIWrapper cli) throws Exceptio
joiner.add(s1);
}
sb.append("protocols=[")
- .append(joiner.toString()).append("], ");
+ .append(joiner).append("], ");
}
if (StringUtils.isNotBlank(trustManager)) {
sb.append("trust-manager=\"").append(trustManager).append("\", ");
}
- if (StringUtils.isNotBlank(securityDomain)) {
- sb.append("security-domain=\"").append(securityDomain).append("\", ");
- }
if (authenticationOptional != null) {
sb.append("authentication-optional=").append(authenticationOptional).append(", ");
}
@@ -87,11 +84,11 @@ public void create(ModelControllerClient client, CLIWrapper cli) throws Exceptio
@Override
public void remove(ModelControllerClient client, CLIWrapper cli) throws Exception {
- cli.sendLine(String.format("/subsystem=elytron/server-ssl-context=%s:remove()", name));
+ cli.sendLine(String.format("/subsystem=elytron-tls/server-ssl-context=%s:remove()", name));
}
/**
- * Creates builder to build {@link SimpleServerSslContext}.
+ * Creates builder to build {@link SimpleTlsServerSslContext}.
*
* @return created builder
*/
@@ -100,12 +97,11 @@ public static Builder builder() {
}
/**
- * Builder to build {@link SimpleServerSslContext}.
+ * Builder to build {@link SimpleTlsServerSslContext}.
*/
public static final class Builder extends AbstractConfigurableElement.Builder {
private String keyManager;
private String trustManager;
- private String securityDomain;
private String[] protocols;
private boolean needClientAuth;
private Boolean authenticationOptional;
@@ -125,11 +121,6 @@ public Builder withTrustManagers(String trustManagers) {
return this;
}
- public Builder withSecurityDomain(String securityDomain) {
- this.securityDomain = securityDomain;
- return this;
- }
-
public Builder withProtocols(String... protocols) {
this.protocols = protocols;
return this;
@@ -155,8 +146,8 @@ public Builder withCipherSuiteNames(String cipherSuiteNames) {
return this;
}
- public SimpleServerSslContext build() {
- return new SimpleServerSslContext(this);
+ public SimpleTlsServerSslContext build() {
+ return new SimpleTlsServerSslContext(this);
}
@Override
diff --git a/testsuite/integration/subsystem/src/test/java/org/wildfly/test/feature/pack/elytron/tls/subsystem/common/SimpleTrustManager.java b/testsuite/integration/subsystem/src/test/java/org/wildfly/test/security/common/elytron/tls/subsystem/SimpleTlsTrustManager.java
similarity index 66%
rename from testsuite/integration/subsystem/src/test/java/org/wildfly/test/feature/pack/elytron/tls/subsystem/common/SimpleTrustManager.java
rename to testsuite/integration/subsystem/src/test/java/org/wildfly/test/security/common/elytron/tls/subsystem/SimpleTlsTrustManager.java
index d101f60..18e6a99 100644
--- a/testsuite/integration/subsystem/src/test/java/org/wildfly/test/feature/pack/elytron/tls/subsystem/common/SimpleTrustManager.java
+++ b/testsuite/integration/subsystem/src/test/java/org/wildfly/test/security/common/elytron/tls/subsystem/SimpleTlsTrustManager.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.wildfly.test.feature.pack.elytron.tls.subsystem.common;
+package org.wildfly.test.security.common.elytron.tls.subsystem;
import static org.wildfly.common.Assert.checkNotNullParamWithNullPointerException;
@@ -21,36 +21,38 @@
import org.jboss.as.controller.client.ModelControllerClient;
import org.jboss.as.test.integration.management.util.CLIWrapper;
+import org.wildfly.test.security.common.elytron.AbstractConfigurableElement;
/**
- * Elytron trust-managers configuration implementation.
+ * Elytron TLS trust-managers configuration implementation.
*
* @author Josef Cacek
+ * @author Cameron Rodriguez
*/
-public class SimpleTrustManager extends AbstractConfigurableElement {
+public class SimpleTlsTrustManager extends AbstractConfigurableElement {
private final String keyStore;
- private SimpleTrustManager(Builder builder) {
+ private SimpleTlsTrustManager(Builder builder) {
super(builder);
this.keyStore = checkNotNullParamWithNullPointerException("builder.keyStore", builder.keyStore);
}
@Override
public void create(ModelControllerClient client, CLIWrapper cli) throws Exception {
- // /subsystem=elytron/trust-manager=twoWayTM:add(key-store=twoWayTS,algorithm="SunX509")
+ // /subsystem=elytron-tls/trust-manager=twoWayTM:add(key-store=twoWayTS,algorithm="SunX509")
- cli.sendLine(String.format("/subsystem=elytron/trust-manager=%s:add(key-store=\"%s\",algorithm=\"%s\")", name,
+ cli.sendLine(String.format("/subsystem=elytron-tls/trust-manager=%s:add(key-store=\"%s\",algorithm=\"%s\")", name,
keyStore, KeyManagerFactory.getDefaultAlgorithm()));
}
@Override
public void remove(ModelControllerClient client, CLIWrapper cli) throws Exception {
- cli.sendLine(String.format("/subsystem=elytron/trust-manager=%s:remove()", name));
+ cli.sendLine(String.format("/subsystem=elytron-tls/trust-manager=%s:remove()", name));
}
/**
- * Creates builder to build {@link SimpleTrustManager}.
+ * Creates builder to build {@link SimpleTlsTrustManager}.
*
* @return created builder
*/
@@ -59,7 +61,7 @@ public static Builder builder() {
}
/**
- * Builder to build {@link SimpleTrustManager}.
+ * Builder to build {@link SimpleTlsTrustManager}.
*/
public static final class Builder extends AbstractConfigurableElement.Builder {
private String keyStore;
@@ -72,8 +74,8 @@ public Builder withKeyStore(String keyStore) {
return this;
}
- public SimpleTrustManager build() {
- return new SimpleTrustManager(this);
+ public SimpleTlsTrustManager build() {
+ return new SimpleTlsTrustManager(this);
}
@Override
diff --git a/testsuite/pom.xml b/testsuite/pom.xml
index 3f254d4..d166d54 100644
--- a/testsuite/pom.xml
+++ b/testsuite/pom.xml
@@ -96,7 +96,6 @@
none
- -Djboss.dist=${jboss.dist}
-Djava.io.tmpdir=${basedir}/target