Skip to content

Commit

Permalink
Merge pull request #2949 from fjuma/WFCORE-3305
Browse files Browse the repository at this point in the history
[WFCORE-3305][WFCORE-3425] Add more runtime operations to the Elytron key-store resource for advanced KeyStore manipulation
  • Loading branch information
bstansberry committed Feb 12, 2018
2 parents ee6df94 + 1b4ef35 commit 7e5735e
Show file tree
Hide file tree
Showing 17 changed files with 1,560 additions and 40 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ public void registerChildren(ManagementResourceRegistration resourceRegistration
resourceRegistration.registerSubModel(SaslServerDefinitions.getServiceLoaderSaslServerFactoryDefinition());

// TLS Building Blocks
resourceRegistration.registerSubModel(ModifiableKeyStoreDecorator.wrap(new KeyStoreDefinition()));
resourceRegistration.registerSubModel(AdvancedModifiableKeyStoreDecorator.wrap(new KeyStoreDefinition()));
resourceRegistration.registerSubModel(ModifiableKeyStoreDecorator.wrap(new LdapKeyStoreDefinition()));
resourceRegistration.registerSubModel(ModifiableKeyStoreDecorator.wrap(new FilteringKeyStoreDefinition()));
resourceRegistration.registerSubModel(SSLDefinitions.getKeyManagerDefinition());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ interface ElytronDescriptionConstants {
String CERTIFICATE_TYPE = "certificate-type";
String CERTIFICATE_REVOCATION_LIST = "certificate-revocation-list";
String CHAINED_PRINCIPAL_TRANSFORMER = "chained-principal-transformer";
String CHANGE_ALIAS = "change-alias";
String CIPHER_SUITE = "cipher-suite";
String CIPHER_SUITE_FILTER = "cipher-suite-filter";
String CLASS_LOADING = "class-loading";
Expand Down Expand Up @@ -120,6 +121,7 @@ interface ElytronDescriptionConstants {
String CREDENTIAL_STORE = "credential-store";
String CREDENTIAL_STORES = "credential-stores";
String CREDENTIALS = "credentials";
String CRITICAL = "critical";
String CUSTOM_CREDENTIAL_SECURITY_FACTORY = "custom-credential-security-factory";
String CUSTOM_PERMISSION_MAPPER = "custom-permission-mapper";
String CUSTOM_POLICY = "custom-policy";
Expand All @@ -145,14 +147,18 @@ interface ElytronDescriptionConstants {
String DIR_CONTEXTS = "dir-contexts";
String DIRECT_VERIFICATION = "direct-verification";
String DISALLOWED_PROVIDERS = "disallowed-providers";
String DISTINGUISHED_NAME = "distinguished-name";

String ELYTRON_SECURITY = "elytron-security";
String ENABLE_CONNECTION_POOLING = "enable-connection-pooling";
String ENABLING = "enabling";
String ENCODED = "encoded";
String ENTRY_TYPE = "entry-type";
String EXPORT_CERTIFICATE = "export-certificate";
String EXTRACT_RDN = "extract-rdn";
String EXTENDS = "extends";
String EXTENSION = "extension";
String EXTENSIONS = "extensions";

String FAIL_CACHE = "fail-cache";
String FILE = "file";
Expand All @@ -173,6 +179,8 @@ interface ElytronDescriptionConstants {
String FORMAT = "format";
String FROM = "from";

String GENERATE_CERTIFICATE_SIGNING_REQUEST = "generate-certificate-signing-request";
String GENERATE_KEY_PAIR = "generate-key-pair";
String GREATER_THAN = "greater-than";
String GROUPS = "groups";
String GROUPS_ATTRIBUTE = "groups-attribute";
Expand All @@ -192,6 +200,7 @@ interface ElytronDescriptionConstants {
String IDENTITY_REALM = "identity-realm";
String IMPLEMENTATION = "implementation";
String IMPLEMENTATION_PROPERTIES = "implementation-properties";
String IMPORT_CERTIFICATE = "import-certificate";
String INDEX = "index";
String INFO = "info";
String INIT = "init";
Expand All @@ -215,6 +224,7 @@ interface ElytronDescriptionConstants {
String KEY_TYPE = "key-type";
String KEY_MANAGER = "key-manager";
String KEY_MANAGERS = "key-managers";
String KEY_SIZE = "key-size";
String KEY_STORE = "key-store";
String KEY_STORE_REALM = "key-store-realm";
String KEY_STORES = "key-stores";
Expand Down Expand Up @@ -281,6 +291,7 @@ interface ElytronDescriptionConstants {

String NAME = "name";
String NEED_CLIENT_AUTH = "need-client-auth";
String NEW_ALIAS = "new-alias";
String NEW_IDENTITY_ATTRIBUTES = "new-identity-attributes";
String NEW_IDENTITY_PARENT_DN = "new-identity-parent-dn";
String NEW_ITEM_ATTRIBUTES = "new-item-attributes";
Expand Down Expand Up @@ -312,6 +323,7 @@ interface ElytronDescriptionConstants {
String PEER_HOST = "peer-host";
String PEER_PORT = "peer-port";
String PEER_PRINCIPAL = "peer-principal";
String PEM = "pem";
String PERIODIC_ROTATING_FILE_AUDIT_LOG = "periodic-rotating-file-audit-log";
String PERMISSION = "permission";
String PERMISSIONS = "permissions";
Expand Down Expand Up @@ -456,6 +468,7 @@ interface ElytronDescriptionConstants {
String TO = "to";
String TOKEN_REALM = "token-realm";
String TRANSPORT = "transport";
String TRUST_CACERTS = "trust-cacerts";
String TRUST_MANAGER = "trust-manager";
String TRUST_MANAGERS = "trust-managers";
String TRUSTED_SECURITY_DOMAINS = "trusted-security-domains";
Expand All @@ -471,6 +484,8 @@ interface ElytronDescriptionConstants {
String USER_PASSWORD_MAPPER = "user-password-mapper";

String VALID = "valid";
String VALIDATE = "validate";
String VALIDITY = "validity";
String VALUE = "value";
String VERIFIABLE = "verifiable";
String VERSION = "version";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,8 +262,8 @@ protected void performRuntime(OperationContext context, ModelNode operation, Res
ServiceName serviceName = runtimeCapability.getCapabilityServiceName(KeyStore.class);
ServiceBuilder<KeyStore> serviceBuilder = serviceTarget.addService(serviceName, keyStoreService).setInitialMode(Mode.ACTIVE);

serviceBuilder.addDependency(PathManagerService.SERVICE_NAME, PathManager.class, keyStoreService.getPathManagerInjector());
if (relativeTo != null) {
serviceBuilder.addDependency(PathManagerService.SERVICE_NAME, PathManager.class, keyStoreService.getPathManagerInjector());
serviceBuilder.addDependency(pathName(relativeTo));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,7 @@ public void start(StartContext startContext) throws StartException {
AtomicLoadKeyStore keyStore = AtomicLoadKeyStore.newInstance(type, provider);
if (path != null) {
pathResolver = pathResolver();
pathResolver.path(path);
if (relativeTo != null) {
pathResolver.relativeTo(relativeTo, pathManager.getValue());
}
resolvedPath = pathResolver.resolve();
resolvedPath = getResolvedPath(pathResolver, path, relativeTo);
}

synched = System.currentTimeMillis();
Expand All @@ -124,10 +120,9 @@ public void start(StartContext startContext) throws StartException {
throw ROOT_LOGGER.keyStoreFileNotExists(resolvedPath.getAbsolutePath());
} else {
ROOT_LOGGER.keyStoreFileNotExistsButIgnored(resolvedPath.getAbsolutePath());
resolvedPath = null;
}
}
try (InputStream is = resolvedPath != null ? new FileInputStream(resolvedPath) : null) {
try (InputStream is = (resolvedPath != null && resolvedPath.exists()) ? new FileInputStream(resolvedPath) : null) {
char[] password = resolvePassword();

ROOT_LOGGER.tracef(
Expand Down Expand Up @@ -271,6 +266,21 @@ boolean isModified() {
return trackingKeyStore.isModified();
}

char[] resolveKeyPassword(final ExceptionSupplier<CredentialSource, Exception> keyPasswordCredentialSourceSupplier) throws Exception {
if (keyPasswordCredentialSourceSupplier == null) {
// use the key-store password if no key password is provided
return resolvePassword();
}
CredentialSource cs = keyPasswordCredentialSourceSupplier.get();
String path = resolvedPath != null ? resolvedPath.getPath() : "null";
if (cs == null) throw ROOT_LOGGER.keyPasswordCannotBeResolved(path);
PasswordCredential credential = cs.getCredential(PasswordCredential.class);
if (credential == null) throw ROOT_LOGGER.keyPasswordCannotBeResolved(path);
ClearPassword password = credential.getPassword(ClearPassword.class);
if (password == null) throw ROOT_LOGGER.keyPasswordCannotBeResolved(path);
return password.getPassword();
}

private char[] resolvePassword() throws Exception {
ExceptionSupplier<CredentialSource, Exception> sourceSupplier = credentialSourceSupplier.getValue();
CredentialSource cs = sourceSupplier != null ? sourceSupplier.get() : null;
Expand All @@ -284,6 +294,14 @@ private char[] resolvePassword() throws Exception {
return password.getPassword();
}

File getResolvedPath(PathResolver pathResolver, String path, String relativeTo) {
pathResolver.path(path);
if (relativeTo != null) {
pathResolver.relativeTo(relativeTo, pathManager.getValue());
}
return pathResolver.resolve();
}

static class LoadKey {
private final AtomicLoadKeyStore.LoadKey loadKey;
private final long modifiedTime;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ static ResourceDefinition wrap(ResourceDefinition resourceDefinition) {
return new ModifiableKeyStoreDecorator(resourceDefinition);
}

private ModifiableKeyStoreDecorator(ResourceDefinition resourceDefinition) {
ModifiableKeyStoreDecorator(ResourceDefinition resourceDefinition) {
setDelegate(resourceDefinition);
}

Expand All @@ -80,10 +80,6 @@ public void registerOperations(ManagementResourceRegistration resourceRegistrati

if (isServerOrHostController(resourceRegistration)) { // server-only operations
RemoveAliasHandler.register(resourceRegistration, resolver);

// Create Key Pair / Certificate
// Create CSR
// Import certificate
}
}

Expand Down Expand Up @@ -230,6 +226,17 @@ static KeyStore getKeyStore(OperationContext context) throws OperationFailedExce
* @throws OperationFailedException if any error occurs while obtaining.
*/
static KeyStore getModifiableKeyStore(OperationContext context) throws OperationFailedException {
return getModifiableKeyStoreService(context).getModifiableValue();
}

/**
* Try to obtain a modifiable {@link KeyStoreService} based on the given {@link OperationContext}.
*
* @param context the current context
* @return the modifiable KeyStore service
* @throws OperationFailedException if an error occurs while attempting to obtain the modifiable KeyStore service
*/
static ModifiableKeyStoreService getModifiableKeyStoreService(OperationContext context) throws OperationFailedException {
ServiceRegistry serviceRegistry = context.getServiceRegistry(true);
PathAddress currentAddress = context.getCurrentAddress();
RuntimeCapability<Void> runtimeCapability = KEY_STORE_RUNTIME_CAPABILITY.fromBaseCapability(currentAddress.getLastElement().getValue());
Expand All @@ -241,7 +248,6 @@ static KeyStore getModifiableKeyStore(OperationContext context) throws Operation
throw ROOT_LOGGER.requiredServiceNotUp(serviceName, serviceState);
}

ModifiableKeyStoreService service = (ModifiableKeyStoreService) serviceContainer.getService();
return service.getModifiableValue();
return (ModifiableKeyStoreService) serviceContainer.getService();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -445,4 +445,52 @@ public interface ElytronSubsystemMessages extends BasicLogger {
@Message(id = 1026, value = "Element '%s' with attribute '%s' set to '%s' is unused. Since unused policy " +
"configurations can no longer be stored in the configuration model this item is being discarded.")
void discardingUnusedPolicy(String element, String attr, String name);

@Message(id = 1027, value = "Key password cannot be resolved for key-store '%s'")
IOException keyPasswordCannotBeResolved(String path);

@Message(id = 1028, value = "Invalid value for not-before. %s")
OperationFailedException invalidNotBefore(@Cause Throwable cause, String causeMessage);

@Message(id = 1029, value = "Alias '%s' does not exist in KeyStore")
OperationFailedException keyStoreAliasDoesNotExist(String alias);

@Message(id = 1030, value = "Alias '%s' does not identify a PrivateKeyEntry in KeyStore")
OperationFailedException keyStoreAliasDoesNotIdentifyPrivateKeyEntry(String alias);

@Message(id = 1031, value = "Unable to obtain PrivateKey for alias '%s'")
OperationFailedException unableToObtainPrivateKey(String alias);

@Message(id = 1032, value = "Unable to obtain Certificate for alias '%s'")
OperationFailedException unableToObtainCertificate(String alias);

@Message(id = 1033, value = "No certificates found in certificate reply")
OperationFailedException noCertificatesFoundInCertificateReply();

@Message(id = 1034, value = "Public key from certificate reply does not match public key from certificate in KeyStore")
OperationFailedException publicKeyFromCertificateReplyDoesNotMatchKeyStore();

@Message(id = 1035, value = "Certificate reply is the same as the certificate from PrivateKeyEntry in KeyStore")
OperationFailedException certificateReplySameAsCertificateFromKeyStore();

@Message(id = 1036, value = "Alias '%s' already exists in KeyStore")
OperationFailedException keyStoreAliasAlreadyExists(String alias);

@Message(id = 1037, value = "Top-most certificate from certificate reply is not trusted. Inspect the certificate carefully and if it is valid, execute import-certificate again with validate set to false.")
OperationFailedException topMostCertificateFromCertificateReplyNotTrusted();

@Message(id = 1038, value = "Trusted certificate is already in KeyStore under alias '%s'")
OperationFailedException trustedCertificateAlreadyInKeyStore(String alias);

@Message(id = 1039, value = "Trusted certificate is already in cacerts KeyStore under alias '%s'")
OperationFailedException trustedCertificateAlreadyInCacertsKeyStore(String alias);

@Message(id = 1040, value = "Unable to determine if the certificate is trusted. Inspect the certificate carefully and if it is valid, execute import-certificate again with validate set to false.")
OperationFailedException unableToDetermineIfCertificateIsTrusted();

@Message(id = 1041, value = "Certificate file does not exist")
OperationFailedException certificateFileDoesNotExist(@Cause Exception cause);

@Message(id = 1042, value = "Unable to obtain Entry for alias '%s'")
OperationFailedException unableToObtainEntry(String alias);
}

0 comments on commit 7e5735e

Please sign in to comment.