Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WFCORE-3305][WFCORE-3425] Add more runtime operations to the Elytron key-store resource for advanced KeyStore manipulation #2949

Merged
merged 2 commits into from
Feb 12, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view

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 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not related to this PR but we also want at some point to look at KeyStore password re-use for the KeyManager resource as well.

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);
}