diff --git a/.gitignore b/.gitignore index 2055c9d34e5..5e7aeeaaa67 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,8 @@ target nbactions.xml nb-configuration.xml catalog.xml +# Ignore VSCode Files +.vscode # maven-ant-tasks.jar test-output diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1ca5fd48f53..9ff111730ca 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,6 +8,10 @@ Welcome to the WildFly Elytron project! We welcome contributions from the commun - [Good First Issues](#good-first-issues) - [Setting up your Developer Environment](#setting-up-your-developer-environment) - [Contributing Guidelines](#contributing-guidelines) + - [Testing](#testing) + - [Pull Request Process](#pull-request-process) + - [Documentation](#documentation) +- [FAQ for New Contributors](#faq-for-new-contributors) - [Community](#community) @@ -92,8 +96,18 @@ The generated report is at `target/site/clover` and to access it start by openin For more information, including details on how WildFly Elytron is integrated in WildFly Core and WildFly, check out our [developer guide](https://wildfly-security.github.io/wildfly-elytron/getting-started-for-developers/). + ## Contributing Guidelines +### Testing +Ensure that your changes are thoroughly tested before submitting a pull request. Follow these testing guidelines: + +- Run the existing unit tests using Maven: `mvn clean test` +- Include new unit tests for your code changes. + +If applicable, provide instructions on how to run integration tests or any additional testing procedures. + +### Pull Request Process When submitting a PR, please keep the following guidelines in mind: 1. In general, it's good practice to squash all of your commits into a single commit. For larger changes, it's ok to have multiple meaningful commits. If you need help with squashing your commits, feel free to ask us how to do this on your pull request. We're more than happy to help! @@ -104,6 +118,13 @@ When submitting a PR, please keep the following guidelines in mind: For an example of a properly formatted PR, take a look at https://github.com/wildfly-security/wildfly-elytron/pull/1532 +### Documentation +Contributors are encouraged to keep documentation up-to-date along with code changes. If your changes impact user-facing features, update the relevant documentation files in directory. +Community documentation can be found in the [wildfly repository](https://github.com/wildfly/wildfly/tree/main/docs) + +## FAQ for New Contributors +Check out our [Frequently Asked Questions](https://fjuma.github.io/wildfly-elytron/blog/frequently-asked-questions-new-contributors/) for New Contributors. + ## Code Reviews All submissions, including submissions by project members, need to be reviewed by at least two WildFly Elytron committers before being merged. @@ -117,4 +138,4 @@ your PR directly against the relevant maintenance branch. Once a fix for a maint merge the maintenance branch to the upstream branch to ensure changes are kept in sync. ## Community -For more information on how to get involved with WildFly Elytron, check out our [community](https://wildfly-security.github.io/wildfly-elytron/community/) page. +For more information on how to get involved with WildFly Elytron, check out our [community](https://wildfly-security.github.io/wildfly-elytron/community/) page. \ No newline at end of file diff --git a/asn1/pom.xml b/asn1/pom.xml index 1eefb6c1f3f..fb4be4b879d 100644 --- a/asn1/pom.xml +++ b/asn1/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT 4.0.0 diff --git a/asn1/src/main/java/org/wildfly/security/asn1/DEREncoder.java b/asn1/src/main/java/org/wildfly/security/asn1/DEREncoder.java index 91ee56c1cb3..0ab91bd1253 100644 --- a/asn1/src/main/java/org/wildfly/security/asn1/DEREncoder.java +++ b/asn1/src/main/java/org/wildfly/security/asn1/DEREncoder.java @@ -470,7 +470,7 @@ public void writeEncoded(byte[] encoded) { @Override public void flush() { - while (states.size() != 0) { + while (!states.isEmpty()) { EncoderState lastState = states.peekLast(); if (lastState.getTag() == SEQUENCE_TYPE) { endSequence(); diff --git a/audit/pom.xml b/audit/pom.xml index d4f6c840eda..70673c851c8 100644 --- a/audit/pom.xml +++ b/audit/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT 4.0.0 diff --git a/auth/base/pom.xml b/auth/base/pom.xml index 0661646ab8b..764d0639c6e 100644 --- a/auth/base/pom.xml +++ b/auth/base/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../pom.xml diff --git a/auth/client/pom.xml b/auth/client/pom.xml index 2ab12bd36ca..88375a5d569 100644 --- a/auth/client/pom.xml +++ b/auth/client/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../pom.xml diff --git a/auth/client/src/main/java/org/wildfly/security/auth/client/ElytronXmlParser.java b/auth/client/src/main/java/org/wildfly/security/auth/client/ElytronXmlParser.java index 967df3725b8..b731c2821b0 100644 --- a/auth/client/src/main/java/org/wildfly/security/auth/client/ElytronXmlParser.java +++ b/auth/client/src/main/java/org/wildfly/security/auth/client/ElytronXmlParser.java @@ -3466,7 +3466,7 @@ static CredentialSource parseLocalKerberos(ConfigurationXMLStreamReader reader) default: throw reader.unexpectedAttribute(i); } } - if (mechanismOids.size() == 0) { + if (mechanismOids.isEmpty()) { mechanismOids.add(GSSCredentialSecurityFactory.KERBEROS_V5); mechanismOids.add(GSSCredentialSecurityFactory.SPNEGO); } @@ -3649,6 +3649,9 @@ protected AbstractLoadingKeyStoreFactory(final ExceptionSupplier expectedClass, Class actualClass); + @LogMessage(level = INFO) + @Message(id = 1138, value = "No Keystore password specified \"%s\"") + void noKeystorePasswordSpecified(Location location); + @Message(id = 1139, value = "Failed to create credential store") ConfigXMLParseException xmlFailedToCreateCredentialStore(@Param Location location, @Cause Throwable cause); diff --git a/auth/realm/base/pom.xml b/auth/realm/base/pom.xml index 6cd31e3a957..7011a4cf695 100644 --- a/auth/realm/base/pom.xml +++ b/auth/realm/base/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../../pom.xml diff --git a/auth/realm/base/src/main/java/org/wildfly/security/auth/realm/AggregateSecurityRealm.java b/auth/realm/base/src/main/java/org/wildfly/security/auth/realm/AggregateSecurityRealm.java index dde13678819..198c5e8331c 100644 --- a/auth/realm/base/src/main/java/org/wildfly/security/auth/realm/AggregateSecurityRealm.java +++ b/auth/realm/base/src/main/java/org/wildfly/security/auth/realm/AggregateSecurityRealm.java @@ -79,18 +79,14 @@ public AggregateSecurityRealm(final SecurityRealm authenticationRealm, Function< public RealmIdentity getRealmIdentity(final Evidence evidence) throws RealmUnavailableException { boolean ok = false; final RealmIdentity authenticationIdentity = authenticationRealm.getRealmIdentity(evidence); - if (authenticationIdentity.exists()) { - log.tracef("Authentication identity for principal [%s] found.", evidence.getDecodedPrincipal()); - } + log.tracef("Authentication identity for principal [%s] obtained.", evidence.getDecodedPrincipal()); final RealmIdentity[] authorizationIdentities = new RealmIdentity[authorizationRealms.length]; try { for (int i = 0; i < authorizationIdentities.length; i++) { SecurityRealm authorizationRealm = authorizationRealms[i]; authorizationIdentities[i] = (authorizationRealm == authenticationRealm) ? authenticationIdentity : getAuthorizationIdentity(authorizationRealm, evidence, principalTransformer, authenticationIdentity); - if (authorizationIdentities[i].exists()) { - log.tracef("Authorization identity for principal [%s] found.", evidence.getDecodedPrincipal()); - } + log.tracef("Authorization identity for principal [%s] obtained.", evidence.getDecodedPrincipal()); } final Identity identity = new Identity(authenticationIdentity, authorizationIdentities); @@ -111,9 +107,7 @@ public RealmIdentity getRealmIdentity(final Evidence evidence) throws RealmUnava public RealmIdentity getRealmIdentity(final Principal principal) throws RealmUnavailableException { boolean ok = false; final RealmIdentity authenticationIdentity = authenticationRealm.getRealmIdentity(principal); - if (authenticationIdentity.exists()) { - log.tracef("Authentication identity for principal [%s] found.", principal); - } + log.tracef("Authentication identity for principal [%s] obtained.", principal); Principal authorizationPrincipal = principal; if (principalTransformer != null) { authorizationPrincipal = principalTransformer.apply(authorizationPrincipal); @@ -125,9 +119,7 @@ public RealmIdentity getRealmIdentity(final Principal principal) throws RealmUna for (int i = 0; i < authorizationIdentities.length; i++) { SecurityRealm authorizationRealm = authorizationRealms[i]; authorizationIdentities[i] = (authorizationRealm == authenticationRealm) && (principalTransformer == null) ? authenticationIdentity : authorizationRealm.getRealmIdentity(authorizationPrincipal); - if (authorizationIdentities[i].exists()) { - log.tracef("Authorization identity for principal [%s] found.", principal); - } + log.tracef("Authorization identity for principal [%s] obtained.", principal); } final Identity identity = new Identity(authenticationIdentity, authorizationIdentities); diff --git a/auth/realm/base/src/main/java/org/wildfly/security/auth/realm/FileSystemRealmUtil.java b/auth/realm/base/src/main/java/org/wildfly/security/auth/realm/FileSystemRealmUtil.java index f4899cb1a88..3165221f16b 100644 --- a/auth/realm/base/src/main/java/org/wildfly/security/auth/realm/FileSystemRealmUtil.java +++ b/auth/realm/base/src/main/java/org/wildfly/security/auth/realm/FileSystemRealmUtil.java @@ -32,7 +32,7 @@ * A utility class to utilize methods from the {@code FileSystemSecurityRealm} class for the Elytron Tool. * * @author Ashpan Raskar - * @author Cameron Rodriguez + * @author Jessica Rodriguez */ public class FileSystemRealmUtil { diff --git a/auth/realm/base/src/test/java/org/wildfly/security/auth/realm/AggregateRealmEvidenceTest.java b/auth/realm/base/src/test/java/org/wildfly/security/auth/realm/AggregateRealmEvidenceTest.java index 579e109ec5e..c07245d2b06 100644 --- a/auth/realm/base/src/test/java/org/wildfly/security/auth/realm/AggregateRealmEvidenceTest.java +++ b/auth/realm/base/src/test/java/org/wildfly/security/auth/realm/AggregateRealmEvidenceTest.java @@ -275,8 +275,7 @@ private static X509Certificate populateCertificateChain() throws Exception { builder.setSignatureAlgorithmName("SHA256withRSA"); builder.setPublicKey(keyPair.getPublic()); - final X509Certificate orderedCertificate = builder.build(); - return orderedCertificate; + return builder.build(); } private Path getRootPath(String path, boolean deleteIfExists) throws Exception { diff --git a/auth/realm/jdbc/pom.xml b/auth/realm/jdbc/pom.xml index 6e48afe2a25..d0092cd639b 100644 --- a/auth/realm/jdbc/pom.xml +++ b/auth/realm/jdbc/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../../pom.xml diff --git a/auth/realm/ldap/pom.xml b/auth/realm/ldap/pom.xml index 2243df70dfd..27a3cda086a 100644 --- a/auth/realm/ldap/pom.xml +++ b/auth/realm/ldap/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../../pom.xml diff --git a/auth/realm/token/pom.xml b/auth/realm/token/pom.xml index c691385b5e9..e0cb18aa0f5 100644 --- a/auth/realm/token/pom.xml +++ b/auth/realm/token/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../../pom.xml @@ -85,7 +85,7 @@ - org.glassfish + org.eclipse.parsson jakarta.json test diff --git a/auth/realm/token/src/test/java/org/wildfly/security/auth/realm/token/OAuth2TokenSecurityRealmTest.java b/auth/realm/token/src/test/java/org/wildfly/security/auth/realm/token/OAuth2TokenSecurityRealmTest.java index e2586601e37..720a43b4373 100644 --- a/auth/realm/token/src/test/java/org/wildfly/security/auth/realm/token/OAuth2TokenSecurityRealmTest.java +++ b/auth/realm/token/src/test/java/org/wildfly/security/auth/realm/token/OAuth2TokenSecurityRealmTest.java @@ -44,7 +44,10 @@ import java.util.Arrays; import java.util.function.Function; -import static org.junit.Assert.*; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; /** * @author Pedro Igor diff --git a/auth/server/base/pom.xml b/auth/server/base/pom.xml index a63d8942f3f..29a7ec9b566 100644 --- a/auth/server/base/pom.xml +++ b/auth/server/base/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../../pom.xml diff --git a/auth/server/deprecated/pom.xml b/auth/server/deprecated/pom.xml index a30057a6abc..10b865ef5e6 100644 --- a/auth/server/deprecated/pom.xml +++ b/auth/server/deprecated/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../../pom.xml diff --git a/auth/server/deprecated/src/main/java/org/wildfly/security/auth/server/HttpAuthenticationFactory.java b/auth/server/deprecated/src/main/java/org/wildfly/security/auth/server/HttpAuthenticationFactory.java index 403bc2f8696..c07a8a3ed03 100644 --- a/auth/server/deprecated/src/main/java/org/wildfly/security/auth/server/HttpAuthenticationFactory.java +++ b/auth/server/deprecated/src/main/java/org/wildfly/security/auth/server/HttpAuthenticationFactory.java @@ -46,7 +46,7 @@ * {@link HttpServerAuthenticationMechanismFactory} for obtaining configured mechanisms. * * @author Darran Lofthouse - * @deprecated Use {@link org.wildfly.security.auth.server.http.HttpAuthenticationFactory} instead + * @deprecated Use {@link org.wildfly.security.auth.server.http.HttpAuthenticationFactory org.wildfly.security.auth.server.http.HttpAuthenticationFactory} instead */ @Deprecated public final class HttpAuthenticationFactory extends AbstractMechanismAuthenticationFactory { diff --git a/auth/server/deprecated/src/main/java/org/wildfly/security/auth/server/SaslAuthenticationFactory.java b/auth/server/deprecated/src/main/java/org/wildfly/security/auth/server/SaslAuthenticationFactory.java index 85636863d9b..e05351e9fcc 100644 --- a/auth/server/deprecated/src/main/java/org/wildfly/security/auth/server/SaslAuthenticationFactory.java +++ b/auth/server/deprecated/src/main/java/org/wildfly/security/auth/server/SaslAuthenticationFactory.java @@ -48,7 +48,7 @@ * A SASL server factory configuration. * * @author David M. Lloyd - * @deprecated Use {@link org.wildfly.security.auth.server.sasl.SaslAuthenticationFactory} instead + * @deprecated Use {@link org.wildfly.security.auth.server.sasl.SaslAuthenticationFactory org.wildfly.security.auth.server.sasl.SaslAuthenticationFactory} instead */ @Deprecated public final class SaslAuthenticationFactory extends AbstractMechanismAuthenticationFactory { diff --git a/auth/server/deprecated/src/main/java/org/wildfly/security/auth/server/SecurityIdentityServerMechanismFactory.java b/auth/server/deprecated/src/main/java/org/wildfly/security/auth/server/SecurityIdentityServerMechanismFactory.java index 430340ec0c1..9f63571f861 100644 --- a/auth/server/deprecated/src/main/java/org/wildfly/security/auth/server/SecurityIdentityServerMechanismFactory.java +++ b/auth/server/deprecated/src/main/java/org/wildfly/security/auth/server/SecurityIdentityServerMechanismFactory.java @@ -41,7 +41,7 @@ * the callback handler is returned instead. * * @author Darran Lofthouse - * @deprecated Use {@link org.wildfly.security.auth.server.http.SecurityIdentityServerMechanismFactory} instead + * @deprecated Use {@link org.wildfly.security.auth.server.http.SecurityIdentityServerMechanismFactory org.wildfly.security.auth.server.http.SecurityIdentityServerMechanismFactory} instead */ @Deprecated class SecurityIdentityServerMechanismFactory implements HttpServerAuthenticationMechanismFactory { diff --git a/auth/server/http/pom.xml b/auth/server/http/pom.xml index bafda60cf0b..cec7657b45d 100644 --- a/auth/server/http/pom.xml +++ b/auth/server/http/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../../pom.xml diff --git a/auth/server/sasl/pom.xml b/auth/server/sasl/pom.xml index 58ce9bfc75e..8bf68a3ed45 100644 --- a/auth/server/sasl/pom.xml +++ b/auth/server/sasl/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../../pom.xml diff --git a/auth/util/pom.xml b/auth/util/pom.xml index df27ef751ed..6f39d9fa05e 100644 --- a/auth/util/pom.xml +++ b/auth/util/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../pom.xml diff --git a/base/pom.xml b/base/pom.xml index 50ec88ea27a..1c30ef98cd9 100644 --- a/base/pom.xml +++ b/base/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT 4.0.0 diff --git a/credential/base/pom.xml b/credential/base/pom.xml index 7c1976839e1..2c98ff8943c 100644 --- a/credential/base/pom.xml +++ b/credential/base/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../pom.xml diff --git a/credential/base/src/main/java/org/wildfly/security/key/KeyUtil.java b/credential/base/src/main/java/org/wildfly/security/key/KeyUtil.java index 234734c96bb..4ab3edd0236 100644 --- a/credential/base/src/main/java/org/wildfly/security/key/KeyUtil.java +++ b/credential/base/src/main/java/org/wildfly/security/key/KeyUtil.java @@ -37,6 +37,7 @@ import java.security.interfaces.RSAMultiPrimePrivateCrtKey; import java.security.interfaces.RSAPrivateKey; import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.DSAParameterSpec; import java.security.spec.ECParameterSpec; import java.util.Arrays; import java.util.Objects; @@ -99,7 +100,9 @@ public static

P getParameters(Key key, Class< } else if (key instanceof RSAKey && paramSpecClass.isAssignableFrom(RSAParameterSpec.class)) { return paramSpecClass.cast(new RSAParameterSpec((RSAKey) key)); } else if (key instanceof DSAKey && paramSpecClass.isAssignableFrom(DSAParams.class)) { - return paramSpecClass.cast(((DSAKey) key).getParams()); + final DSAKey dsaKey = (DSAKey) key; + final DSAParams dsaParams = dsaKey.getParams(); + return paramSpecClass.cast(new DSAParameterSpec(dsaParams.getP(), dsaParams.getQ(), dsaParams.getG())); } else if (key instanceof ECKey && paramSpecClass.isAssignableFrom(ECParameterSpec.class)) { return paramSpecClass.cast(((ECKey) key).getParams()); } else if (key instanceof DHKey && paramSpecClass.isAssignableFrom(DHParameterSpec.class)) { diff --git a/credential/source/deprecated/pom.xml b/credential/source/deprecated/pom.xml index 8f6938ab3fa..2c91de751de 100644 --- a/credential/source/deprecated/pom.xml +++ b/credential/source/deprecated/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../../pom.xml diff --git a/credential/source/deprecated/src/main/java/org/wildfly/security/credential/source/CallbackHandlerCredentialSource.java b/credential/source/deprecated/src/main/java/org/wildfly/security/credential/source/CallbackHandlerCredentialSource.java index 509491c2252..deb676a58e8 100644 --- a/credential/source/deprecated/src/main/java/org/wildfly/security/credential/source/CallbackHandlerCredentialSource.java +++ b/credential/source/deprecated/src/main/java/org/wildfly/security/credential/source/CallbackHandlerCredentialSource.java @@ -37,7 +37,7 @@ * A credential source which is backed by a callback handler. * * @author David M. Lloyd - * @deprecated Use {@link org.wildfly.security.credential.source.impl.CallbackHandlerCredentialSource} instead + * @deprecated Use {@link org.wildfly.security.credential.source.impl.CallbackHandlerCredentialSource org.wildfly.security.credential.source.impl.CallbackHandlerCredentialSource} instead */ @Deprecated public final class CallbackHandlerCredentialSource implements CredentialSource { diff --git a/credential/source/deprecated/src/main/java/org/wildfly/security/credential/source/CommandCredentialSource.java b/credential/source/deprecated/src/main/java/org/wildfly/security/credential/source/CommandCredentialSource.java index b5914bda876..2265e3da231 100644 --- a/credential/source/deprecated/src/main/java/org/wildfly/security/credential/source/CommandCredentialSource.java +++ b/credential/source/deprecated/src/main/java/org/wildfly/security/credential/source/CommandCredentialSource.java @@ -52,7 +52,7 @@ * A credential source which acquires a credential from the command line. * * @author David M. Lloyd - * @deprecated Use {@link org.wildfly.security.credential.source.impl.CommandCredentialSource} instead + * @deprecated Use {@link org.wildfly.security.credential.source.impl.CommandCredentialSource org.wildfly.security.credential.source.impl.CommandCredentialSource} instead */ @Deprecated public final class CommandCredentialSource implements CredentialSource { diff --git a/credential/source/deprecated/src/main/java/org/wildfly/security/credential/source/CredentialStoreCredentialSource.java b/credential/source/deprecated/src/main/java/org/wildfly/security/credential/source/CredentialStoreCredentialSource.java index 76e35fd81f9..234b0d32d66 100644 --- a/credential/source/deprecated/src/main/java/org/wildfly/security/credential/source/CredentialStoreCredentialSource.java +++ b/credential/source/deprecated/src/main/java/org/wildfly/security/credential/source/CredentialStoreCredentialSource.java @@ -37,7 +37,7 @@ * * @author David M. Lloyd * @author Peter Skopek - * @deprecated Use {@link org.wildfly.security.credential.source.impl.CredentialStoreCredentialSource} instead + * @deprecated Use {@link org.wildfly.security.credential.source.impl.CredentialStoreCredentialSource org.wildfly.security.credential.source.impl.CredentialStoreCredentialSource} instead */ @Deprecated public final class CredentialStoreCredentialSource implements CredentialSource { diff --git a/credential/source/deprecated/src/main/java/org/wildfly/security/credential/source/FactoryCredentialSource.java b/credential/source/deprecated/src/main/java/org/wildfly/security/credential/source/FactoryCredentialSource.java index 3e5944f3673..088ff37a36e 100644 --- a/credential/source/deprecated/src/main/java/org/wildfly/security/credential/source/FactoryCredentialSource.java +++ b/credential/source/deprecated/src/main/java/org/wildfly/security/credential/source/FactoryCredentialSource.java @@ -31,7 +31,7 @@ * A credential source which is backed by a credential security factory. * * @author Martin Mazanek - * @deprecated Use {@link org.wildfly.security.credential.source.impl.FactoryCredentialSource} instead + * @deprecated Use {@link org.wildfly.security.credential.source.impl.FactoryCredentialSource org.wildfly.security.credential.source.impl.FactoryCredentialSource} instead */ @Deprecated public class FactoryCredentialSource implements CredentialSource { diff --git a/credential/source/deprecated/src/main/java/org/wildfly/security/credential/source/KeyStoreCredentialSource.java b/credential/source/deprecated/src/main/java/org/wildfly/security/credential/source/KeyStoreCredentialSource.java index 5b12588b703..40087d618b4 100644 --- a/credential/source/deprecated/src/main/java/org/wildfly/security/credential/source/KeyStoreCredentialSource.java +++ b/credential/source/deprecated/src/main/java/org/wildfly/security/credential/source/KeyStoreCredentialSource.java @@ -43,7 +43,7 @@ * A credential source which is backed by a key store entry. * * @author David M. Lloyd - * @deprecated Use {@link org.wildfly.security.credential.source.impl.KeyStoreCredentialSource} instead + * @deprecated Use {@link org.wildfly.security.credential.source.impl.KeyStoreCredentialSource org.wildfly.security.credential.source.impl.KeyStoreCredentialSource} instead */ @Deprecated public final class KeyStoreCredentialSource implements CredentialSource { diff --git a/credential/source/deprecated/src/main/java/org/wildfly/security/credential/source/LocalKerberosCredentialSource.java b/credential/source/deprecated/src/main/java/org/wildfly/security/credential/source/LocalKerberosCredentialSource.java index 11e521dc5ed..c27d20012b0 100644 --- a/credential/source/deprecated/src/main/java/org/wildfly/security/credential/source/LocalKerberosCredentialSource.java +++ b/credential/source/deprecated/src/main/java/org/wildfly/security/credential/source/LocalKerberosCredentialSource.java @@ -40,7 +40,7 @@ * * Successful obtaining from cache requires set system property {@code javax.security.auth.useSubjectCredsOnly} to {@code false}. * - * @deprecated Kerberos based authentication mechanism obtains credential himself, see {@link org.wildfly.security.credential.source.impl.LocalKerberosCredentialSource} to use with the new wildfly-elytron-credential-source-impl module + * @deprecated Kerberos based authentication mechanism obtains credential himself, see {@link org.wildfly.security.credential.source.impl.LocalKerberosCredentialSource org.wildfly.security.credential.source.impl.LocalKerberosCredentialSource} to use with the new wildfly-elytron-credential-source-impl module * * @author Jan Kalina */ diff --git a/credential/source/impl/pom.xml b/credential/source/impl/pom.xml index 5be0f3844b4..64e2fb398a1 100644 --- a/credential/source/impl/pom.xml +++ b/credential/source/impl/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../../pom.xml diff --git a/credential/store/pom.xml b/credential/store/pom.xml index 53f6d726221..ac6bc803d5c 100644 --- a/credential/store/pom.xml +++ b/credential/store/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../pom.xml diff --git a/digest/pom.xml b/digest/pom.xml index 6005943ae52..fd791d6cfde 100644 --- a/digest/pom.xml +++ b/digest/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT 4.0.0 diff --git a/dynamic-ssl/pom.xml b/dynamic-ssl/pom.xml index 98618df9ef8..0149158d921 100644 --- a/dynamic-ssl/pom.xml +++ b/dynamic-ssl/pom.xml @@ -5,7 +5,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT 4.0.0 @@ -39,6 +39,12 @@ org.wildfly.security wildfly-elytron-client + + org.wildfly.security + wildfly-elytron-tests-common + test + test-jar + org.kohsuke.metainf-services metainf-services diff --git a/dynamic-ssl/src/test/java/org/wildfly/security/dynamic/ssl/DynamicSSLContextTest.java b/dynamic-ssl/src/test/java/org/wildfly/security/dynamic/ssl/DynamicSSLContextTest.java index cd74cba609f..6c4378f34f6 100644 --- a/dynamic-ssl/src/test/java/org/wildfly/security/dynamic/ssl/DynamicSSLContextTest.java +++ b/dynamic-ssl/src/test/java/org/wildfly/security/dynamic/ssl/DynamicSSLContextTest.java @@ -330,7 +330,7 @@ public void testChangingAuthenticationContextsTest() throws NoSuchAlgorithmExcep SSLSocketFactory socketFactory = dynamicSSLContext.getSocketFactory(); AuthenticationContext.empty().withSsl(MatchRule.ALL.matchPort(10001), () -> DynamicSSLTestUtils - .createSSLContext(RESOURCES + "client1.keystore.jks", RESOURCES + "client1.truststore.jks", "secret")).run(() -> { + .createSSLContext(RESOURCES + "client1.keystore.jks", RESOURCES + "client1.truststore.jks", "Elytron")).run(() -> { try { Socket clientSslSocket = socketFactory.createSocket("localhost", 10001); checkOutputIsOK((SSLSocket) clientSslSocket); @@ -341,7 +341,7 @@ public void testChangingAuthenticationContextsTest() throws NoSuchAlgorithmExcep }); AuthenticationContext.empty().withSsl(MatchRule.ALL.matchPort(10002), () -> DynamicSSLTestUtils - .createSSLContext(RESOURCES + "client2.keystore.jks", RESOURCES + "client2.truststore.jks", "secret")).run(() -> { + .createSSLContext(RESOURCES + "client2.keystore.jks", RESOURCES + "client2.truststore.jks", "Elytron")).run(() -> { try { Socket clientSslSocket = socketFactory.createSocket("localhost", 10002); checkOutputIsOK((SSLSocket) clientSslSocket); @@ -352,7 +352,7 @@ public void testChangingAuthenticationContextsTest() throws NoSuchAlgorithmExcep }); AuthenticationContext.empty().withSsl(MatchRule.ALL.matchPort(10003), () -> DynamicSSLTestUtils - .createSSLContext(RESOURCES + "client3.keystore.jks", RESOURCES + "client3.truststore.jks", "secret")).run(() -> { + .createSSLContext(RESOURCES + "client3.keystore.jks", RESOURCES + "client3.truststore.jks", "Elytron")).run(() -> { try { Socket clientSslSocket = socketFactory.createSocket("localhost", 10003); checkOutputIsOK((SSLSocket) clientSslSocket); @@ -371,7 +371,7 @@ public void testThrowAnExceptionWhenLoop() throws NoSuchAlgorithmException { SSLContext previousDefaultSSLContext = SSLContext.getDefault(); SSLContext.setDefault(dynamicSSLContext); AuthenticationContext.empty().withSsl(MatchRule.ALL.matchPort(10000), () -> DynamicSSLTestUtils - .createSSLContext(RESOURCES + "client1.keystore.jks", RESOURCES + "client1.truststore.jks", "secret")).run(() -> { + .createSSLContext(RESOURCES + "client1.keystore.jks", RESOURCES + "client1.truststore.jks", "Elytron")).run(() -> { try { Socket clientSslSocket = socketFactory.createSocket("localhost", 12345); checkOutputIsOK((SSLSocket) clientSslSocket); diff --git a/dynamic-ssl/src/test/java/org/wildfly/security/dynamic/ssl/DynamicSSLTestUtils.java b/dynamic-ssl/src/test/java/org/wildfly/security/dynamic/ssl/DynamicSSLTestUtils.java index 3f73dec2930..1f60cbdc64a 100644 --- a/dynamic-ssl/src/test/java/org/wildfly/security/dynamic/ssl/DynamicSSLTestUtils.java +++ b/dynamic-ssl/src/test/java/org/wildfly/security/dynamic/ssl/DynamicSSLTestUtils.java @@ -20,8 +20,6 @@ package org.wildfly.security.dynamic.ssl; import org.junit.Assert; -import org.wildfly.security.x500.cert.BasicConstraintsExtension; -import org.wildfly.security.x500.cert.X509CertificateBuilder; import javax.net.ssl.KeyManager; import javax.net.ssl.KeyManagerFactory; @@ -33,17 +31,15 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; -import java.math.BigInteger; -import java.security.KeyPair; -import java.security.KeyPairGenerator; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; -import java.security.PublicKey; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; +import org.wildfly.security.ssl.test.util.CAGenerationTool; +import org.wildfly.security.x500.cert.X509CertificateExtension; + /** * Utility class for DynamicSSLContextTest class. * @@ -54,10 +50,9 @@ public class DynamicSSLTestUtils { private static final String CLIENT_ALIAS = "client"; private static final String LOCALHOST_ALIAS = "localhost"; private static final String KEYSTORE_TYPE = "JKS"; - private static final String SHA_1_WITH_RSA = "SHA1withRSA"; private static final String TLS_PROTOCOL_VERSION = "TLSv1.2"; public static final String KEY_MANAGER_FACTORY_ALGORITHM = "SunX509"; - private static char[] PASSWORD = "secret".toCharArray(); + private static char[] PASSWORD = "Elytron".toCharArray(); private static File KEYSTORES_DIR = new File("./target/keystores"); private static String CLIENT1_KEYSTORE_FILENAME = "client1.keystore.jks"; @@ -92,6 +87,7 @@ static SSLContext createSSLContext(String keystorePath, String truststorePath, S KeyStore trustStore = KeyStore.getInstance(KEYSTORE_TYPE); trustStore.load(new FileInputStream(truststorePath), password.toCharArray()); + // Create trust manager TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(KEY_MANAGER_FACTORY_ALGORITHM); trustManagerFactory.init(trustStore); @@ -112,6 +108,7 @@ static void createKeystores() throws KeyStoreException, CertificateException, No if (!KEYSTORES_DIR.exists()) { KEYSTORES_DIR.mkdirs(); } + generateTwoWaySSLKeystoresAndTruststores(CLIENT1_KEYSTORE_FILENAME, SERVER1_KEYSTORE_FILENAME, CLIENT1_TRUSTSTORE_FILENAME, SERVER1_TRUSTSTORE_FILENAME); generateTwoWaySSLKeystoresAndTruststores(CLIENT2_KEYSTORE_FILENAME, SERVER2_KEYSTORE_FILENAME, CLIENT2_TRUSTSTORE_FILENAME, SERVER2_TRUSTSTORE_FILENAME); generateTwoWaySSLKeystoresAndTruststores(CLIENT3_KEYSTORE_FILENAME, SERVER3_KEYSTORE_FILENAME, CLIENT3_TRUSTSTORE_FILENAME, SERVER3_TRUSTSTORE_FILENAME); @@ -120,57 +117,30 @@ static void createKeystores() throws KeyStoreException, CertificateException, No private static void generateTwoWaySSLKeystoresAndTruststores(String clientKeystoreFilename, String serverKeystoreFilename, String clientTruststoreFilename, String serverTruststoreFilename) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException { - // Generates client certificate and keystore - KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); - KeyStore clientKeyStore = KeyStore.getInstance(KEYSTORE_TYPE); - clientKeyStore.load(null, null); - - KeyPair clientKeyPair = keyPairGenerator.generateKeyPair(); - PrivateKey signingKey = clientKeyPair.getPrivate(); - PublicKey publicKey = clientKeyPair.getPublic(); - - X500Principal testClient10DN = new X500Principal("CN=" + CLIENT_ALIAS); - X509Certificate clientCertificate = new X509CertificateBuilder() - .setIssuerDn(testClient10DN) - .setSubjectDn(new X500Principal("OU=Elytron")) - .setSignatureAlgorithmName(SHA_1_WITH_RSA) - .setSigningKey(signingKey) - .setPublicKey(publicKey) - .setSerialNumber(new BigInteger("3")) - .addExtension(new BasicConstraintsExtension(false, false, -1)) - .build(); - clientKeyStore.setKeyEntry(CLIENT_ALIAS, signingKey, PASSWORD, new X509Certificate[]{clientCertificate}); - - - // Generates server certificate and keystore - KeyStore serverKeyStore = KeyStore.getInstance(KEYSTORE_TYPE); - serverKeyStore.load(null, null); - - KeyPair serverKeyPair = keyPairGenerator.generateKeyPair(); - PrivateKey serverSigningKey = serverKeyPair.getPrivate(); - PublicKey serverPublicKey = serverKeyPair.getPublic(); - - X500Principal testServer10DN = new X500Principal("CN=" + LOCALHOST_ALIAS); - X509Certificate serverCertificate = new X509CertificateBuilder() - .setIssuerDn(testServer10DN) - .setSubjectDn(new X500Principal("OU=Elytron")) - .setSignatureAlgorithmName(SHA_1_WITH_RSA) - .setSigningKey(serverSigningKey) - .setPublicKey(serverPublicKey) - .setSerialNumber(new BigInteger("4")) - .addExtension(new BasicConstraintsExtension(false, false, -1)) - .build(); - serverKeyStore.setKeyEntry(LOCALHOST_ALIAS, serverSigningKey, PASSWORD, new X509Certificate[]{serverCertificate}); - - File clientKeystoreFile = new File(KEYSTORES_DIR, clientKeystoreFilename); - try (FileOutputStream clientStream = new FileOutputStream(clientKeystoreFile)) { - clientKeyStore.store(clientStream, PASSWORD); + CAGenerationTool caGenerationTool = null; + try { + caGenerationTool = CAGenerationTool.builder() + .setBaseDir(KEYSTORES_DIR.getCanonicalPath()) + .setRequestIdentities(CAGenerationTool.Identity.values()) + .build(); + } catch(Exception e) { + e.printStackTrace(); + Assert.fail(); } - File serverKeystoreFile = new File(KEYSTORES_DIR, serverKeystoreFilename); - try (FileOutputStream serverStream = new FileOutputStream(serverKeystoreFile)) { - serverKeyStore.store(serverStream, PASSWORD); - } + // Generates client certificate + X509Certificate clientCertificate = caGenerationTool.createIdentity(CLIENT_ALIAS, + new X500Principal("OU=Elytron"), + clientKeystoreFilename, + CAGenerationTool.Identity.CA, + new X509CertificateExtension[]{}); + + // Generates server certificate + X509Certificate serverCertificate = caGenerationTool.createIdentity(LOCALHOST_ALIAS, + new X500Principal("OU=Elytron"), + serverKeystoreFilename, + CAGenerationTool.Identity.CA, + new X509CertificateExtension[]{}); // create truststores KeyStore clientTrustStore = KeyStore.getInstance(KEYSTORE_TYPE); @@ -178,8 +148,9 @@ private static void generateTwoWaySSLKeystoresAndTruststores(String clientKeysto KeyStore serverTrustStore = KeyStore.getInstance(KEYSTORE_TYPE); serverTrustStore.load(null, null); - clientTrustStore.setCertificateEntry(LOCALHOST_ALIAS, serverKeyStore.getCertificate(LOCALHOST_ALIAS)); - serverTrustStore.setCertificateEntry(CLIENT_ALIAS, clientKeyStore.getCertificate(CLIENT_ALIAS) ); + + clientTrustStore.setCertificateEntry(LOCALHOST_ALIAS, serverCertificate); + serverTrustStore.setCertificateEntry(CLIENT_ALIAS, clientCertificate); File clientTrustFile = new File(KEYSTORES_DIR, clientTruststoreFilename); try (FileOutputStream clientStream = new FileOutputStream(clientTrustFile)) { diff --git a/dynamic-ssl/src/test/java/org/wildfly/security/dynamic/ssl/SSLServerSocketTestInstance.java b/dynamic-ssl/src/test/java/org/wildfly/security/dynamic/ssl/SSLServerSocketTestInstance.java index e404fd3e622..b69715f1437 100644 --- a/dynamic-ssl/src/test/java/org/wildfly/security/dynamic/ssl/SSLServerSocketTestInstance.java +++ b/dynamic-ssl/src/test/java/org/wildfly/security/dynamic/ssl/SSLServerSocketTestInstance.java @@ -59,7 +59,7 @@ void setConfiguredEnabledCipherSuites(String[] configuredEnabledCipherSuite) { } public void run() { - String password = "secret"; + String password = "Elytron"; SSLContext sslContext = DynamicSSLTestUtils.createSSLContext(this.keystorePath, this.truststorePath, password); try { SSLServerSocketFactory sslServerSocketFactory = sslContext.getServerSocketFactory(); diff --git a/dynamic-ssl/src/test/resources/org/wildfly/security/dynamic/ssl/wildfly-config-dynamic-ssl-test-without-default-sslcontext.xml b/dynamic-ssl/src/test/resources/org/wildfly/security/dynamic/ssl/wildfly-config-dynamic-ssl-test-without-default-sslcontext.xml index 07bfe16b243..4bfe9365125 100644 --- a/dynamic-ssl/src/test/resources/org/wildfly/security/dynamic/ssl/wildfly-config-dynamic-ssl-test-without-default-sslcontext.xml +++ b/dynamic-ssl/src/test/resources/org/wildfly/security/dynamic/ssl/wildfly-config-dynamic-ssl-test-without-default-sslcontext.xml @@ -22,27 +22,27 @@ - + - + - + - + - + - + @@ -52,7 +52,7 @@ - + @@ -61,7 +61,7 @@ - + @@ -70,7 +70,7 @@ - + diff --git a/dynamic-ssl/src/test/resources/org/wildfly/security/dynamic/ssl/wildfly-config-dynamic-ssl-test.xml b/dynamic-ssl/src/test/resources/org/wildfly/security/dynamic/ssl/wildfly-config-dynamic-ssl-test.xml index 5e01db70445..e857cbb9d08 100644 --- a/dynamic-ssl/src/test/resources/org/wildfly/security/dynamic/ssl/wildfly-config-dynamic-ssl-test.xml +++ b/dynamic-ssl/src/test/resources/org/wildfly/security/dynamic/ssl/wildfly-config-dynamic-ssl-test.xml @@ -22,38 +22,38 @@ - + - + - + - + - + - + - + - + @@ -63,7 +63,7 @@ - + @@ -72,7 +72,7 @@ - + @@ -81,7 +81,7 @@ - + @@ -90,7 +90,7 @@ - + diff --git a/encryption/pom.xml b/encryption/pom.xml index 193f81c319d..de9ed3fea5f 100644 --- a/encryption/pom.xml +++ b/encryption/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT 4.0.0 diff --git a/http/base/pom.xml b/http/base/pom.xml index 06370d1c6d3..5fb11808f14 100644 --- a/http/base/pom.xml +++ b/http/base/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../pom.xml diff --git a/http/basic/pom.xml b/http/basic/pom.xml index 3690a681977..382d0f54c79 100644 --- a/http/basic/pom.xml +++ b/http/basic/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../pom.xml diff --git a/http/basic/src/main/java/org/wildfly/security/http/basic/BasicAuthenticationMechanism.java b/http/basic/src/main/java/org/wildfly/security/http/basic/BasicAuthenticationMechanism.java index be1ce0e9688..25dc84b08ae 100644 --- a/http/basic/src/main/java/org/wildfly/security/http/basic/BasicAuthenticationMechanism.java +++ b/http/basic/src/main/java/org/wildfly/security/http/basic/BasicAuthenticationMechanism.java @@ -42,6 +42,7 @@ import org.wildfly.common.iteration.ByteIterator; import org.wildfly.security.auth.callback.AvailableRealmsCallback; import org.wildfly.security.http.HttpAuthenticationException; +import org.wildfly.security.http.HttpConstants; import org.wildfly.security.http.HttpServerRequest; import org.wildfly.security.http.HttpServerResponse; import org.wildfly.security.mechanism.http.UsernamePasswordAuthenticationMechanism; @@ -170,7 +171,7 @@ public void evaluateRequest(final HttpServerRequest request) throws HttpAuthenti httpBasic.debugf("User %s authorization failed.", username); fail(); - request.authenticationFailed(httpBasic.authorizationFailed(username), response -> prepareResponse(request, displayRealmName, response)); + request.authenticationFailed(httpBasic.authorizationFailed(username), response -> response.setStatusCode(HttpConstants.FORBIDDEN)); return; } diff --git a/http/bearer/pom.xml b/http/bearer/pom.xml index 29b5f908d29..c7ca60a5060 100644 --- a/http/bearer/pom.xml +++ b/http/bearer/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../pom.xml diff --git a/http/cert/pom.xml b/http/cert/pom.xml index e5fe1afd830..669a855053d 100644 --- a/http/cert/pom.xml +++ b/http/cert/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../pom.xml diff --git a/http/deprecated/pom.xml b/http/deprecated/pom.xml index 4cb7fa865c5..190c1e7adc2 100644 --- a/http/deprecated/pom.xml +++ b/http/deprecated/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../pom.xml diff --git a/http/digest/pom.xml b/http/digest/pom.xml index 187158d2dee..8f6d77deb59 100644 --- a/http/digest/pom.xml +++ b/http/digest/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../pom.xml diff --git a/http/external/pom.xml b/http/external/pom.xml index fdf26ca42f8..3951119cd99 100644 --- a/http/external/pom.xml +++ b/http/external/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../pom.xml diff --git a/http/external/src/main/java/org/wildfly/security/http/external/ExternalAuthenticationMechanism.java b/http/external/src/main/java/org/wildfly/security/http/external/ExternalAuthenticationMechanism.java index 8dc6da9b21a..bd6021da8cc 100644 --- a/http/external/src/main/java/org/wildfly/security/http/external/ExternalAuthenticationMechanism.java +++ b/http/external/src/main/java/org/wildfly/security/http/external/ExternalAuthenticationMechanism.java @@ -59,19 +59,24 @@ public void evaluateRequest(HttpServerRequest request) throws HttpAuthentication String remoteUser = request.getRemoteUser(); if (remoteUser == null) { + httpExternal.trace("The remote-user was not obtained from the request"); request.noAuthenticationInProgress(); return; } if (authorize(remoteUser)) { + httpExternal.tracef("Authorization of user [%s] succeed", remoteUser); succeed(request); } else { + httpExternal.tracef("Authorization of user [%s] failed", remoteUser); fail(request); } } private boolean authorize(String username) throws HttpAuthenticationException { + httpExternal.tracef("Authorizing username: [%s]",username); + AuthorizeCallback authorizeCallback = new AuthorizeCallback(username, username); try { MechanismUtil.handleCallbacks(httpExternal, callbackHandler, authorizeCallback); @@ -88,6 +93,7 @@ private void succeed(HttpServerRequest request) throws HttpAuthenticationExcepti MechanismUtil.handleCallbacks(httpExternal, callbackHandler, AuthenticationCompleteCallback.SUCCEEDED); request.authenticationComplete(); } catch (AuthenticationMechanismException e) { + httpExternal.trace("Failed to complete successful authentication", e); throw e.toHttpAuthenticationException(); } catch (UnsupportedCallbackException e) { throw httpExternal.mechCallbackHandlerFailedForUnknownReason(e).toHttpAuthenticationException(); @@ -99,6 +105,7 @@ private void fail(HttpServerRequest request) throws HttpAuthenticationException MechanismUtil.handleCallbacks(httpExternal, callbackHandler, AuthenticationCompleteCallback.FAILED); request.authenticationFailed(httpExternal.authenticationFailed(), response -> response.setStatusCode(FORBIDDEN)); } catch (AuthenticationMechanismException e) { + httpExternal.trace("Failed authentication not completed", e); throw e.toHttpAuthenticationException(); } catch (UnsupportedCallbackException e) { throw httpExternal.mechCallbackHandlerFailedForUnknownReason(e).toHttpAuthenticationException(); diff --git a/http/form/pom.xml b/http/form/pom.xml index 6703cc6e6c7..2b72dc32603 100644 --- a/http/form/pom.xml +++ b/http/form/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../pom.xml diff --git a/http/oidc/pom.xml b/http/oidc/pom.xml index 0d98cb9cdae..f0a272321fb 100644 --- a/http/oidc/pom.xml +++ b/http/oidc/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../pom.xml @@ -169,7 +169,7 @@ test - org.glassfish + org.eclipse.parsson jakarta.json test diff --git a/http/oidc/src/main/java/org/wildfly/security/http/oidc/Oidc.java b/http/oidc/src/main/java/org/wildfly/security/http/oidc/Oidc.java index 575809f2f4b..c6b38c9ef4d 100644 --- a/http/oidc/src/main/java/org/wildfly/security/http/oidc/Oidc.java +++ b/http/oidc/src/main/java/org/wildfly/security/http/oidc/Oidc.java @@ -45,7 +45,13 @@ public class Oidc { public static final String ACCEPT = "Accept"; + public static final String ADAPTER_STATE_COOKIE_PATH = "adapter-state-cookie-path"; + public static final String ALLOW_ANY_HOSTNAME = "allow-any-hostname"; + public static final String ALWAYS_REFRESH_TOKEN = "always-refresh-token"; + public static final String AUTH_SERVER_URL = "auth-server-url"; public static final String AUTHENTICATION_REQUEST_FORMAT = "authentication-request-format"; + public static final String AUTODETECT_BEARER_ONLY = "autodetect-bearer-only"; + public static final String BEARER_ONLY = "bearer-only"; public static final String OIDC_NAME = "OIDC"; public static final String JSON_CONTENT_TYPE = "application/json"; public static final String HTML_CONTENT_TYPE = "text/html"; @@ -55,14 +61,27 @@ public class Oidc { public static final String KEYCLOAK_REALMS_PATH = "realms/"; public static final String JSON_CONFIG_CONTEXT_PARAM = "org.wildfly.security.http.oidc.json.config"; static final String ACCOUNT_PATH = "account"; + public static final String CORS_MAX_AGE = "cors-max-age"; + public static final String CORS_ALLOWED_HEADERS = "cors-allowed-headers"; + public static final String CORS_ALLOWED_METHODS = "cors-allowed-methods"; + public static final String CORS_EXPOSED_HEADERS = "cors-exposed-headers"; + public static final String CONNECTION_POOL_SIZE = "connection-pool-size"; public static final String CLIENTS_MANAGEMENT_REGISTER_NODE_PATH = "clients-managements/register-node"; public static final String CLIENTS_MANAGEMENT_UNREGISTER_NODE_PATH = "clients-managements/unregister-node"; + public static final String CREDENTIALS = "credentials"; + public static final String DISABLE_TRUST_MANAGER = "disable-trust-manager"; public static final String SLASH = "/"; public static final String OIDC_CLIENT_CONTEXT_KEY = OidcClientContext.class.getName(); public static final String CLIENT_ID = "client_id"; + public static final String CLIENT_ID_JSON_VALUE = "client-id"; + public static final String CLIENT_KEYSTORE = "client-keystore"; + public static final String CLIENT_KEYSTORE_PASSWORD = "client-keystore-password"; + public static final String CLIENT_KEY_PASSWORD = "client-key-password"; public static final String CODE = "code"; + public static final String ENABLE_CORS = "enable-cors"; public static final String ERROR = "error"; public static final String ERROR_DESCRIPTION = "error_description"; + public static final String EXPOSE_TOKEN = "expose-token"; public static final String FACES_REQUEST = "Faces-Request"; public static final String GRANT_TYPE = "grant_type"; public static final String INVALID_TOKEN = "invalid_token"; @@ -74,9 +93,17 @@ public class Oidc { public static final String OPTIONS = "OPTIONS"; public static final String PARTIAL = "partial/"; public static final String PASSWORD = "password"; + public static final String PRINCIPAL_ATTRIBUTE = "principal-attribute"; public static final String PROMPT = "prompt"; + public static final String PROXY_URL = "proxy-url"; + public static final String PUBLIC_CLIENT = "public-client"; + public static final String REALM = "realm"; + public static final String REALM_PUBLIC_KEY = "realm-public-key"; + public static final String REGISTER_NODE_AT_STARTUP = "register-node-at-startup"; + public static final String REGISTER_NODE_PERIOD = "register-node-period"; public static final String REQUEST = "request"; public static final String REQUEST_URI = "request_uri"; + public static final String RESOURCE = "resource"; public static final String SCOPE = "scope"; public static final String UI_LOCALES = "ui_locales"; public static final String USERNAME = "username"; @@ -86,6 +113,7 @@ public class Oidc { public static final String RESPONSE_TYPE = "response_type"; public static final String SESSION_STATE = "session_state"; public static final String SOAP_ACTION = "SOAPAction"; + public static final String SSL_REQUIRED = "ssl-required"; public static final String STALE_TOKEN = "Stale token"; public static final String STATE = "state"; public static final int INVALID_ISSUED_FOR_CLAIM = -1; @@ -118,8 +146,33 @@ public class Oidc { static final String DEFAULT_TOKEN_SIGNATURE_ALGORITHM = "RS256"; public static final String DISABLE_TYP_CLAIM_VALIDATION_PROPERTY_NAME = "wildfly.elytron.oidc.disable.typ.claim.validation"; public static final String ALLOW_QUERY_PARAMS_PROPERTY_NAME = "wildfly.elytron.oidc.allow.query.params"; + public static final String TOKEN_MINIMUM_TIME_TO_LIVE = "token-minimum-time-to-live"; + public static final String TOKEN_SIGNATURE_ALGORITHM = "token-signature-algorithm"; + public static final String TOKEN_STORE = "token-store"; + public static final String TRUSTSTORE = "truststore"; + public static final String TRUSTSTORE_PASSWORD = "truststore-password"; + public static final String TURN_OFF_CHANGE_SESSION_ID_ON_LOGIN = "turn-off-change-session-id-on-login"; + public static final String USE_RESOURCE_ROLE_MAPPINGS = "use-resource-role-mappings"; + public static final String USE_REALM_ROLE_MAPPINGS = "use-realm-role-mappings"; public static final String X_REQUESTED_WITH = "X-Requested-With"; public static final String XML_HTTP_REQUEST = "XMLHttpRequest"; + public static final String MIN_TIME_BETWEEN_JWKS_REQUESTS = "min-time-between-jwks-requests"; + public static final String PUBLIC_KEY_CACHE_TTL = "public-key-cache-ttl"; + public static final String IGNORE_OAUTH_QUERY_PARAMETER = "ignore-oauth-query-parameter"; + public static final String VERIFY_TOKEN_AUDIENCE = "verify-token-audience"; + public static final String REQUEST_OBJECT_SIGNING_ALGORITHM = "request-object-signing-algorithm"; + public static final String REQUEST_OBJECT_ENCRYPTION_ALG_VALUE = "request-object-encryption-alg-value"; + public static final String REQUEST_OBJECT_ENCRYPTION_ENC_VALUE = "request-object-encryption-enc-value"; + public static final String REQUEST_OBJECT_SIGNING_KEYSTORE_FILE = "request-object-signing-keystore-file"; + public static final String REQUEST_OBJECT_SIGNING_KEYSTORE_PASSWORD = "request-object-signing-keystore-password"; + public static final String REQUEST_OBJECT_SIGNING_KEY_PASSWORD = "request-object-signing-key-password"; + public static final String REQUEST_OBJECT_SIGNING_KEY_ALIAS = "request-object-signing-key-alias"; + public static final String REQUEST_OBJECT_SIGNING_KEYSTORE_TYPE = "request-object-signing-keystore-type"; + public static final String REDIRECT_REWRITE_RULES = "redirect-rewrite-rules"; + public static final String ENABLE_PKCE = "enable-pkce"; + public static final String CONFIDENTIAL_PORT = "confidential-port"; + public static final String ENABLE_BASIC_AUTH = "enable-basic-auth"; + public static final String PROVIDER_URL = "provider-url"; /** * Bearer token pattern. diff --git a/http/oidc/src/main/java/org/wildfly/security/http/oidc/OidcJsonConfiguration.java b/http/oidc/src/main/java/org/wildfly/security/http/oidc/OidcJsonConfiguration.java index 29d2d785e3c..4f107b79591 100644 --- a/http/oidc/src/main/java/org/wildfly/security/http/oidc/OidcJsonConfiguration.java +++ b/http/oidc/src/main/java/org/wildfly/security/http/oidc/OidcJsonConfiguration.java @@ -19,6 +19,61 @@ package org.wildfly.security.http.oidc; import static org.wildfly.security.http.oidc.Oidc.DEFAULT_TOKEN_SIGNATURE_ALGORITHM; +import static org.wildfly.security.http.oidc.Oidc.ADAPTER_STATE_COOKIE_PATH; +import static org.wildfly.security.http.oidc.Oidc.ALLOW_ANY_HOSTNAME; +import static org.wildfly.security.http.oidc.Oidc.ALWAYS_REFRESH_TOKEN; +import static org.wildfly.security.http.oidc.Oidc.AUTH_SERVER_URL; +import static org.wildfly.security.http.oidc.Oidc.AUTHENTICATION_REQUEST_FORMAT; +import static org.wildfly.security.http.oidc.Oidc.AUTODETECT_BEARER_ONLY; +import static org.wildfly.security.http.oidc.Oidc.BEARER_ONLY; +import static org.wildfly.security.http.oidc.Oidc.CLIENT_ID_JSON_VALUE; +import static org.wildfly.security.http.oidc.Oidc.CLIENT_KEYSTORE; +import static org.wildfly.security.http.oidc.Oidc.CLIENT_KEYSTORE_PASSWORD; +import static org.wildfly.security.http.oidc.Oidc.CLIENT_KEY_PASSWORD; +import static org.wildfly.security.http.oidc.Oidc.CONFIDENTIAL_PORT; +import static org.wildfly.security.http.oidc.Oidc.CONNECTION_POOL_SIZE; +import static org.wildfly.security.http.oidc.Oidc.CORS_ALLOWED_HEADERS; +import static org.wildfly.security.http.oidc.Oidc.CORS_ALLOWED_METHODS; +import static org.wildfly.security.http.oidc.Oidc.CORS_EXPOSED_HEADERS; +import static org.wildfly.security.http.oidc.Oidc.CORS_MAX_AGE; +import static org.wildfly.security.http.oidc.Oidc.CREDENTIALS; +import static org.wildfly.security.http.oidc.Oidc.DISABLE_TRUST_MANAGER; +import static org.wildfly.security.http.oidc.Oidc.ENABLE_BASIC_AUTH; +import static org.wildfly.security.http.oidc.Oidc.ENABLE_CORS; +import static org.wildfly.security.http.oidc.Oidc.ENABLE_PKCE; +import static org.wildfly.security.http.oidc.Oidc.EXPOSE_TOKEN; +import static org.wildfly.security.http.oidc.Oidc.IGNORE_OAUTH_QUERY_PARAMETER; +import static org.wildfly.security.http.oidc.Oidc.MIN_TIME_BETWEEN_JWKS_REQUESTS; +import static org.wildfly.security.http.oidc.Oidc.PRINCIPAL_ATTRIBUTE; +import static org.wildfly.security.http.oidc.Oidc.PROVIDER_URL; +import static org.wildfly.security.http.oidc.Oidc.PROXY_URL; +import static org.wildfly.security.http.oidc.Oidc.PUBLIC_CLIENT; +import static org.wildfly.security.http.oidc.Oidc.PUBLIC_KEY_CACHE_TTL; +import static org.wildfly.security.http.oidc.Oidc.REDIRECT_REWRITE_RULES; +import static org.wildfly.security.http.oidc.Oidc.REGISTER_NODE_AT_STARTUP; +import static org.wildfly.security.http.oidc.Oidc.REGISTER_NODE_PERIOD; +import static org.wildfly.security.http.oidc.Oidc.REALM; +import static org.wildfly.security.http.oidc.Oidc.REALM_PUBLIC_KEY; +import static org.wildfly.security.http.oidc.Oidc.RESOURCE; +import static org.wildfly.security.http.oidc.Oidc.REQUEST_OBJECT_ENCRYPTION_ALG_VALUE; +import static org.wildfly.security.http.oidc.Oidc.REQUEST_OBJECT_ENCRYPTION_ENC_VALUE; +import static org.wildfly.security.http.oidc.Oidc.REQUEST_OBJECT_SIGNING_ALGORITHM; +import static org.wildfly.security.http.oidc.Oidc.REQUEST_OBJECT_SIGNING_KEY_ALIAS; +import static org.wildfly.security.http.oidc.Oidc.REQUEST_OBJECT_SIGNING_KEY_PASSWORD; +import static org.wildfly.security.http.oidc.Oidc.REQUEST_OBJECT_SIGNING_KEYSTORE_FILE; +import static org.wildfly.security.http.oidc.Oidc.REQUEST_OBJECT_SIGNING_KEYSTORE_PASSWORD; +import static org.wildfly.security.http.oidc.Oidc.REQUEST_OBJECT_SIGNING_KEYSTORE_TYPE; +import static org.wildfly.security.http.oidc.Oidc.SCOPE; +import static org.wildfly.security.http.oidc.Oidc.SSL_REQUIRED; +import static org.wildfly.security.http.oidc.Oidc.TOKEN_MINIMUM_TIME_TO_LIVE; +import static org.wildfly.security.http.oidc.Oidc.TOKEN_SIGNATURE_ALGORITHM; +import static org.wildfly.security.http.oidc.Oidc.TOKEN_STORE; +import static org.wildfly.security.http.oidc.Oidc.TRUSTSTORE; +import static org.wildfly.security.http.oidc.Oidc.TRUSTSTORE_PASSWORD; +import static org.wildfly.security.http.oidc.Oidc.TURN_OFF_CHANGE_SESSION_ID_ON_LOGIN; +import static org.wildfly.security.http.oidc.Oidc.USE_RESOURCE_ROLE_MAPPINGS; +import static org.wildfly.security.http.oidc.Oidc.USE_REALM_ROLE_MAPPINGS; +import static org.wildfly.security.http.oidc.Oidc.VERIFY_TOKEN_AUDIENCE; import java.util.Map; import java.util.TreeMap; @@ -34,143 +89,143 @@ * @author John D. Ament * @author Farah Juma */ -@JsonPropertyOrder({"realm", "realm-public-key", "auth-server-url", "ssl-required", - "resource", "public-client", "credentials", - "use-resource-role-mappings", "use-realm-role-mappings", - "enable-cors", "cors-max-age", "cors-allowed-methods", "cors-exposed-headers", - "expose-token", "bearer-only", "autodetect-bearer-only", "connection-pool-size", - "allow-any-hostname", "disable-trust-manager", "truststore", "truststore-password", - "client-keystore", "client-keystore-password", "client-key-password", - "always-refresh-token", - "register-node-at-startup", "register-node-period", "token-store", "adapter-state-cookie-path", "principal-attribute", - "proxy-url", "turn-off-change-session-id-on-login", "token-minimum-time-to-live", - "min-time-between-jwks-requests", "public-key-cache-ttl", - "ignore-oauth-query-parameter", "verify-token-audience", "token-signature-algorithm", "scope", - "authentication-request-format", "request-object-signing-algorithm", "request-object-encryption-alg-value", - "request-object-encryption-enc-value", "request-object-signing-keystore-file", - "request-object-signing-keystore-password","request-object-signing-key-password", "request-object-signing-key-alias", - "request-object-signing-keystore-type" +@JsonPropertyOrder({REALM, REALM_PUBLIC_KEY, AUTH_SERVER_URL, SSL_REQUIRED, + RESOURCE, PUBLIC_CLIENT, CREDENTIALS, + USE_RESOURCE_ROLE_MAPPINGS, USE_REALM_ROLE_MAPPINGS, + ENABLE_CORS, CORS_MAX_AGE, CORS_ALLOWED_METHODS, CORS_EXPOSED_HEADERS, + EXPOSE_TOKEN, BEARER_ONLY, AUTODETECT_BEARER_ONLY, CONNECTION_POOL_SIZE, + ALLOW_ANY_HOSTNAME, DISABLE_TRUST_MANAGER, TRUSTSTORE, TRUSTSTORE_PASSWORD, + CLIENT_KEYSTORE, CLIENT_KEYSTORE_PASSWORD, CLIENT_KEY_PASSWORD, + ALWAYS_REFRESH_TOKEN, + REGISTER_NODE_AT_STARTUP, REGISTER_NODE_PERIOD, TOKEN_STORE, ADAPTER_STATE_COOKIE_PATH, PRINCIPAL_ATTRIBUTE, + PROXY_URL, TURN_OFF_CHANGE_SESSION_ID_ON_LOGIN, TOKEN_MINIMUM_TIME_TO_LIVE, + MIN_TIME_BETWEEN_JWKS_REQUESTS, PUBLIC_KEY_CACHE_TTL, + IGNORE_OAUTH_QUERY_PARAMETER, VERIFY_TOKEN_AUDIENCE, TOKEN_SIGNATURE_ALGORITHM, SCOPE, + AUTHENTICATION_REQUEST_FORMAT, REQUEST_OBJECT_SIGNING_ALGORITHM, REQUEST_OBJECT_ENCRYPTION_ALG_VALUE, + REQUEST_OBJECT_ENCRYPTION_ENC_VALUE, REQUEST_OBJECT_SIGNING_KEYSTORE_FILE, + REQUEST_OBJECT_SIGNING_KEYSTORE_PASSWORD,REQUEST_OBJECT_SIGNING_KEY_PASSWORD, REQUEST_OBJECT_SIGNING_KEY_ALIAS, + REQUEST_OBJECT_SIGNING_KEYSTORE_TYPE }) public class OidcJsonConfiguration { - @JsonProperty("allow-any-hostname") + @JsonProperty(ALLOW_ANY_HOSTNAME) protected boolean allowAnyHostname; - @JsonProperty("disable-trust-manager") + @JsonProperty(DISABLE_TRUST_MANAGER) protected boolean disableTrustManager; - @JsonProperty("truststore") + @JsonProperty(TRUSTSTORE) protected String truststore; - @JsonProperty("truststore-password") + @JsonProperty(TRUSTSTORE_PASSWORD) protected String truststorePassword; - @JsonProperty("client-keystore") + @JsonProperty(CLIENT_KEYSTORE) protected String clientKeystore; - @JsonProperty("client-keystore-password") + @JsonProperty(CLIENT_KEYSTORE_PASSWORD) protected String clientKeystorePassword; - @JsonProperty("client-key-password") + @JsonProperty(CLIENT_KEY_PASSWORD) protected String clientKeyPassword; - @JsonProperty("request-object-signing-keystore-file") + @JsonProperty(REQUEST_OBJECT_SIGNING_KEYSTORE_FILE) protected String requestObjectSigningKeyStoreFile; - @JsonProperty("request-object-signing-keystore-password") + @JsonProperty(REQUEST_OBJECT_SIGNING_KEYSTORE_PASSWORD) protected String requestObjectSigningKeyStorePassword; - @JsonProperty("request-object-signing-key-password") + @JsonProperty(REQUEST_OBJECT_SIGNING_KEY_PASSWORD) protected String requestObjectSigningKeyPassword; - @JsonProperty("request-object-signing-key-alias") + @JsonProperty(REQUEST_OBJECT_SIGNING_KEY_ALIAS) protected String requestObjectSigningKeyAlias; - @JsonProperty("request-object-signing-keystore-type") + @JsonProperty(REQUEST_OBJECT_SIGNING_KEYSTORE_TYPE) protected String requestObjectSigningKeyStoreType; - @JsonProperty("connection-pool-size") + @JsonProperty(CONNECTION_POOL_SIZE) protected int connectionPoolSize = 20; - @JsonProperty("always-refresh-token") + @JsonProperty(ALWAYS_REFRESH_TOKEN) protected boolean alwaysRefreshToken = false; - @JsonProperty("register-node-at-startup") + @JsonProperty(REGISTER_NODE_AT_STARTUP) protected boolean registerNodeAtStartup = false; - @JsonProperty("register-node-period") + @JsonProperty(REGISTER_NODE_PERIOD) protected int registerNodePeriod = -1; - @JsonProperty("token-store") + @JsonProperty(TOKEN_STORE) protected String tokenStore; - @JsonProperty("adapter-state-cookie-path") + @JsonProperty(ADAPTER_STATE_COOKIE_PATH) protected String tokenCookiePath; - @JsonProperty("principal-attribute") + @JsonProperty(PRINCIPAL_ATTRIBUTE) protected String principalAttribute; - @JsonProperty("turn-off-change-session-id-on-login") + @JsonProperty(TURN_OFF_CHANGE_SESSION_ID_ON_LOGIN) protected Boolean turnOffChangeSessionIdOnLogin; - @JsonProperty("token-minimum-time-to-live") + @JsonProperty(TOKEN_MINIMUM_TIME_TO_LIVE) protected int tokenMinimumTimeToLive = 0; - @JsonProperty("min-time-between-jwks-requests") + @JsonProperty(MIN_TIME_BETWEEN_JWKS_REQUESTS) protected int minTimeBetweenJwksRequests = 10; - @JsonProperty("public-key-cache-ttl") + @JsonProperty(PUBLIC_KEY_CACHE_TTL) protected int publicKeyCacheTtl = 86400; // 1 day // https://tools.ietf.org/html/rfc7636 - @JsonProperty("enable-pkce") + @JsonProperty(ENABLE_PKCE) protected boolean pkce = false; - @JsonProperty("ignore-oauth-query-parameter") + @JsonProperty(IGNORE_OAUTH_QUERY_PARAMETER) protected boolean ignoreOAuthQueryParameter = false; - @JsonProperty("verify-token-audience") + @JsonProperty(VERIFY_TOKEN_AUDIENCE) protected boolean verifyTokenAudience = false; - @JsonProperty("confidential-port") + @JsonProperty(CONFIDENTIAL_PORT) protected int confidentialPort; - @JsonProperty("resource") + @JsonProperty(RESOURCE) protected String resource; - @JsonProperty("use-resource-role-mappings") + @JsonProperty(USE_RESOURCE_ROLE_MAPPINGS) protected boolean useResourceRoleMappings; - @JsonProperty("use-realm-role-mappings") + @JsonProperty(USE_REALM_ROLE_MAPPINGS) protected boolean useRealmRoleMappings = true; - @JsonProperty("enable-cors") + @JsonProperty(ENABLE_CORS) protected boolean cors; - @JsonProperty("cors-max-age") + @JsonProperty(CORS_MAX_AGE) protected int corsMaxAge = -1; - @JsonProperty("cors-allowed-headers") + @JsonProperty(CORS_ALLOWED_HEADERS) protected String corsAllowedHeaders; - @JsonProperty("cors-allowed-methods") + @JsonProperty(CORS_ALLOWED_METHODS) protected String corsAllowedMethods; - @JsonProperty("cors-exposed-headers") + @JsonProperty(CORS_EXPOSED_HEADERS) protected String corsExposedHeaders; - @JsonProperty("expose-token") + @JsonProperty(EXPOSE_TOKEN) protected boolean exposeToken; - @JsonProperty("bearer-only") + @JsonProperty(BEARER_ONLY) protected boolean bearerOnly; - @JsonProperty("autodetect-bearer-only") + @JsonProperty(AUTODETECT_BEARER_ONLY) protected boolean autodetectBearerOnly; - @JsonProperty("enable-basic-auth") + @JsonProperty(ENABLE_BASIC_AUTH) protected boolean enableBasicAuth; - @JsonProperty("public-client") + @JsonProperty(PUBLIC_CLIENT) protected boolean publicClient; - @JsonProperty("credentials") + @JsonProperty(CREDENTIALS) protected Map credentials = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); - @JsonProperty("redirect-rewrite-rules") + @JsonProperty(REDIRECT_REWRITE_RULES) protected Map redirectRewriteRules; - @JsonProperty("realm") + @JsonProperty(REALM) protected String realm; - @JsonProperty("realm-public-key") + @JsonProperty(REALM_PUBLIC_KEY) protected String realmKey; - @JsonProperty("auth-server-url") + @JsonProperty(AUTH_SERVER_URL) protected String authServerUrl; - @JsonProperty("ssl-required") + @JsonProperty(SSL_REQUIRED) protected String sslRequired; - @JsonProperty("provider-url") + @JsonProperty(PROVIDER_URL) protected String providerUrl; - @JsonProperty("client-id") + @JsonProperty(CLIENT_ID_JSON_VALUE) protected String clientId; - @JsonProperty("token-signature-algorithm") + @JsonProperty(TOKEN_SIGNATURE_ALGORITHM) protected String tokenSignatureAlgorithm = DEFAULT_TOKEN_SIGNATURE_ALGORITHM; - @JsonProperty("scope") + @JsonProperty(SCOPE) protected String scope; - @JsonProperty("authentication-request-format") + @JsonProperty(AUTHENTICATION_REQUEST_FORMAT) protected String authenticationRequestFormat; - @JsonProperty("request-object-signing-algorithm") + @JsonProperty(REQUEST_OBJECT_SIGNING_ALGORITHM) protected String requestObjectSigningAlgorithm; - @JsonProperty("request-object-encryption-alg-value") + @JsonProperty(REQUEST_OBJECT_ENCRYPTION_ALG_VALUE) protected String requestObjectEncryptionAlgValue; - @JsonProperty("request-object-encryption-enc-value") + @JsonProperty(REQUEST_OBJECT_ENCRYPTION_ENC_VALUE) protected String requestObjectEncryptionEncValue; /** * The Proxy url to use for requests to the auth-server, configurable via the adapter config property {@code proxy-url}. */ - @JsonProperty("proxy-url") + @JsonProperty(PROXY_URL) protected String proxyUrl; public boolean isAllowAnyHostname() { diff --git a/http/oidc/src/main/java/org/wildfly/security/http/oidc/OidcProviderMetadata.java b/http/oidc/src/main/java/org/wildfly/security/http/oidc/OidcProviderMetadata.java index 6c964dbfe1b..7619a89b4b0 100644 --- a/http/oidc/src/main/java/org/wildfly/security/http/oidc/OidcProviderMetadata.java +++ b/http/oidc/src/main/java/org/wildfly/security/http/oidc/OidcProviderMetadata.java @@ -329,8 +329,8 @@ public void setClaimTypesSupported(List claimTypesSupported) { this.claimTypesSupported = claimTypesSupported; } - public Boolean getClaimsParameterSupported() { - return claimsParameterSupported; + public boolean getClaimsParameterSupported() { + return claimsParameterSupported == null ? false : claimsParameterSupported; } public void setClaimsParameterSupported(Boolean claimsParameterSupported) { @@ -345,16 +345,16 @@ public void setScopesSupported(List scopesSupported) { this.scopesSupported = scopesSupported; } - public Boolean getRequestParameterSupported() { - return requestParameterSupported; + public boolean getRequestParameterSupported() { + return requestParameterSupported == null ? false : requestParameterSupported; } public void setRequestParameterSupported(Boolean requestParameterSupported) { this.requestParameterSupported = requestParameterSupported; } - public Boolean getRequestUriParameterSupported() { - return requestUriParameterSupported; + public boolean getRequestUriParameterSupported() { + return requestUriParameterSupported == null ? false : requestUriParameterSupported; } public void setRequestUriParameterSupported(Boolean requestUriParameterSupported) { @@ -393,12 +393,12 @@ public void setRevocationEndpointAuthSigningAlgValuesSupported(List revo this.revocationEndpointAuthSigningAlgValuesSupported = revocationEndpointAuthSigningAlgValuesSupported; } - public Boolean getBackchannelLogoutSupported() { - return backchannelLogoutSupported; + public boolean getBackchannelLogoutSupported() { + return backchannelLogoutSupported == null ? false : backchannelLogoutSupported; } - public Boolean getBackchannelLogoutSessionSupported() { - return backchannelLogoutSessionSupported; + public boolean getBackchannelLogoutSessionSupported() { + return backchannelLogoutSessionSupported == null ? false : backchannelLogoutSessionSupported; } public void setBackchannelLogoutSessionSupported(Boolean backchannelLogoutSessionSupported) { @@ -416,8 +416,8 @@ public List getCodeChallengeMethodsSupported() { // KEYCLOAK-6771 Certificate Bound Token // https://tools.ietf.org/html/draft-ietf-oauth-mtls-08#section-6.2 - public Boolean getTlsClientCertificateBoundAccessTokens() { - return tlsClientCertificateBoundAccessTokens; + public boolean getTlsClientCertificateBoundAccessTokens() { + return tlsClientCertificateBoundAccessTokens == null ? false : tlsClientCertificateBoundAccessTokens; } public List getRequestObjectEncryptionAlgValuesSupported() { diff --git a/http/oidc/src/test/java/org/wildfly/security/http/oidc/OidcBaseTest.java b/http/oidc/src/test/java/org/wildfly/security/http/oidc/OidcBaseTest.java index b604af8a8f8..6eb698160a0 100644 --- a/http/oidc/src/test/java/org/wildfly/security/http/oidc/OidcBaseTest.java +++ b/http/oidc/src/test/java/org/wildfly/security/http/oidc/OidcBaseTest.java @@ -413,12 +413,12 @@ private void performAuthentication(InputStream oidcConfig, String username, Stri protected InputStream getOidcConfigurationInputStreamWithProviderUrl() { String oidcConfig = "{\n" + - " \"resource\" : \"" + CLIENT_ID + "\",\n" + - " \"public-client\" : \"false\",\n" + - " \"provider-url\" : \"" + KEYCLOAK_CONTAINER.getAuthServerUrl() + "/realms/" + TEST_REALM + "\",\n" + - " \"ssl-required\" : \"EXTERNAL\",\n" + - " \"credentials\" : {\n" + - " \"secret\" : \"" + CLIENT_SECRET + "\"\n" + + " \"" + Oidc.RESOURCE + "\" : \"" + CLIENT_ID + "\",\n" + + " \"" + Oidc.PUBLIC_CLIENT + "\" : \"false\",\n" + + " \"" + Oidc.PROVIDER_URL + "\" : \"" + KEYCLOAK_CONTAINER.getAuthServerUrl() + "/realms/" + TEST_REALM + "\",\n" + + " \"" + Oidc.SSL_REQUIRED + "\" : \"EXTERNAL\",\n" + + " \"" + Oidc.CREDENTIALS + "\" : {\n" + + " \"" + Oidc.ClientCredentialsProviderType.SECRET.getValue() + "\" : \"" + CLIENT_SECRET + "\"\n" + " }\n" + "}"; return new ByteArrayInputStream(oidcConfig.getBytes(StandardCharsets.UTF_8)); diff --git a/http/oidc/src/test/java/org/wildfly/security/http/oidc/OidcProviderMetadataTest.java b/http/oidc/src/test/java/org/wildfly/security/http/oidc/OidcProviderMetadataTest.java new file mode 100644 index 00000000000..3773451f682 --- /dev/null +++ b/http/oidc/src/test/java/org/wildfly/security/http/oidc/OidcProviderMetadataTest.java @@ -0,0 +1,378 @@ +/* + * JBoss, Home of Professional Open Source. + * Copyright 2024 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.security.http.oidc; + +import org.wildfly.security.jose.util.JsonSerialization; + +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.util.List; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +/** + * Test OIDC json config class to return of values. + */ +public class OidcProviderMetadataTest { + private static OidcProviderMetadata oidcProviderMetadata; + private static OidcProviderMetadata emptyOidcProviderMetadata; + private static OidcProviderMetadata withoutOptionalsOidcProviderMetadata; + + @BeforeClass + public static void setUp() throws IOException { + // load the control data + ByteArrayInputStream is = new ByteArrayInputStream(providerMetaData.getBytes()); + oidcProviderMetadata = JsonSerialization.readValue(is, OidcProviderMetadata.class); + is.close(); + + // control data to check variable inits in OidcProviderMetadata + is = new ByteArrayInputStream(emptyProviderMetaData.getBytes()); + emptyOidcProviderMetadata = JsonSerialization.readValue(is, OidcProviderMetadata.class); + is.close(); + + is = new ByteArrayInputStream(withoutOptionalsProviderMetaData.getBytes()); + withoutOptionalsOidcProviderMetadata = JsonSerialization.readValue(is, OidcProviderMetadata.class); + is.close(); + } + + @Test + public void testIssuer() throws Exception { + assertTrue("http://localhost:8080/realms/myrealm".equals(oidcProviderMetadata.getIssuer())); + assertTrue("http://localhost:8080/realms/myrealm".equals(withoutOptionalsOidcProviderMetadata.getIssuer())); + assertNull(emptyOidcProviderMetadata.getIssuer()); + } + + @Test + public void testAuthorizationEndpoint() throws Exception { + assertTrue("http://localhost:8080/realms/myrealm/protocol/openid-connect/auth".equals(oidcProviderMetadata.getAuthorizationEndpoint())); + assertTrue("http://localhost:8080/auth".equals(withoutOptionalsOidcProviderMetadata.getAuthorizationEndpoint())); + assertNull(emptyOidcProviderMetadata.getAuthorizationEndpoint()); + } + + @Test + public void testTokenEndpoint() throws Exception { + assertTrue("http://localhost:8080/realms/myrealm/protocol/openid-connect/token".equals(oidcProviderMetadata.getTokenEndpoint())); + assertTrue("http://localhost:8080/token".equals(withoutOptionalsOidcProviderMetadata.getTokenEndpoint())); + assertNull(emptyOidcProviderMetadata.getTokenEndpoint()); + } + + @Test + public void testIntrospectionEndpoint() throws Exception { + assertTrue("http://localhost:8080/realms/myrealm/protocol/openid-connect/token/introspect".equals(oidcProviderMetadata.getIntrospectionEndpoint())); + assertTrue("http://localhost:8080/introspect".equals(withoutOptionalsOidcProviderMetadata.getIntrospectionEndpoint())); + assertNull(emptyOidcProviderMetadata.getIntrospectionEndpoint()); + } + + @Test + public void testUserinfoEndpoint() throws Exception { + assertTrue("http://localhost:8080/realms/myrealm/protocol/openid-connect/userinfo".equals(oidcProviderMetadata.getUserinfoEndpoint())); + assertTrue("http://localhost:8080/userinfo".equals(withoutOptionalsOidcProviderMetadata.getUserinfoEndpoint())); + assertNull(emptyOidcProviderMetadata.getUserinfoEndpoint()); + } + + @Test + public void testLogoutEndpoint() throws Exception { + assertTrue("http://localhost:8080/realms/myrealm/protocol/openid-connect/logout".equals(oidcProviderMetadata.getLogoutEndpoint())); + assertTrue("http://localhost:8080/logout".equals(withoutOptionalsOidcProviderMetadata.getLogoutEndpoint())); + assertNull(emptyOidcProviderMetadata.getLogoutEndpoint()); + } + + @Test + public void testJwksUri() throws Exception { + assertTrue("http://localhost:8080/realms/myrealm/protocol/openid-connect/certs".equals(oidcProviderMetadata.getJwksUri())); + assertTrue("http://localhost:8080/certs".equals(withoutOptionalsOidcProviderMetadata.getJwksUri())); + assertNull(emptyOidcProviderMetadata.getJwksUri()); + } + + @Test + public void testCheckSessionIframe() throws Exception { + assertTrue("http://localhost:8080/realms/myrealm/protocol/openid-connect/login-status-iframe.html".equals(oidcProviderMetadata.getCheckSessionIframe())); + assertTrue("http://localhost:8080/login-status-iframe.html".equals(withoutOptionalsOidcProviderMetadata.getCheckSessionIframe())); + assertNull(emptyOidcProviderMetadata.getCheckSessionIframe()); + } + + @Test + public void testGrantTypesSupported() throws Exception { + List l = oidcProviderMetadata.getGrantTypesSupported(); + assertTrue(l.contains("refresh_token")); + assertNull(emptyOidcProviderMetadata.getGrantTypesSupported()); + } + + @Test + public void testResponseTypesSupported() throws Exception { + List l = oidcProviderMetadata.getResponseTypesSupported(); + assertTrue(l.contains("code id_token")); + assertNull(emptyOidcProviderMetadata.getResponseTypesSupported()); + } + + @Test + public void testSubjectTypesSupported() throws Exception { + List l = oidcProviderMetadata.getSubjectTypesSupported(); + assertTrue(l.contains("pairwise")); + assertNull(emptyOidcProviderMetadata.getSubjectTypesSupported()); + } + + @Test + public void testIdTokenSigningAlgValuesSupported() throws Exception { + List l = oidcProviderMetadata.getIdTokenSigningAlgValuesSupported(); + assertTrue(l.contains("HS256")); + assertNull(emptyOidcProviderMetadata.getIdTokenSigningAlgValuesSupported()); + } + + @Test + public void testIdTokenEncryptionAlgValuesSupported() throws Exception { + List l = oidcProviderMetadata.getIdTokenEncryptionAlgValuesSupported(); + assertTrue(l.contains("RSA1_5")); + assertNull(emptyOidcProviderMetadata.getIdTokenEncryptionAlgValuesSupported()); + } + + @Test + public void testIdTokenEncryptionEncValuesSupported() throws Exception { + List l = oidcProviderMetadata.getIdTokenEncryptionEncValuesSupported(); + assertTrue(l.contains("A128CBC-HS256")); + assertNull(emptyOidcProviderMetadata.getIdTokenEncryptionEncValuesSupported()); + } + + @Test + public void testUserInfoSigningAlgValuesSupported() throws Exception { + List l = oidcProviderMetadata.getUserInfoSigningAlgValuesSupported(); + assertTrue(l.contains("EdDSA")); + assertNull(emptyOidcProviderMetadata.getUserInfoSigningAlgValuesSupported()); + } + + @Test + public void testRequestObjectSigningAlgValuesSupported() throws Exception { + List l = oidcProviderMetadata.getRequestObjectSigningAlgValuesSupported(); + assertTrue(l.contains("RS384")); + assertNull(emptyOidcProviderMetadata.getRequestObjectSigningAlgValuesSupported()); + assertNull(withoutOptionalsOidcProviderMetadata.getRequestObjectSigningAlgValuesSupported()); + } + + @Test + public void testResponseModesSupported() throws Exception { + List l = oidcProviderMetadata.getResponseModesSupported(); + assertTrue(l.contains("query.jwt")); + assertNull(emptyOidcProviderMetadata.getResponseModesSupported()); + } + + @Test + public void testRegistrationEndpoint() throws Exception { + assertTrue("http://localhost:8080/realms/myrealm/clients-registrations/openid-connect".equals(oidcProviderMetadata.getRegistrationEndpoint())); + assertTrue("http://localhost:8080/openid-connect".equals(withoutOptionalsOidcProviderMetadata.getRegistrationEndpoint())); + assertNull(emptyOidcProviderMetadata.getRegistrationEndpoint()); + } + + @Test + public void testTokenEndpointAuthMethodsSupported() throws Exception { + List l = oidcProviderMetadata.getTokenEndpointAuthMethodsSupported(); + assertTrue(l.contains("client_secret_basic")); + assertNull(emptyOidcProviderMetadata.getTokenEndpointAuthMethodsSupported()); + } + + @Test + public void testTokenEndpointAuthSigningAlgValuesSupported() throws Exception { + List l = oidcProviderMetadata.getTokenEndpointAuthSigningAlgValuesSupported(); + assertTrue(l.contains("PS384")); + assertNull(emptyOidcProviderMetadata.getTokenEndpointAuthSigningAlgValuesSupported()); + } + + @Test + public void testClaimsSupported() throws Exception { + List l = oidcProviderMetadata.getClaimsSupported(); + assertTrue(l.contains("given_name")); + assertNull(emptyOidcProviderMetadata.getClaimsSupported()); + } + + @Test + public void testClaimTypesSupported() throws Exception { + List l = oidcProviderMetadata.getClaimTypesSupported(); + assertTrue(l.contains("normal")); + assertNull(emptyOidcProviderMetadata.getClaimTypesSupported()); + } + + @Test + public void testClaimsParameterSupported() throws Exception { + assertTrue(oidcProviderMetadata.getClaimsParameterSupported()); + assertFalse(withoutOptionalsOidcProviderMetadata.getClaimsParameterSupported()); + } + + @Test + public void testScopesSupported() throws Exception { + List l = oidcProviderMetadata.getScopesSupported(); + assertTrue(l.contains("offline_access")); + assertNull(emptyOidcProviderMetadata.getScopesSupported()); + } + + @Test + public void testRequestParameterSupported() throws Exception { + assertTrue(oidcProviderMetadata.getRequestParameterSupported()); + assertFalse(withoutOptionalsOidcProviderMetadata.getRequestParameterSupported()); + } + + @Test + public void testRequestUriParameterSupported() throws Exception { + assertTrue(oidcProviderMetadata.getRequestUriParameterSupported()); + assertFalse(withoutOptionalsOidcProviderMetadata.getRequestUriParameterSupported()); + } + + @Test + public void testPushedAuthorizationRequestEndpoint() throws Exception { + assertTrue("http://localhost:8080/realms/myrealm/protocol/openid-connect/ext/par/request".equals(oidcProviderMetadata.getPushedAuthorizationRequestEndpoint())); + assertNull(emptyOidcProviderMetadata.getPushedAuthorizationRequestEndpoint()); + assertNull(withoutOptionalsOidcProviderMetadata.getPushedAuthorizationRequestEndpoint()); + } + + @Test + public void testRevocationEndpoint() throws Exception { + assertTrue("http://localhost:8080/realms/myrealm/protocol/openid-connect/revoke".equals(oidcProviderMetadata.getRevocationEndpoint())); + assertTrue("http://localhost:8080/revoke".equals(withoutOptionalsOidcProviderMetadata.getRevocationEndpoint())); + assertNull(emptyOidcProviderMetadata.getRevocationEndpoint()); + } + + @Test + public void testRevocationEndpointAuthMethodsSupported() throws Exception { + List l = oidcProviderMetadata.getRevocationEndpointAuthMethodsSupported(); + assertTrue(l.contains("client_secret_basic")); + assertNull(emptyOidcProviderMetadata.getRevocationEndpointAuthMethodsSupported()); + } + + @Test + public void testRevocationEndpointAuthSigningAlgValuesSupported() throws Exception { + List l = oidcProviderMetadata.getRevocationEndpointAuthSigningAlgValuesSupported(); + assertTrue(l.contains("RS384")); + assertNull(emptyOidcProviderMetadata.getRevocationEndpointAuthSigningAlgValuesSupported()); + } + + @Test + public void testBackchannelLogoutSupported() throws Exception { + assertTrue(oidcProviderMetadata.getBackchannelLogoutSupported()); + assertFalse(withoutOptionalsOidcProviderMetadata.getBackchannelLogoutSupported()); + } + + @Test + public void testBackchannelLogoutSessionSupported() throws Exception { + assertTrue(oidcProviderMetadata.getBackchannelLogoutSessionSupported()); + assertFalse(withoutOptionalsOidcProviderMetadata.getBackchannelLogoutSessionSupported()); + } + + @Test + public void testCodeChallengeMethodsSupported() throws Exception { + List l = oidcProviderMetadata.getCodeChallengeMethodsSupported(); + assertTrue(l.contains("S256")); + assertNull(emptyOidcProviderMetadata.getCodeChallengeMethodsSupported()); + } + + @Test + public void testTlsClientCertificateBoundAccessTokens() throws Exception { + assertTrue(oidcProviderMetadata.getTlsClientCertificateBoundAccessTokens()); + assertFalse(withoutOptionalsOidcProviderMetadata.getTlsClientCertificateBoundAccessTokens()); + } + + @Test + public void testRequestObjectEncryptionEncValuesSupported() throws Exception { + List l = oidcProviderMetadata.getRequestObjectEncryptionEncValuesSupported(); + assertTrue(l.contains("A192GCM")); + assertNull(emptyOidcProviderMetadata.getRequestObjectEncryptionEncValuesSupported()); + assertNull(withoutOptionalsOidcProviderMetadata.getRequestObjectEncryptionEncValuesSupported()); + } + + @Test + public void testRequestObjectEncryptionAlgValuesSupported() throws Exception { + List l = oidcProviderMetadata.getRequestObjectEncryptionAlgValuesSupported(); + assertTrue(l.contains("RSA1_5")); + assertNull(emptyOidcProviderMetadata.getRequestObjectEncryptionAlgValuesSupported()); + assertNull(withoutOptionalsOidcProviderMetadata.getRequestObjectEncryptionAlgValuesSupported()); + } + + // Control data taken from keycloak + private static final String providerMetaData = "{\n" + + "\"issuer\":\"http://localhost:8080/realms/myrealm\"\n" + + ",\"authorization_endpoint\":\"http://localhost:8080/realms/myrealm/protocol/openid-connect/auth\"\n" + + ",\"token_endpoint\":\"http://localhost:8080/realms/myrealm/protocol/openid-connect/token\"\n" + + ",\"introspection_endpoint\":\"http://localhost:8080/realms/myrealm/protocol/openid-connect/token/introspect\"\n" + + ",\"userinfo_endpoint\":\"http://localhost:8080/realms/myrealm/protocol/openid-connect/userinfo\"\n" + + ",\"end_session_endpoint\":\"http://localhost:8080/realms/myrealm/protocol/openid-connect/logout\"\n" + + ",\"jwks_uri\":\"http://localhost:8080/realms/myrealm/protocol/openid-connect/certs\"\n" + + ",\"check_session_iframe\":\"http://localhost:8080/realms/myrealm/protocol/openid-connect/login-status-iframe.html\"\n" + + ",\"grant_types_supported\":[\"authorization_code\",\"implicit\",\"refresh_token\",\"password\",\"client_credentials\",\"urn:openid:params:grant-type:ciba\",\"urn:ietf:params:oauth:grant-type:device_code\"]\n" + + ",\"response_types_supported\":[\"code\",\"none\",\"id_token\",\"token\",\"id_token token\",\"code id_token\",\"code token\",\"code id_token token\"]\n" + + ",\"subject_types_supported\":[\"public\",\"pairwise\"]\n" + + ",\"id_token_signing_alg_values_supported\":[\"PS384\",\"RS384\",\"EdDSA\",\"ES384\",\"HS256\",\"HS512\",\"ES256\",\"RS256\",\"HS384\",\"ES512\",\"PS256\",\"PS512\",\"RS512\"]\n" + + ",\"id_token_encryption_alg_values_supported\":[\"RSA-OAEP\",\"RSA-OAEP-256\",\"RSA1_5\"]\n" + + ",\"id_token_encryption_enc_values_supported\":[\"A256GCM\",\"A192GCM\",\"A128GCM\",\"A128CBC-HS256\",\"A192CBC-HS384\",\"A256CBC-HS512\"]\n" + + ",\"userinfo_signing_alg_values_supported\":[\"PS384\",\"RS384\",\"EdDSA\",\"ES384\",\"HS256\",\"HS512\",\"ES256\",\"RS256\",\"HS384\",\"ES512\",\"PS256\",\"PS512\",\"RS512\",\"none\"]\n" + + ",\"request_object_signing_alg_values_supported\":[\"PS384\",\"RS384\",\"EdDSA\",\"ES384\",\"HS256\",\"HS512\",\"ES256\",\"RS256\",\"HS384\",\"ES512\",\"PS256\",\"PS512\",\"RS512\",\"none\"]\n" + + ",\"response_modes_supported\":[\"query\",\"fragment\",\"form_post\",\"query.jwt\",\"fragment.jwt\",\"form_post.jwt\",\"jwt\"]\n" + + ",\"registration_endpoint\":\"http://localhost:8080/realms/myrealm/clients-registrations/openid-connect\"\n" + + ",\"token_endpoint_auth_methods_supported\":[\"private_key_jwt\",\"client_secret_basic\",\"client_secret_post\",\"tls_client_auth\",\"client_secret_jwt\"]\n" + + ",\"token_endpoint_auth_signing_alg_values_supported\":[\"PS384\",\"RS384\",\"EdDSA\",\"ES384\",\"HS256\",\"HS512\",\"ES256\",\"RS256\",\"HS384\",\"ES512\",\"PS256\",\"PS512\",\"RS512\"]\n" + + ",\"claims_supported\":[\"aud\",\"sub\",\"iss\",\"auth_time\",\"name\",\"given_name\",\"family_name\",\"preferred_username\",\"email\",\"acr\"]\n" + + ",\"claim_types_supported\":[\"normal\"]\n" + + ",\"claims_parameter_supported\":true\n" + + ",\"scopes_supported\":[\"openid\",\"address\",\"profile\",\"offline_access\",\"microprofile-jwt\",\"acr\",\"web-origins\",\"basic\",\"email\",\"roles\",\"phone\"]\n" + + ",\"request_parameter_supported\":true\n" + + ",\"request_uri_parameter_supported\":true\n" + + ",\"pushed_authorization_request_endpoint\":\"http://localhost:8080/realms/myrealm/protocol/openid-connect/ext/par/request\"\n" + + ",\"revocation_endpoint\":\"http://localhost:8080/realms/myrealm/protocol/openid-connect/revoke\"\n" + + ",\"revocation_endpoint_auth_methods_supported\":[\"private_key_jwt\",\"client_secret_basic\",\"client_secret_post\",\"tls_client_auth\",\"client_secret_jwt\"]\n" + + ",\"revocation_endpoint_auth_signing_alg_values_supported\":[\"PS384\",\"RS384\",\"EdDSA\",\"ES384\",\"HS256\",\"HS512\",\"ES256\",\"RS256\",\"HS384\",\"ES512\",\"PS256\",\"PS512\",\"RS512\"]\n" + + ",\"backchannel_logout_supported\":true\n" + + ",\"backchannel_logout_session_supported\":true\n" + + ",\"code_challenge_methods_supported\":[\"plain\",\"S256\"]\n" + + ",\"tls_client_certificate_bound_access_tokens\":true\n" + + ",\"request_object_encryption_enc_values_supported\":[\"A256GCM\",\"A192GCM\",\"A128GCM\",\"A128CBC-HS256\",\"A192CBC-HS384\",\"A256CBC-HS512\"]\n" + + ",\"request_object_encryption_alg_values_supported\":[\"RSA-OAEP\",\"RSA-OAEP-256\",\"RSA1_5\"]\n" + + "}"; + + private static final String emptyProviderMetaData = "{}"; + + private static final String withoutOptionalsProviderMetaData = "{\n" + + "\"issuer\":\"http://localhost:8080/realms/myrealm\"\n" + + ",\"authorization_endpoint\":\"http://localhost:8080/auth\"\n" + + ",\"token_endpoint\":\"http://localhost:8080/token\"\n" + + ",\"introspection_endpoint\":\"http://localhost:8080/introspect\"\n" + + ",\"userinfo_endpoint\":\"http://localhost:8080/userinfo\"\n" + + ",\"end_session_endpoint\":\"http://localhost:8080/logout\"\n" + + ",\"jwks_uri\":\"http://localhost:8080/certs\"\n" + + ",\"check_session_iframe\":\"http://localhost:8080/login-status-iframe.html\"\n" + + ",\"grant_types_supported\":[\"authorization_code\",\"implicit\"]\n" + + ",\"response_types_supported\":[\"code\",\"none\",\"id_token\",\"token\"]\n" + + ",\"subject_types_supported\":[\"public\",\"pairwise\"]\n" + + ",\"id_token_signing_alg_values_supported\":[\"PS384\"]\n" + + ",\"id_token_encryption_alg_values_supported\":[\"RSA-OAEP\",\"RSA-OAEP-256\",\"RSA1_5\"]\n" + + ",\"id_token_encryption_enc_values_supported\":[\"A256GCM\"]\n" + + ",\"userinfo_signing_alg_values_supported\":[\"PS384\",\"none\"]\n" + + ",\"response_modes_supported\":[\"query\",\"fragment\",\"form_post.jwt\",\"jwt\"]\n" + + ",\"registration_endpoint\":\"http://localhost:8080/openid-connect\"\n" + + ",\"token_endpoint_auth_methods_supported\":[\"private_key_jwt\",\"client_secret_basic\"]\n" + + ",\"token_endpoint_auth_signing_alg_values_supported\":[\"PS384\",\"RS384\"]\n" + + ",\"claims_supported\":[\"aud\",\"sub\"]\n" + + ",\"claim_types_supported\":[\"normal\"]\n" + + ",\"scopes_supported\":[\"openid\",\"address\",\"profile\"]\n" + + ",\"revocation_endpoint\":\"http://localhost:8080/revoke\"\n" + + ",\"revocation_endpoint_auth_methods_supported\":[\"private_key_jwt\"]\n" + + ",\"revocation_endpoint_auth_signing_alg_values_supported\":[\"PS384\",\"RS384\",\"EdDSA\"]\n" + + ",\"code_challenge_methods_supported\":[\"plain\",\"S256\"]\n" + + "}"; +} diff --git a/http/oidc/src/test/java/org/wildfly/security/http/oidc/OidcTest.java b/http/oidc/src/test/java/org/wildfly/security/http/oidc/OidcTest.java index fdda1aac447..4dede8b5ed6 100644 --- a/http/oidc/src/test/java/org/wildfly/security/http/oidc/OidcTest.java +++ b/http/oidc/src/test/java/org/wildfly/security/http/oidc/OidcTest.java @@ -44,8 +44,28 @@ import static org.wildfly.security.http.oidc.KeycloakConfiguration.TENANT1_USER; import static org.wildfly.security.http.oidc.KeycloakConfiguration.TENANT2_PASSWORD; import static org.wildfly.security.http.oidc.KeycloakConfiguration.TENANT2_USER; +import static org.wildfly.security.http.oidc.Oidc.AUTH_SERVER_URL; +import static org.wildfly.security.http.oidc.Oidc.AUTHENTICATION_REQUEST_FORMAT; +import static org.wildfly.security.http.oidc.Oidc.CREDENTIALS; +import static org.wildfly.security.http.oidc.Oidc.ClientCredentialsProviderType; +import static org.wildfly.security.http.oidc.Oidc.PROVIDER_URL; import static org.wildfly.security.http.oidc.Oidc.OIDC_NAME; import static org.wildfly.security.http.oidc.Oidc.OIDC_SCOPE; +import static org.wildfly.security.http.oidc.Oidc.PUBLIC_CLIENT; +import static org.wildfly.security.http.oidc.Oidc.PRINCIPAL_ATTRIBUTE; +import static org.wildfly.security.http.oidc.Oidc.REQUEST_OBJECT_SIGNING_ALGORITHM; +import static org.wildfly.security.http.oidc.Oidc.REQUEST_OBJECT_SIGNING_KEYSTORE_FILE; +import static org.wildfly.security.http.oidc.Oidc.REQUEST_OBJECT_SIGNING_KEYSTORE_PASSWORD; +import static org.wildfly.security.http.oidc.Oidc.REQUEST_OBJECT_SIGNING_KEYSTORE_TYPE; +import static org.wildfly.security.http.oidc.Oidc.REQUEST_OBJECT_SIGNING_KEY_PASSWORD; +import static org.wildfly.security.http.oidc.Oidc.REQUEST_OBJECT_SIGNING_KEY_ALIAS; +import static org.wildfly.security.http.oidc.Oidc.REQUEST_OBJECT_ENCRYPTION_ALG_VALUE; +import static org.wildfly.security.http.oidc.Oidc.REQUEST_OBJECT_ENCRYPTION_ENC_VALUE; +import static org.wildfly.security.http.oidc.Oidc.RESOURCE; +import static org.wildfly.security.http.oidc.Oidc.REALM; +import static org.wildfly.security.http.oidc.Oidc.SCOPE; +import static org.wildfly.security.http.oidc.Oidc.SSL_REQUIRED; +import static org.wildfly.security.http.oidc.Oidc.TOKEN_SIGNATURE_ALGORITHM; import static org.wildfly.security.http.oidc.Oidc.AuthenticationRequestFormat.OAUTH2; import static org.wildfly.security.http.oidc.Oidc.AuthenticationRequestFormat.REQUEST; import static org.wildfly.security.http.oidc.Oidc.AuthenticationRequestFormat.REQUEST_URI; @@ -664,13 +684,13 @@ private InputStream getOidcConfigurationInputStream(String clientSecret) { private InputStream getOidcConfigurationInputStream(String clientSecret, String authServerUrl) { String oidcConfig = "{\n" + - " \"realm\" : \"" + TEST_REALM + "\",\n" + - " \"resource\" : \"" + CLIENT_ID + "\",\n" + - " \"public-client\" : \"false\",\n" + - " \"auth-server-url\" : \"" + authServerUrl + "\",\n" + - " \"ssl-required\" : \"EXTERNAL\",\n" + - " \"credentials\" : {\n" + - " \"secret\" : \"" + clientSecret + "\"\n" + + " \"" + REALM + "\" : \"" + TEST_REALM + "\",\n" + + " \"" + RESOURCE + "\" : \"" + CLIENT_ID + "\",\n" + + " \"" + PUBLIC_CLIENT + "\" : \"false\",\n" + + " \"" + AUTH_SERVER_URL + "\" : \"" + authServerUrl + "\",\n" + + " \"" + SSL_REQUIRED + "\" : \"EXTERNAL\",\n" + + " \"" + CREDENTIALS + "\" : {\n" + + " \"" + ClientCredentialsProviderType.SECRET.getValue() + "\" : \"" + clientSecret + "\"\n" + " }\n" + "}"; return new ByteArrayInputStream(oidcConfig.getBytes(StandardCharsets.UTF_8)); @@ -678,12 +698,12 @@ private InputStream getOidcConfigurationInputStream(String clientSecret, String private InputStream getOidcConfigurationInputStreamWithEnvironmentVariableExpression() { String oidcConfig = "{\n" + - " \"resource\" : \"" + CLIENT_ID + "\",\n" + - " \"public-client\" : \"false\",\n" + - " \"provider-url\" : \"" + KEYCLOAK_CONTAINER.getAuthServerUrl() + "${oidc.provider-url-env}\",\n" + - " \"ssl-required\" : \"EXTERNAL\",\n" + - " \"credentials\" : {\n" + - " \"secret\" : \"" + CLIENT_SECRET + "\"\n" + + " \"" + RESOURCE + "\" : \"" + CLIENT_ID + "\",\n" + + " \"" + PUBLIC_CLIENT + "\" : \"false\",\n" + + " \"" + PROVIDER_URL + "\" : \"" + KEYCLOAK_CONTAINER.getAuthServerUrl() + "${oidc.provider-url-env}\",\n" + + " \"" + SSL_REQUIRED + "\" : \"EXTERNAL\",\n" + + " \"" + CREDENTIALS + "\" : {\n" + + " \"" + ClientCredentialsProviderType.SECRET.getValue() + "\" : \"" + CLIENT_SECRET + "\"\n" + " }\n" + "}"; return new ByteArrayInputStream(oidcConfig.getBytes(StandardCharsets.UTF_8)); @@ -691,12 +711,12 @@ private InputStream getOidcConfigurationInputStreamWithEnvironmentVariableExpres private InputStream getOidcConfigurationInputStreamWithSystemPropertyExpression() { String oidcConfig = "{\n" + - " \"resource\" : \"" + CLIENT_ID + "\",\n" + - " \"public-client\" : \"false\",\n" + - " \"provider-url\" : \"${oidc.provider.url}\",\n" + - " \"ssl-required\" : \"EXTERNAL\",\n" + - " \"credentials\" : {\n" + - " \"secret\" : \"" + CLIENT_SECRET + "\"\n" + + " \"" + RESOURCE + "\" : \"" + CLIENT_ID + "\",\n" + + " \"" + PUBLIC_CLIENT + "\" : \"false\",\n" + + " \"" + PROVIDER_URL + "\" : \"${oidc.provider.url}\",\n" + + " \"" + SSL_REQUIRED + "\" : \"EXTERNAL\",\n" + + " \"" + CREDENTIALS + "\" : {\n" + + " \"" + ClientCredentialsProviderType.SECRET.getValue() + "\" : \"" + CLIENT_SECRET + "\"\n" + " }\n" + "}"; return new ByteArrayInputStream(oidcConfig.getBytes(StandardCharsets.UTF_8)); @@ -704,12 +724,12 @@ private InputStream getOidcConfigurationInputStreamWithSystemPropertyExpression( private InputStream getOidcConfigurationInputStreamWithProviderUrlTrailingSlash() { String oidcConfig = "{\n" + - " \"resource\" : \"" + CLIENT_ID + "\",\n" + - " \"public-client\" : \"false\",\n" + - " \"provider-url\" : \"" + KEYCLOAK_CONTAINER.getAuthServerUrl() + "/realms/" + TEST_REALM + "/" + "\",\n" + - " \"ssl-required\" : \"EXTERNAL\",\n" + - " \"credentials\" : {\n" + - " \"secret\" : \"" + CLIENT_SECRET + "\"\n" + + " \"" + RESOURCE + "\" : \"" + CLIENT_ID + "\",\n" + + " \"" + PUBLIC_CLIENT + "\" : \"false\",\n" + + " \"" + PROVIDER_URL + "\" : \"" + KEYCLOAK_CONTAINER.getAuthServerUrl() + "/realms/" + TEST_REALM + "/" + "\",\n" + + " \"" + SSL_REQUIRED + "\" : \"EXTERNAL\",\n" + + " \"" + CREDENTIALS + "\" : {\n" + + " \"" + ClientCredentialsProviderType.SECRET.getValue() + "\" : \"" + CLIENT_SECRET + "\"\n" + " }\n" + "}"; return new ByteArrayInputStream(oidcConfig.getBytes(StandardCharsets.UTF_8)); @@ -717,11 +737,11 @@ private InputStream getOidcConfigurationInputStreamWithProviderUrlTrailingSlash( private InputStream getOidcConfigurationMissingRequiredOption() { String oidcConfig = "{\n" + - " \"public-client\" : \"false\",\n" + - " \"provider-url\" : \"" + KEYCLOAK_CONTAINER.getAuthServerUrl() + "/realms/" + TEST_REALM + "\",\n" + - " \"ssl-required\" : \"EXTERNAL\",\n" + - " \"credentials\" : {\n" + - " \"secret\" : \"" + CLIENT_SECRET + "\"\n" + + " \"" + PUBLIC_CLIENT + "\" : \"false\",\n" + + " \"" + PROVIDER_URL + "\" : \"" + KEYCLOAK_CONTAINER.getAuthServerUrl() + "/realms/" + TEST_REALM + "\",\n" + + " \"" + SSL_REQUIRED + "\" : \"EXTERNAL\",\n" + + " \"" + CREDENTIALS + "\" : {\n" + + " \"" + ClientCredentialsProviderType.SECRET.getValue() + "\" : \"" + CLIENT_SECRET + "\"\n" + " }\n" + "}"; return new ByteArrayInputStream(oidcConfig.getBytes(StandardCharsets.UTF_8)); @@ -729,45 +749,43 @@ private InputStream getOidcConfigurationMissingRequiredOption() { private InputStream getOidcConfigurationInputStreamWithTokenSignatureAlgorithm() { String oidcConfig = "{\n" + - " \"token-signature-algorithm\" : \"RS256\",\n" + - " \"resource\" : \"" + CLIENT_ID + "\",\n" + - " \"public-client\" : \"false\",\n" + - " \"provider-url\" : \"" + KEYCLOAK_CONTAINER.getAuthServerUrl() + "/realms/" + TEST_REALM + "\",\n" + - " \"ssl-required\" : \"EXTERNAL\",\n" + - " \"credentials\" : {\n" + - " \"secret\" : \"" + CLIENT_SECRET + "\"\n" + + " \"" + TOKEN_SIGNATURE_ALGORITHM + "\" : \"RS256\",\n" + + " \"" + RESOURCE + "\" : \"" + CLIENT_ID + "\",\n" + + " \"" + PUBLIC_CLIENT + "\" : \"false\",\n" + + " \"" + PROVIDER_URL + "\" : \"" + KEYCLOAK_CONTAINER.getAuthServerUrl() + "/realms/" + TEST_REALM + "\",\n" + + " \"" + SSL_REQUIRED + "\" : \"EXTERNAL\",\n" + + " \"" + CREDENTIALS + "\" : {\n" + + " \"" + ClientCredentialsProviderType.SECRET.getValue() + "\" : \"" + CLIENT_SECRET + "\"\n" + " }\n" + "}"; return new ByteArrayInputStream(oidcConfig.getBytes(StandardCharsets.UTF_8)); } private InputStream getOidcConfigurationInputStreamWithScope(String scopeValue){ String oidcConfig = "{\n" + - " \"client-id\" : \"" + CLIENT_ID + "\",\n" + - " \"provider-url\" : \"" + KEYCLOAK_CONTAINER.getAuthServerUrl() + "/realms/" + TEST_REALM_WITH_SCOPES + "/" + "\",\n" + - " \"public-client\" : \"false\",\n" + - " \"scope\" : \"" + scopeValue + "\",\n" + - " \"ssl-required\" : \"EXTERNAL\",\n" + - " \"ssl-required\" : \"EXTERNAL\",\n" + - " \"credentials\" : {\n" + - " \"secret\" : \"" + CLIENT_SECRET + "\"\n" + + " \"" + Oidc.CLIENT_ID_JSON_VALUE + "\" : \"" + CLIENT_ID + "\",\n" + + " \"" + PROVIDER_URL + "\" : \"" + KEYCLOAK_CONTAINER.getAuthServerUrl() + "/realms/" + TEST_REALM_WITH_SCOPES + "/" + "\",\n" + + " \"" + PUBLIC_CLIENT + "\" : \"false\",\n" + + " \"" + SCOPE + "\" : \"" + scopeValue + "\",\n" + + " \"" + SSL_REQUIRED + "\" : \"EXTERNAL\",\n" + + " \"" + CREDENTIALS + "\" : {\n" + + " \"" + ClientCredentialsProviderType.SECRET.getValue() + "\" : \"" + CLIENT_SECRET + "\"\n" + " }\n" + "}"; return new ByteArrayInputStream(oidcConfig.getBytes(StandardCharsets.UTF_8)); } private InputStream getOidcConfigurationInputStreamWithRequestParameter(String requestParameter, String signingAlgorithm, String encryptionAlgorithm, String encMethod){ String oidcConfig = "{\n" + - " \"client-id\" : \"" + CLIENT_ID + "\",\n" + - " \"provider-url\" : \"" + KEYCLOAK_CONTAINER.getAuthServerUrl() + "/realms/" + TEST_REALM_WITH_SCOPES + "/" + "\",\n" + - " \"public-client\" : \"false\",\n" + - " \"ssl-required\" : \"EXTERNAL\",\n" + - " \"ssl-required\" : \"EXTERNAL\",\n" + - " \"authentication-request-format\" : \"" + requestParameter + "\",\n" + - " \"request-object-signing-algorithm\" : \"" + signingAlgorithm + "\",\n" + - " \"request-object-encryption-alg-value\" : \"" + encryptionAlgorithm + "\",\n" + - " \"request-object-encryption-enc-value\" : \"" + encMethod + "\",\n" + - " \"scope\" : \"profile email phone\",\n" + - " \"credentials\" : {\n" + - " \"secret\" : \"" + CLIENT_SECRET + "\"\n" + + " \"" + Oidc.CLIENT_ID_JSON_VALUE + "\" : \"" + CLIENT_ID + "\",\n" + + " \"" + PROVIDER_URL + "\" : \"" + KEYCLOAK_CONTAINER.getAuthServerUrl() + "/realms/" + TEST_REALM_WITH_SCOPES + "/" + "\",\n" + + " \"" + PUBLIC_CLIENT + "\" : \"false\",\n" + + " \"" + SSL_REQUIRED + "\" : \"EXTERNAL\",\n" + + " \"" + AUTHENTICATION_REQUEST_FORMAT + "\" : \"" + requestParameter + "\",\n" + + " \"" + REQUEST_OBJECT_SIGNING_ALGORITHM + "\" : \"" + signingAlgorithm + "\",\n" + + " \"" + REQUEST_OBJECT_ENCRYPTION_ALG_VALUE + "\" : \"" + encryptionAlgorithm + "\",\n" + + " \"" + REQUEST_OBJECT_ENCRYPTION_ENC_VALUE + "\" : \"" + encMethod + "\",\n" + + " \"" + SCOPE + "\" : \"profile email phone\",\n" + + " \"" + CREDENTIALS + "\" : {\n" + + " \"" + ClientCredentialsProviderType.SECRET.getValue() + "\" : \"" + CLIENT_SECRET + "\"\n" + " }\n" + "}"; return new ByteArrayInputStream(oidcConfig.getBytes(StandardCharsets.UTF_8)); @@ -775,16 +793,15 @@ private InputStream getOidcConfigurationInputStreamWithRequestParameter(String r private InputStream getOidcConfigurationInputStreamWithoutEncValue(String requestParameter, String encryptionAlgorithm){ String oidcConfig = "{\n" + - " \"client-id\" : \"" + CLIENT_ID + "\",\n" + - " \"provider-url\" : \"" + KEYCLOAK_CONTAINER.getAuthServerUrl() + "/realms/" + TEST_REALM_WITH_SCOPES + "/" + "\",\n" + - " \"public-client\" : \"false\",\n" + - " \"ssl-required\" : \"EXTERNAL\",\n" + - " \"ssl-required\" : \"EXTERNAL\",\n" + - " \"authentication-request-format\" : \"" + requestParameter + "\",\n" + - " \"request-object-encryption-alg-value\" : \"" + encryptionAlgorithm + "\",\n" + - " \"scope\" : \"profile email phone\",\n" + - " \"credentials\" : {\n" + - " \"secret\" : \"" + CLIENT_SECRET + "\"\n" + + " \"" + Oidc.CLIENT_ID_JSON_VALUE + "\" : \"" + CLIENT_ID + "\",\n" + + " \"" + PROVIDER_URL + "\" : \"" + KEYCLOAK_CONTAINER.getAuthServerUrl() + "/realms/" + TEST_REALM_WITH_SCOPES + "/" + "\",\n" + + " \"" + PUBLIC_CLIENT + "\" : \"false\",\n" + + " \"" + SSL_REQUIRED + "\" : \"EXTERNAL\",\n" + + " \"" + AUTHENTICATION_REQUEST_FORMAT + "\" : \"" + requestParameter + "\",\n" + + " \"" + REQUEST_OBJECT_ENCRYPTION_ALG_VALUE + "\" : \"" + encryptionAlgorithm + "\",\n" + + " \"" + SCOPE + "\" : \"profile email phone\",\n" + + " \"" + CREDENTIALS + "\" : {\n" + + " \"" + ClientCredentialsProviderType.SECRET.getValue() + "\" : \"" + CLIENT_SECRET + "\"\n" + " }\n" + "}"; return new ByteArrayInputStream(oidcConfig.getBytes(StandardCharsets.UTF_8)); @@ -792,22 +809,22 @@ private InputStream getOidcConfigurationInputStreamWithoutEncValue(String reques private InputStream getOidcConfigurationInputStreamWithRequestParameter(String requestParameter, String signingAlgorithm, String encryptionAlgorithm, String encMethod, String keyStorePath, String alias, String keyStoreType){ String oidcConfig = "{\n" + - " \"client-id\" : \"" + CLIENT_ID + "\",\n" + - " \"provider-url\" : \"" + KEYCLOAK_CONTAINER.getAuthServerUrl() + "/realms/" + TEST_REALM_WITH_SCOPES + "/" + "\",\n" + - " \"public-client\" : \"false\",\n" + - " \"ssl-required\" : \"EXTERNAL\",\n" + - " \"authentication-request-format\" : \"" + requestParameter + "\",\n" + - " \"request-object-signing-algorithm\" : \"" + signingAlgorithm + "\",\n" + - " \"request-object-encryption-alg-value\" : \"" + encryptionAlgorithm + "\",\n" + - " \"request-object-encryption-enc-value\" : \"" + encMethod + "\",\n" + - " \"request-object-signing-keystore-file\" : \"" + keyStorePath + "\",\n" + - " \"request-object-signing-keystore-type\" : \"" + keyStoreType + "\",\n" + - " \"request-object-signing-keystore-password\" : \"" + KEYSTORE_PASS + "\",\n" + - " \"request-object-signing-key-password\" : \"" + KEYSTORE_PASS + "\",\n" + - " \"request-object-signing-key-alias\" : \"" + alias + "\",\n" + - " \"scope\" : \"email phone profile\",\n" + - " \"credentials\" : {\n" + - " \"secret\" : \"" + CLIENT_SECRET + "\"\n" + + " \"" + Oidc.CLIENT_ID_JSON_VALUE + "\" : \"" + CLIENT_ID + "\",\n" + + " \"" + PROVIDER_URL + "\" : \"" + KEYCLOAK_CONTAINER.getAuthServerUrl() + "/realms/" + TEST_REALM_WITH_SCOPES + "/" + "\",\n" + + " \"" + PUBLIC_CLIENT + "\" : \"false\",\n" + + " \"" + SSL_REQUIRED + "\" : \"EXTERNAL\",\n" + + " \"" + AUTHENTICATION_REQUEST_FORMAT + "\" : \"" + requestParameter + "\",\n" + + " \"" + REQUEST_OBJECT_SIGNING_ALGORITHM + "\" : \"" + signingAlgorithm + "\",\n" + + " \"" + REQUEST_OBJECT_ENCRYPTION_ALG_VALUE + "\" : \"" + encryptionAlgorithm + "\",\n" + + " \"" + REQUEST_OBJECT_ENCRYPTION_ENC_VALUE + "\" : \"" + encMethod + "\",\n" + + " \"" + REQUEST_OBJECT_SIGNING_KEYSTORE_FILE + "\" : \"" + keyStorePath + "\",\n" + + " \"" + REQUEST_OBJECT_SIGNING_KEYSTORE_TYPE + "\" : \"" + keyStoreType + "\",\n" + + " \"" + REQUEST_OBJECT_SIGNING_KEYSTORE_PASSWORD + "\" : \"" + KEYSTORE_PASS + "\",\n" + + " \"" + REQUEST_OBJECT_SIGNING_KEY_PASSWORD + "\" : \"" + KEYSTORE_PASS + "\",\n" + + " \"" + REQUEST_OBJECT_SIGNING_KEY_ALIAS + "\" : \"" + alias + "\",\n" + + " \"" + SCOPE + "\" : \"email phone profile\",\n" + + " \"" + CREDENTIALS + "\" : {\n" + + " \"" + ClientCredentialsProviderType.SECRET.getValue() + "\" : \"" + CLIENT_SECRET + "\"\n" + " }\n" + "}"; return new ByteArrayInputStream(oidcConfig.getBytes(StandardCharsets.UTF_8)); @@ -815,26 +832,26 @@ private InputStream getOidcConfigurationInputStreamWithRequestParameter(String r private InputStream getOidcConfigurationInputStreamWithRequestObjectPublicClient(String requestParameter, String signingAlgorithm){ String oidcConfig = "{\n" + - " \"client-id\" : \"" + CLIENT_ID + "\",\n" + - " \"provider-url\" : \"" + KEYCLOAK_CONTAINER.getAuthServerUrl() + "/realms/" + TEST_REALM_WITH_SCOPES + "/" + "\",\n" + - " \"public-client\" : \"true\",\n" + - " \"ssl-required\" : \"EXTERNAL\",\n" + - " \"authentication-request-format\" : \"" + requestParameter + "\",\n" + - " \"request-object-signing-algorithm\" : \"" + signingAlgorithm + "\",\n" + - " \"scope\" : \"email phone profile\"\n" + + " \"" + Oidc.CLIENT_ID_JSON_VALUE + "\" : \"" + CLIENT_ID + "\",\n" + + " \"" + PROVIDER_URL + "\" : \"" + KEYCLOAK_CONTAINER.getAuthServerUrl() + "/realms/" + TEST_REALM_WITH_SCOPES + "/" + "\",\n" + + " \"" + PUBLIC_CLIENT + "\" : \"true\",\n" + + " \"" + SSL_REQUIRED + "\" : \"EXTERNAL\",\n" + + " \"" + AUTHENTICATION_REQUEST_FORMAT + "\" : \"" + requestParameter + "\",\n" + + " \"" + REQUEST_OBJECT_SIGNING_ALGORITHM + "\" : \"" + signingAlgorithm + "\",\n" + + " \"" + SCOPE + "\" : \"email phone profile\"\n" + "}"; return new ByteArrayInputStream(oidcConfig.getBytes(StandardCharsets.UTF_8)); } private InputStream getOidcConfigurationInputStreamWithPrincipalAttribute(String principalAttributeValue) { String oidcConfig = "{\n" + - " \"principal-attribute\" : \"" + principalAttributeValue + "\",\n" + - " \"resource\" : \"" + CLIENT_ID + "\",\n" + - " \"public-client\" : \"false\",\n" + - " \"provider-url\" : \"" + KEYCLOAK_CONTAINER.getAuthServerUrl() + "/realms/" + TEST_REALM + "\",\n" + - " \"ssl-required\" : \"EXTERNAL\",\n" + - " \"credentials\" : {\n" + - " \"secret\" : \"" + CLIENT_SECRET + "\"\n" + + " \"" + PRINCIPAL_ATTRIBUTE + "\" : \"" + principalAttributeValue + "\",\n" + + " \"" + RESOURCE + "\" : \"" + CLIENT_ID + "\",\n" + + " \"" + PUBLIC_CLIENT + "\" : \"false\",\n" + + " \"" + PROVIDER_URL + "\" : \"" + KEYCLOAK_CONTAINER.getAuthServerUrl() + "/realms/" + TEST_REALM + "\",\n" + + " \"" + SSL_REQUIRED + "\" : \"EXTERNAL\",\n" + + " \"" + CREDENTIALS + "\" : {\n" + + " \"" + ClientCredentialsProviderType.SECRET.getValue() + "\" : \"" + CLIENT_SECRET + "\"\n" + " }\n" + "}"; return new ByteArrayInputStream(oidcConfig.getBytes(StandardCharsets.UTF_8)); @@ -842,13 +859,13 @@ private InputStream getOidcConfigurationInputStreamWithPrincipalAttribute(String static InputStream getTenantConfigWithAuthServerUrl(String tenant) { String oidcConfig = "{\n" + - " \"realm\" : \"" + tenant + "\",\n" + - " \"resource\" : \"" + CLIENT_ID + "\",\n" + - " \"public-client\" : \"false\",\n" + - " \"auth-server-url\" : \"" + KEYCLOAK_CONTAINER.getAuthServerUrl() + "\",\n" + - " \"ssl-required\" : \"EXTERNAL\",\n" + - " \"credentials\" : {\n" + - " \"secret\" : \"" + CLIENT_SECRET + "\"\n" + + " \"" + REALM + "\" : \"" + tenant + "\",\n" + + " \""+ RESOURCE +"\" : \"" + CLIENT_ID + "\",\n" + + " \"" + PUBLIC_CLIENT +"\" : \"false\",\n" + + " \"" + AUTH_SERVER_URL + "\" : \"" + KEYCLOAK_CONTAINER.getAuthServerUrl() + "\",\n" + + " \"" + SSL_REQUIRED + "\" : \"EXTERNAL\",\n" + + " \"" + CREDENTIALS + "\" : {\n" + + " \"" + ClientCredentialsProviderType.SECRET.getValue() + "\" : \"" + CLIENT_SECRET + "\"\n" + " }\n" + "}"; return new ByteArrayInputStream(oidcConfig.getBytes(StandardCharsets.UTF_8)); @@ -856,12 +873,12 @@ static InputStream getTenantConfigWithAuthServerUrl(String tenant) { static InputStream getTenantConfigWithProviderUrl(String tenant) { String oidcConfig = "{\n" + - " \"provider-url\" : \"" + KEYCLOAK_CONTAINER.getAuthServerUrl() + "/realms/" + tenant + "\",\n" + - " \"client-id\" : \"" + CLIENT_ID + "\",\n" + - " \"public-client\" : \"false\",\n" + - " \"ssl-required\" : \"EXTERNAL\",\n" + - " \"credentials\" : {\n" + - " \"secret\" : \"" + CLIENT_SECRET + "\"\n" + + " \"" + PROVIDER_URL + "\" : \"" + KEYCLOAK_CONTAINER.getAuthServerUrl() + "/realms/" + tenant + "\",\n" + + " \"" + Oidc.CLIENT_ID_JSON_VALUE + "\" : \"" + CLIENT_ID + "\",\n" + + " \"" + PUBLIC_CLIENT + "\" : \"false\",\n" + + " \"" + SSL_REQUIRED + "\" : \"EXTERNAL\",\n" + + " \"" + CREDENTIALS + "\" : {\n" + + " \"" + ClientCredentialsProviderType.SECRET.getValue() + "\" : \"" + CLIENT_SECRET + "\"\n" + " }\n" + "}"; return new ByteArrayInputStream(oidcConfig.getBytes(StandardCharsets.UTF_8)); diff --git a/http/spnego/pom.xml b/http/spnego/pom.xml index e8e9ae7dfaa..f44833a344d 100644 --- a/http/spnego/pom.xml +++ b/http/spnego/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../pom.xml diff --git a/http/sso/pom.xml b/http/sso/pom.xml index 56c9713ff77..3db2fc06dc4 100644 --- a/http/sso/pom.xml +++ b/http/sso/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../pom.xml diff --git a/http/sso/src/main/java/org/wildfly/security/http/util/sso/SingleSignOnServerMechanismFactory.java b/http/sso/src/main/java/org/wildfly/security/http/util/sso/SingleSignOnServerMechanismFactory.java index 867560e90eb..17dc3309357 100644 --- a/http/sso/src/main/java/org/wildfly/security/http/util/sso/SingleSignOnServerMechanismFactory.java +++ b/http/sso/src/main/java/org/wildfly/security/http/util/sso/SingleSignOnServerMechanismFactory.java @@ -46,6 +46,7 @@ *

The single sign-one capabilities provided by this factory is based on a HTTP Cookie to track SSO sessions and also an {@link IdentityCache} providing * a storage (eg.: using a shared or distributable cache/map) for these sessions and related data. * + * @deprecated Only inner class SingleSignOnConfiguration is deprecated. * @author Pedro Igor * @author Paul Ferraro */ diff --git a/http/stateful-basic/pom.xml b/http/stateful-basic/pom.xml index 7844474a2cf..ff8fd8a810b 100644 --- a/http/stateful-basic/pom.xml +++ b/http/stateful-basic/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../pom.xml diff --git a/http/util/pom.xml b/http/util/pom.xml index 92c37b726d3..3643831549e 100644 --- a/http/util/pom.xml +++ b/http/util/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../pom.xml diff --git a/http/util/src/main/java/org/wildfly/security/http/util/SetRequestInformationCallbackMechanismFactory.java b/http/util/src/main/java/org/wildfly/security/http/util/SetRequestInformationCallbackMechanismFactory.java index 8252c361280..571442b4abd 100644 --- a/http/util/src/main/java/org/wildfly/security/http/util/SetRequestInformationCallbackMechanismFactory.java +++ b/http/util/src/main/java/org/wildfly/security/http/util/SetRequestInformationCallbackMechanismFactory.java @@ -17,11 +17,7 @@ */ package org.wildfly.security.http.util; -import org.wildfly.security.auth.callback.RequestInformationCallback; -import org.wildfly.security.http.HttpAuthenticationException; -import org.wildfly.security.http.HttpServerAuthenticationMechanism; -import org.wildfly.security.http.HttpServerAuthenticationMechanismFactory; -import org.wildfly.security.http.HttpServerRequest; +import static org.wildfly.common.Assert.checkNotNullParam; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; @@ -31,7 +27,11 @@ import java.util.Map; import java.util.function.Function; -import static org.wildfly.common.Assert.checkNotNullParam; +import org.wildfly.security.auth.callback.RequestInformationCallback; +import org.wildfly.security.http.HttpAuthenticationException; +import org.wildfly.security.http.HttpServerAuthenticationMechanism; +import org.wildfly.security.http.HttpServerAuthenticationMechanismFactory; +import org.wildfly.security.http.HttpServerRequest; /** * A wrapper {@link HttpServerAuthenticationMechanismFactory} that sets the request information using the current authentication request. diff --git a/jose/jwk/pom.xml b/jose/jwk/pom.xml index b85827d9283..4a82a6a3894 100644 --- a/jose/jwk/pom.xml +++ b/jose/jwk/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../pom.xml diff --git a/jose/util/pom.xml b/jose/util/pom.xml index e5321b18071..ce6101c1ffb 100644 --- a/jose/util/pom.xml +++ b/jose/util/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../pom.xml diff --git a/json-util/pom.xml b/json-util/pom.xml index 8ad8fe59a16..6ecab3a776c 100644 --- a/json-util/pom.xml +++ b/json-util/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT 4.0.0 diff --git a/keystore/pom.xml b/keystore/pom.xml index 6729d438516..4ab364a873b 100644 --- a/keystore/pom.xml +++ b/keystore/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT 4.0.0 diff --git a/manager/action/pom.xml b/manager/action/pom.xml index f6d2e42def8..b0b5cc6e8bd 100644 --- a/manager/action/pom.xml +++ b/manager/action/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../pom.xml diff --git a/manager/base/pom.xml b/manager/base/pom.xml index 915c5814f25..c43c374f491 100644 --- a/manager/base/pom.xml +++ b/manager/base/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../pom.xml diff --git a/mechanism/base/pom.xml b/mechanism/base/pom.xml index 8603e2d2e7d..e8b21d9cb63 100644 --- a/mechanism/base/pom.xml +++ b/mechanism/base/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../pom.xml diff --git a/mechanism/base/src/main/java/org/wildfly/security/mechanism/MechanismUtil.java b/mechanism/base/src/main/java/org/wildfly/security/mechanism/MechanismUtil.java index c845093aeef..28243d661b5 100644 --- a/mechanism/base/src/main/java/org/wildfly/security/mechanism/MechanismUtil.java +++ b/mechanism/base/src/main/java/org/wildfly/security/mechanism/MechanismUtil.java @@ -37,7 +37,7 @@ * * @author David M. Lloyd * - * @deprecated Should not be part of public API. Moved into internal {@link org.wildfly.security.mechanism._private.MechanismUtil}. + * @deprecated Should not be part of public API. Moved into internal {@link org.wildfly.security.mechanism._private.MechanismUtil org.wildfly.security.mechanism._private.MechanismUtil}. */ @Deprecated public final class MechanismUtil { diff --git a/mechanism/digest/pom.xml b/mechanism/digest/pom.xml index d8a70b5a869..c9989e73abb 100644 --- a/mechanism/digest/pom.xml +++ b/mechanism/digest/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../pom.xml diff --git a/mechanism/gssapi/pom.xml b/mechanism/gssapi/pom.xml index 3d34c66ede4..adccd6cda1e 100644 --- a/mechanism/gssapi/pom.xml +++ b/mechanism/gssapi/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../pom.xml diff --git a/mechanism/http/pom.xml b/mechanism/http/pom.xml index 64a8c725123..394a1de641d 100644 --- a/mechanism/http/pom.xml +++ b/mechanism/http/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../pom.xml diff --git a/mechanism/oauth2/pom.xml b/mechanism/oauth2/pom.xml index 10ae56f74c3..e57683a7787 100644 --- a/mechanism/oauth2/pom.xml +++ b/mechanism/oauth2/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../pom.xml diff --git a/mechanism/oauth2/src/main/java/org/wildfly/security/mechanism/oauth2/OAuth2Client.java b/mechanism/oauth2/src/main/java/org/wildfly/security/mechanism/oauth2/OAuth2Client.java index ec78a73eeaa..4e687cda648 100644 --- a/mechanism/oauth2/src/main/java/org/wildfly/security/mechanism/oauth2/OAuth2Client.java +++ b/mechanism/oauth2/src/main/java/org/wildfly/security/mechanism/oauth2/OAuth2Client.java @@ -18,6 +18,11 @@ package org.wildfly.security.mechanism.oauth2; +import static org.wildfly.common.Assert.assertTrue; + +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.UnsupportedCallbackException; + import org.wildfly.common.bytes.ByteStringBuilder; import org.wildfly.common.iteration.ByteIterator; import org.wildfly.security.auth.callback.CredentialCallback; @@ -27,11 +32,6 @@ import org.wildfly.security.mechanism.AuthenticationMechanismException; import org.wildfly.security.sasl.util.StringPrep; -import javax.security.auth.callback.CallbackHandler; -import javax.security.auth.callback.UnsupportedCallbackException; - -import static org.wildfly.common.Assert.assertTrue; - /** * Implementation of the client side of the OAuth2 SASL mechanism. * diff --git a/mechanism/scram/pom.xml b/mechanism/scram/pom.xml index e0cd26073b1..bee2afec31a 100644 --- a/mechanism/scram/pom.xml +++ b/mechanism/scram/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../pom.xml diff --git a/password/impl/pom.xml b/password/impl/pom.xml index 53bc46cdd76..2e71afafcf7 100644 --- a/password/impl/pom.xml +++ b/password/impl/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../pom.xml diff --git a/password/impl/src/main/java/org/wildfly/security/password/impl/BSDUnixDESCryptPasswordImpl.java b/password/impl/src/main/java/org/wildfly/security/password/impl/BSDUnixDESCryptPasswordImpl.java index cb918d2ebe6..c7fb6a44b5b 100644 --- a/password/impl/src/main/java/org/wildfly/security/password/impl/BSDUnixDESCryptPasswordImpl.java +++ b/password/impl/src/main/java/org/wildfly/security/password/impl/BSDUnixDESCryptPasswordImpl.java @@ -30,7 +30,6 @@ import java.security.spec.InvalidParameterSpecException; import java.security.spec.KeySpec; import java.util.Arrays; -import java.util.concurrent.ThreadLocalRandom; import org.wildfly.security.password.interfaces.BSDUnixDESCryptPassword; import org.wildfly.security.password.spec.ClearPasswordSpec; @@ -72,11 +71,11 @@ class BSDUnixDESCryptPasswordImpl extends AbstractPasswordImpl implements BSDUni } BSDUnixDESCryptPasswordImpl(final ClearPasswordSpec passwordSpec) throws InvalidKeySpecException { - this(passwordSpec.getEncodedPassword(), ThreadLocalRandom.current().nextInt() & 0xffffff, DEFAULT_ITERATION_COUNT); + this(passwordSpec.getEncodedPassword(), PasswordUtil.generateRandomSaltInt() & 0xffffff, DEFAULT_ITERATION_COUNT); } BSDUnixDESCryptPasswordImpl(final char[] password, final Charset hashCharset) throws InvalidKeySpecException, InvalidParameterSpecException { - this(password, ThreadLocalRandom.current().nextInt() & 0xffffff, DEFAULT_ITERATION_COUNT, hashCharset); + this(password, PasswordUtil.generateRandomSaltInt() & 0xffffff, DEFAULT_ITERATION_COUNT, hashCharset); } BSDUnixDESCryptPasswordImpl(final char[] password, final IteratedSaltedPasswordAlgorithmSpec spec, final Charset hashCharset) throws InvalidKeySpecException, InvalidParameterSpecException { @@ -84,7 +83,7 @@ class BSDUnixDESCryptPasswordImpl extends AbstractPasswordImpl implements BSDUni } BSDUnixDESCryptPasswordImpl(final char[] password, final IteratedPasswordAlgorithmSpec spec, final Charset hashCharset) throws InvalidKeySpecException, InvalidParameterSpecException { - this(password, ThreadLocalRandom.current().nextInt() & 0xffffff, spec.getIterationCount(), hashCharset); + this(password, PasswordUtil.generateRandomSaltInt() & 0xffffff, spec.getIterationCount(), hashCharset); } BSDUnixDESCryptPasswordImpl(final char[] password, final SaltedPasswordAlgorithmSpec spec, final Charset hashCharset) throws InvalidKeySpecException, InvalidParameterSpecException { diff --git a/password/impl/src/main/java/org/wildfly/security/password/impl/PasswordUtil.java b/password/impl/src/main/java/org/wildfly/security/password/impl/PasswordUtil.java index 21e1f8a58f1..9327f4b5ac0 100644 --- a/password/impl/src/main/java/org/wildfly/security/password/impl/PasswordUtil.java +++ b/password/impl/src/main/java/org/wildfly/security/password/impl/PasswordUtil.java @@ -17,7 +17,7 @@ */ package org.wildfly.security.password.impl; -import java.util.concurrent.ThreadLocalRandom; +import org.wildfly.common.Assert; /** * Helper utility methods for operations on passwords. @@ -27,6 +27,8 @@ */ final class PasswordUtil { + private static final ThreadLocalSecureRandom THREAD_LOCAL_SECURE_RANDOM = new ThreadLocalSecureRandom(); + /** * Generate a random salt as byte array. * @@ -35,7 +37,22 @@ final class PasswordUtil { */ public static byte[] generateRandomSalt(int saltSize) { byte[] randomSalt = new byte[saltSize]; - ThreadLocalRandom.current().nextBytes(randomSalt); + THREAD_LOCAL_SECURE_RANDOM.get().nextBytes(randomSalt); return randomSalt; } + + /** + * Generate a random salt as int. + * + * @return a byte array representing the random salt + */ + static int generateRandomSaltInt() { + byte[] saltBytes = generateRandomSalt(4); + return convertBytesToInt(saltBytes); + } + + static int convertBytesToInt(byte[] saltBytes) { + Assert.assertTrue(saltBytes.length == 4); + return (saltBytes[0] & 0xff) << 24 | (saltBytes[1] & 0xff) << 16 | (saltBytes[2] & 0xff) << 8 | saltBytes[3] & 0xff; + } } diff --git a/password/impl/src/main/java/org/wildfly/security/password/impl/ThreadLocalSecureRandom.java b/password/impl/src/main/java/org/wildfly/security/password/impl/ThreadLocalSecureRandom.java new file mode 100644 index 00000000000..5a99da754e8 --- /dev/null +++ b/password/impl/src/main/java/org/wildfly/security/password/impl/ThreadLocalSecureRandom.java @@ -0,0 +1,32 @@ +/* + * JBoss, Home of Professional Open Source + * + * Copyright 2024 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.security.password.impl; + +import java.security.SecureRandom; +import java.util.function.Supplier; + +class ThreadLocalSecureRandom implements Supplier { + final ThreadLocal localInstance = new ThreadLocal<>(); + + public SecureRandom get() { + if (localInstance.get() == null) { + localInstance.set(new SecureRandom()); + } + return localInstance.get(); + } +} diff --git a/password/impl/src/main/java/org/wildfly/security/password/impl/UnixDESCryptPasswordImpl.java b/password/impl/src/main/java/org/wildfly/security/password/impl/UnixDESCryptPasswordImpl.java index 00ad94110da..267dfd70200 100644 --- a/password/impl/src/main/java/org/wildfly/security/password/impl/UnixDESCryptPasswordImpl.java +++ b/password/impl/src/main/java/org/wildfly/security/password/impl/UnixDESCryptPasswordImpl.java @@ -31,7 +31,6 @@ import java.security.spec.InvalidParameterSpecException; import java.security.spec.KeySpec; import java.util.Arrays; -import java.util.concurrent.ThreadLocalRandom; import org.wildfly.security.password.interfaces.UnixDESCryptPassword; import org.wildfly.security.password.spec.ClearPasswordSpec; @@ -68,11 +67,11 @@ class UnixDESCryptPasswordImpl extends AbstractPasswordImpl implements UnixDESCr } UnixDESCryptPasswordImpl(final ClearPasswordSpec spec) throws InvalidKeySpecException, InvalidKeyException { - this((short) (ThreadLocalRandom.current().nextInt() & 0xfff), spec.getEncodedPassword()); + this((short) (PasswordUtil.generateRandomSaltInt() & 0xfff), spec.getEncodedPassword()); } UnixDESCryptPasswordImpl(final char[] passwordChars, final Charset hashCharset) throws InvalidKeyException { - this((short) (ThreadLocalRandom.current().nextInt() & 0xfff), passwordChars, hashCharset); + this((short) (PasswordUtil.generateRandomSaltInt() & 0xfff), passwordChars, hashCharset); } UnixDESCryptPasswordImpl(final char[] passwordChars, SaltedPasswordAlgorithmSpec algorithmSpec, final Charset hashCharset) throws InvalidParameterSpecException, InvalidKeyException { diff --git a/password/impl/src/main/java/org/wildfly/security/password/impl/UnixSHACryptPasswordImpl.java b/password/impl/src/main/java/org/wildfly/security/password/impl/UnixSHACryptPasswordImpl.java index 71e51451b04..06c7341363f 100644 --- a/password/impl/src/main/java/org/wildfly/security/password/impl/UnixSHACryptPasswordImpl.java +++ b/password/impl/src/main/java/org/wildfly/security/password/impl/UnixSHACryptPasswordImpl.java @@ -435,7 +435,7 @@ public boolean equals(final Object obj) { return false; } UnixSHACryptPasswordImpl other = (UnixSHACryptPasswordImpl) obj; - return iterationCount == other.iterationCount && algorithm.equals(other.algorithm) && Arrays.equals(hash, other.hash) && Arrays.equals(salt, other.salt); + return iterationCount == other.iterationCount && algorithm.equals(other.algorithm) && MessageDigest.isEqual(hash, other.hash) && MessageDigest.isEqual(salt, other.salt); } private void readObject(ObjectInputStream ignored) throws NotSerializableException { diff --git a/password/impl/src/test/java/org/wildfly/security/password/impl/PasswordUtilTest.java b/password/impl/src/test/java/org/wildfly/security/password/impl/PasswordUtilTest.java new file mode 100644 index 00000000000..ace17e04677 --- /dev/null +++ b/password/impl/src/test/java/org/wildfly/security/password/impl/PasswordUtilTest.java @@ -0,0 +1,32 @@ +/* + * JBoss, Home of Professional Open Source + * + * Copyright 2024 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.security.password.impl; + +import org.junit.Assert; +import org.junit.Test; + +public class PasswordUtilTest { + + @Test + public void testConvertBytesToInt() { + Assert.assertEquals(0, PasswordUtil.convertBytesToInt(new byte[] {(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00})); + Assert.assertEquals(Integer.MAX_VALUE, PasswordUtil.convertBytesToInt(new byte[] {(byte) 0x7f, (byte) 0xff, (byte) 0xff, (byte) 0xff})); + Assert.assertEquals(Integer.MIN_VALUE, PasswordUtil.convertBytesToInt(new byte[] {(byte) 0x80, (byte) 0x00, (byte) 0x00, (byte) 0x00})); + Assert.assertEquals(-1, PasswordUtil.convertBytesToInt(new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff})); + } +} diff --git a/permission/pom.xml b/permission/pom.xml index 24e307ac07c..de8707d9c43 100644 --- a/permission/pom.xml +++ b/permission/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT 4.0.0 diff --git a/permission/src/main/java/org/wildfly/security/permission/PermissionActions.java b/permission/src/main/java/org/wildfly/security/permission/PermissionActions.java index a45c5fdad88..f4aa390da7c 100644 --- a/permission/src/main/java/org/wildfly/security/permission/PermissionActions.java +++ b/permission/src/main/java/org/wildfly/security/permission/PermissionActions.java @@ -38,7 +38,7 @@ * * @author David M. Lloyd * - * @deprecated Use one of the abstract permission classes like {@link AbstractActionSetPermission} instead. + * @deprecated Use one of the abstract permission classes like {@link org.wildfly.security.permission.AbstractActionSetPermission org.wildfly.security.permission.AbstractActionSetPermission} instead. */ @Deprecated public final class PermissionActions { diff --git a/pom.xml b/pom.xml index 3b68061c28c..7bcd648dc29 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT pom WildFly Elytron Parent @@ -56,11 +56,12 @@ 11 + 3.7.0 2.17.0 ${version.com.fasterxml.jackson} 1.6.0 4.0.1 - 3.14.0 + 3.15.0 2.0.0.AM27 2.1.6 2.0.3 @@ -70,36 +71,38 @@ 2.12.0 4.5.14 4.4.16 + 1.1.5 3.5.3.Final 2.1.19.Final 1.1.6.Final 2.2.1.Final 1.12.2.Final 1.2.0.Final - 2.0.0 + 2.1.2 5.0.0 3.5.1.Final 1.11 4.13.1 1.34 2.7.1 - 2.0.0 2.4.9 - 9.31 + 9.37.3 3.8.1 1.0.8.Final 1.0.1.Final 1.6.0.Final - 2.7 + 2.16.1 5.4.1 3.0.0 0.9.6 1.15.3 - 18.0.2 - 4.3.3 + 25.0.2 + 5.5.0 2.40.0 2.3.0 - 3.1.0.Final + 23.0.7 + 2.7 + 3.8.16.Final INFO @@ -255,11 +258,119 @@ maven-javadoc-plugin + ${version-javadoc-plugin} + + + org.wildfly.common + wildfly-common + ${version.org.wildfly.common} + + + org.jboss.logging + jboss-logging + ${version.org.jboss.logging} + + + org.jboss.logging + jboss-logging-annotations + ${version.org.jboss.logging.tools} + + + org.jboss.logmanager + jboss-logmanager + ${version.org.jboss.logmanager} + + + org.wildfly.security + wildfly-elytron-credential-source-impl + ${project.version} + + + org.wildfly.security + wildfly-elytron-ssh-util + ${project.version} + + + org.wildfly.client + wildfly-client-config + ${version.org.wildfly.client.config} + + + org.wildfly.security + wildfly-elytron-provider-util + ${project.version} + + + org.kohsuke.metainf-services + metainf-services + ${version.org.kohsuke.metainf-services.metainf-services} + + + org.apache.httpcomponents + httpcore + ${version.org.apache.httpcomponents.httpcore} + + + org.apache.httpcomponents + httpclient + ${version.org.apache.httpcomponents.httpclient} + + + org.bitbucket.b_c + jose4j + ${version.org.bitbucket.b_c.jose4j} + + + com.fasterxml.jackson.core + jackson-databind + ${version.com.fasterxml.jackson.databind} + + + com.fasterxml.jackson.core + jackson-annotations + ${version.com.fasterxml.jackson} + + + com.fasterxml.jackson.core + jackson-core + ${version.com.fasterxml.jackson} + + + jakarta.servlet + jakarta.servlet-api + ${version.jakarta.servlet.jakarta-servlet-api} + + + jakarta.json + jakarta.json-api + ${version.jakarta.json.jakarta-json-api} + + + commons-cli + commons-cli + ${version.commons-cli} + + + org.apache.commons + commons-lang3 + ${version.org.apache.commons} + + + org.apache.sshd + sshd-common + ${version.org.apache.sshd.common} + + + org.jboss.modules + jboss-modules + ${version.org.jboss.modules} + + true none protected - 8 + 11 ${project.basedir}/asn1/src/main/java/; ${project.basedir}/audit/src/main/java/; @@ -1001,6 +1112,11 @@ jose4j ${version.org.bitbucket.b_c.jose4j} + + org.aesh + aesh + ${version.org.aesh} + diff --git a/tool/src/main/java/org/wildfly/security/tool/CredentialStoreCommand.java b/tool/src/main/java/org/wildfly/security/tool/CredentialStoreCommand.java index 493d5df134c..3f6d765d73a 100644 --- a/tool/src/main/java/org/wildfly/security/tool/CredentialStoreCommand.java +++ b/tool/src/main/java/org/wildfly/security/tool/CredentialStoreCommand.java @@ -46,7 +46,6 @@ import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.DefaultParser; -import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Option; import org.apache.commons.cli.OptionGroup; import org.apache.commons.cli.Options; @@ -69,6 +68,10 @@ import org.wildfly.security.password.interfaces.ClearPassword; import org.wildfly.security.pem.Pem; import org.wildfly.security.ssh.util.SshUtil; +import org.wildfly.security.tool.help.DescriptionSection; +import org.wildfly.security.tool.help.HelpCommand; +import org.wildfly.security.tool.help.OptionsSection; +import org.wildfly.security.tool.help.UsageSection; import static org.wildfly.security.tool.Params.ALIAS_PARAM; import static org.wildfly.security.tool.Params.CREATE_CREDENTIAL_STORE_PARAM; @@ -959,13 +962,15 @@ protected Set aliases() { */ @Override public void help() { - HelpFormatter help = new HelpFormatter(); - help.setWidth(WIDTH); - help.printHelp(ElytronToolMessages.msg.cmdHelp(getToolCommand(), CREDENTIAL_STORE_COMMAND), - ElytronToolMessages.msg.cmdLineCredentialStoreHelpHeader().concat(ElytronToolMessages.msg.cmdLineActionsHelpHeader()), - options, - "", - true); + OptionsSection optionsSection = new OptionsSection(ElytronToolMessages.msg.cmdLineActionsHelpHeader(), options); + UsageSection usageSection = new UsageSection(CREDENTIAL_STORE_COMMAND, null); + DescriptionSection descriptionSection = new DescriptionSection(ElytronToolMessages.msg.cmdLineCredentialStoreHelpHeader()); + HelpCommand helpCommand = HelpCommand.HelpCommandBuilder.builder() + .description(descriptionSection) + .usage(usageSection) + .options(optionsSection) + .build(); + helpCommand.printHelp(); } static Map parseCredentialStoreProperties(final String attributeString) { diff --git a/tool/src/main/java/org/wildfly/security/tool/ElytronTool.java b/tool/src/main/java/org/wildfly/security/tool/ElytronTool.java index 2cae692d978..1111c9ad6af 100644 --- a/tool/src/main/java/org/wildfly/security/tool/ElytronTool.java +++ b/tool/src/main/java/org/wildfly/security/tool/ElytronTool.java @@ -20,10 +20,17 @@ import org.apache.commons.cli.AlreadySelectedException; import org.apache.commons.cli.Option; import org.wildfly.security.WildFlyElytronProvider; +import org.wildfly.security.tool.help.CommandsSection; +import org.wildfly.security.tool.help.DescriptionSection; +import org.wildfly.security.tool.help.HelpCommand; +import org.wildfly.security.tool.help.OptionsSection; +import org.wildfly.security.tool.help.UsageSection; import java.security.Security; import java.util.HashMap; import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; /** * Elytron Tool main class which drives all registered commands. @@ -131,15 +138,27 @@ private static void configureLogManager() { } private void generalHelp() { - System.out.print(ElytronToolMessages.msg.generalHelpTitle()); - System.out.println(); - for (Command c: commandRegistry.values()) { - if (scriptName != null) { - c.setToolCommand(scriptName); - } - c.help(); - System.out.println(); - } + DescriptionSection descriptionSection = new DescriptionSection(ElytronToolMessages.msg.cmdElytronToolDescription()); + UsageSection usageSection = new UsageSection(null, null); + OptionsSection optionsSection = new OptionsSection(ElytronToolMessages.msg.generalHelpOptionsOpening(), null); + + // Using SortedMap so commands are in alphabetical order + SortedMap commandsMap = new TreeMap<>(); + commandsMap.put(CredentialStoreCommand.CREDENTIAL_STORE_COMMAND, ElytronToolMessages.msg.cmdLineCredentialStoreHelpHeader()); + commandsMap.put(VaultCommand.VAULT_COMMAND, ElytronToolMessages.msg.cmdVaultHelpHeader()); + commandsMap.put(FileSystemRealmCommand.FILE_SYSTEM_REALM_COMMAND, ElytronToolMessages.msg.cmdFileSystemRealmHelpHeader()); + commandsMap.put(FileSystemEncryptRealmCommand.FILE_SYSTEM_ENCRYPT_COMMAND, ElytronToolMessages.msg.cmdFileSystemEncryptHelpHeader()); + commandsMap.put(MaskCommand.MASK_COMMAND, ElytronToolMessages.msg.cmdMaskHelpHeader()); + commandsMap.put(FileSystemRealmIntegrityCommand.FILE_SYSTEM_REALM_INTEGRITY_COMMAND, ElytronToolMessages.msg.cmdFileSystemIntegrityHelpHeader()); + CommandsSection commandsSection = new CommandsSection(commandsMap); + + HelpCommand helpCommand = HelpCommand.HelpCommandBuilder.builder() + .description(descriptionSection) + .usage(usageSection) + .options(optionsSection) + .commands(commandsSection) + .build(); + helpCommand.printHelp(); } Command findCommand(String commandName) { diff --git a/tool/src/main/java/org/wildfly/security/tool/ElytronToolMessages.java b/tool/src/main/java/org/wildfly/security/tool/ElytronToolMessages.java index 6a023c4f1d2..4b876d33b25 100644 --- a/tool/src/main/java/org/wildfly/security/tool/ElytronToolMessages.java +++ b/tool/src/main/java/org/wildfly/security/tool/ElytronToolMessages.java @@ -105,25 +105,25 @@ public interface ElytronToolMessages extends BasicLogger { "Provider must be installed through java.security file or through service loader from properly packaged jar file on classpath.") String cmdLineCustomCredentialStoreProviderDesc(); - @Message(id = NONE, value = "Create credential store (Action)") + @Message(id = NONE, value = "* Create credential store") String cmdLineCreateCredentialStoreDesc(); @Message(id = NONE, value = "Credential store type") String cmdLineCredentialStoreTypeDesc(); - @Message(id = NONE, value = "Add new alias to the credential store (Action)") + @Message(id = NONE, value = "* Add new alias to the credential store") String cmdLineAddAliasDesc(); - @Message(id = NONE, value = "Remove alias from the credential store (Action)") + @Message(id = NONE, value = "* Remove alias from the credential store") String cmdLineRemoveAliasDesc(); - @Message(id = NONE, value = "Check if alias exists within the credential store (Action)") + @Message(id = NONE, value = "* Check if alias exists within the credential store") String cmdLineCheckAliasDesc(); - @Message(id = NONE, value = "Display all aliases (Action)") + @Message(id = NONE, value = "* Display all aliases") String cmdLineAliasesDesc(); - @Message(id = NONE, value = "Display all types of stored credentials for given alias (Action)") + @Message(id = NONE, value = "* Display all types of stored credentials for given alias") String cmdLineAliasTypes(); @Message(id = NONE, value = "Generate private and public key pair and store them as a KeyPairCredential") @@ -159,7 +159,7 @@ public interface ElytronToolMessages extends BasicLogger { @Message(id = NONE, value = "Print summary, especially command how to create this credential store") String cmdLinePrintSummary(); - @Message(id = NONE, value = "Get help with usage of this command (Action)") + @Message(id = NONE, value = "* Get help with usage of this command") String cmdLineHelp(); @Message(id = NONE, value = "Alias \"%s\" exists") @@ -281,7 +281,7 @@ public interface ElytronToolMessages extends BasicLogger { @Message(id = NONE, value = "CLI command to add new credential store:%n") String cliCommandToNewCredentialStore(); - @Message(id = NONE, value = "Bulk conversion with options listed in description file. All options have no default value and should be set in the file. (Action)%n" + + @Message(id = NONE, value = "* Bulk conversion with options listed in description file. All options have no default value and should be set in the file.%n" + "All options are required with the exceptions:%n" + " - \"properties\" option%n - \"type\" option (defaults to \"KeyStoreCredentialStore\")%n - \"credential-store-provider\" option%n - \"other-providers\" option%n" + " - \"salt\" and \"iteration\" options can be omitted when plain-text password is used%n" + @@ -406,7 +406,7 @@ public interface ElytronToolMessages extends BasicLogger { String longOptionDescription(String option, String longOption); // filesystem-realm command - @Message(id = NONE, value = "'FileSystemRealm' command is used to convert legacy properties files and scripts to an Elytron FileSystemRealm.") + @Message(id = NONE, value = "\"filesystem-realm\" command is used to convert legacy properties files and scripts to an Elytron FileSystemRealm.") String cmdFileSystemRealmHelpHeader(); @Message(id = NONE, value = "The relative or absolute path to the users file.") @@ -489,7 +489,7 @@ public interface ElytronToolMessages extends BasicLogger { @Message(id = NONE, value = "Name of the security-domain to be configured.") String cmdFileSystemRealmSecurityDomainNameDesc(); - @Message(id = NONE, value = "Bulk conversion with options listed in description file. Optional options have default values, required options do not. (Action) %n" + + @Message(id = NONE, value = "* Bulk conversion with options listed in description file. Optional options have default values, required options do not.%n" + "The options fileSystemRealmName and securityDomainName are optional. %n" + "These optional options have default values of: converted-properties-filesystem-realm and converted-properties-security-domain. %n" + "Values are required for the following options: users-file, roles-file, and output-location. %n" + @@ -498,7 +498,7 @@ public interface ElytronToolMessages extends BasicLogger { "Blocks of options must be separated by a blank line.") String cmdFileSystemRealmBulkConvertDesc(); - @Message(id = NONE, value = "Bulk conversion with options listed in description file. Optional options have default values, required options do not. (Action) %n" + + @Message(id = NONE, value = "* Bulk conversion with options listed in description file. Optional options have default values, required options do not. %n" + "The options realm-name, hash-encoding, levels, secret-key, create, populate, keystore, type, password, password-env, and key-pair are optional. %n" + "Values are required for the following options: input-location, output-location, and credential-store. %n" + "The default values of realm-name, hash-encoding, hash-charset, levels, secret-key, create, and populate are encrypted-filesystem-realm, BASE64, UTF-8, 2, key, true, and true respectively. %n" + @@ -508,7 +508,7 @@ public interface ElytronToolMessages extends BasicLogger { "Blocks of options must be separated by a blank line.") String cmdFileSystemRealmEncryptBulkConvertDesc(); - @Message(id = NONE, value = "Bulk conversion with options listed in description file. (Action)" + + @Message(id = NONE, value = "* Bulk conversion with options listed in description file. " + "Optional options have defaults and can be skipped ([type, default_or_NULL]), required options do not (). %n" + "One of either password or password-env is required. %n" + "Blocks of options must be separated by a blank line; order is not important. Syntax: %n" + @@ -519,7 +519,7 @@ public interface ElytronToolMessages extends BasicLogger { String cmdFileSystemRealmIntegrityBulkConvertDesc(); // filesystem-realm encrypt command - @Message(id = NONE, value = "'FileSystemRealmEncrypt' command is used to convert non-empty, un-encrypted FileSystemSecurityRealm(s) to encrypted FileSystemSecurityRealm(s) with a SecretKey.") + @Message(id = NONE, value = "\"filesystem-realm-encrypt\" command is used to convert non-empty, un-encrypted FileSystemSecurityRealm(s) to encrypted FileSystemSecurityRealm(s) with a SecretKey.") String cmdFileSystemEncryptHelpHeader(); @Message(id = NONE, value = "Secret Key was not found in the Credential Store at %s, and populate option was not set. Skipping descriptor file block number %d.") @@ -669,7 +669,7 @@ public interface ElytronToolMessages extends BasicLogger { @Message(id = NONE, value = "Should file %s be overwritten? (y/n) ") String shouldFileBeOverwritten(String file); - @Message(id = NONE, value = "\nSome of the parameters below are mutually exclusive actions which are marked with (Action) in the description.") + @Message(id = NONE, value = "Some of the parameters below are mutually exclusive actions which are marked with * in the description.") String cmdLineActionsHelpHeader(); @Message(id = NONE, value = "Key size (bits).") @@ -738,8 +738,13 @@ public interface ElytronToolMessages extends BasicLogger { @Message(id = NONE, value = "No Credential Store location or Secret Key Alias specified.") MissingOptionException missingCredentialStoreSecretKey(); + @Message(id = NONE, value = "To get list of options for a specific command, please specify the command by using ./elytron-tool.sh [command] --help") + String generalHelpOptionsOpening(); + + @Message(id = NONE, value = "A tool that assists with Elytron configuration") + String cmdElytronToolDescription(); + // Numeric Errors @Message(id = 35, value = "Only one of '%s' and '%s' can be specified at the same time") IllegalArgumentException mutuallyExclusiveOptions(String first, String second); - } diff --git a/tool/src/main/java/org/wildfly/security/tool/FileSystemEncryptRealmCommand.java b/tool/src/main/java/org/wildfly/security/tool/FileSystemEncryptRealmCommand.java index c5e858827a4..5b2c428c027 100644 --- a/tool/src/main/java/org/wildfly/security/tool/FileSystemEncryptRealmCommand.java +++ b/tool/src/main/java/org/wildfly/security/tool/FileSystemEncryptRealmCommand.java @@ -65,7 +65,6 @@ import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.DefaultParser; -import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Option; import org.apache.commons.cli.OptionGroup; import org.apache.commons.cli.Options; @@ -73,6 +72,10 @@ import org.wildfly.security.auth.realm.FileSystemSecurityRealm; import org.wildfly.security.auth.realm.FileSystemSecurityRealmBuilder; import org.wildfly.security.password.spec.Encoding; +import org.wildfly.security.tool.help.DescriptionSection; +import org.wildfly.security.tool.help.HelpCommand; +import org.wildfly.security.tool.help.OptionsSection; +import org.wildfly.security.tool.help.UsageSection; /** * Elytron-Tool command to convert un-encrypted FileSystemRealms into an encrypted realm with the use of a SecretKey. @@ -80,7 +83,7 @@ * security-domain in WildFly. * * @author Ashpan Raskar - * @author Cameron Rodriguez + * @author Jessica Rodriguez */ class FileSystemEncryptRealmCommand extends Command { @@ -576,13 +579,15 @@ public void execute(String[] args) throws Exception { */ @Override public void help() { - HelpFormatter help = new HelpFormatter(); - help.setWidth(WIDTH); - help.printHelp(ElytronToolMessages.msg.cmdHelp(getToolCommand(), FILE_SYSTEM_ENCRYPT_COMMAND), - ElytronToolMessages.msg.cmdFileSystemEncryptHelpHeader(), - options, - "", - true); + OptionsSection optionsSection = new OptionsSection(ElytronToolMessages.msg.cmdLineActionsHelpHeader(), options); + UsageSection usageSection = new UsageSection(FILE_SYSTEM_ENCRYPT_COMMAND, null); + DescriptionSection descriptionSection = new DescriptionSection(ElytronToolMessages.msg.cmdFileSystemEncryptHelpHeader()); + HelpCommand helpCommand = HelpCommand.HelpCommandBuilder.builder() + .description(descriptionSection) + .usage(usageSection) + .options(optionsSection) + .build(); + helpCommand.printHelp(); } /** diff --git a/tool/src/main/java/org/wildfly/security/tool/FileSystemRealmCommand.java b/tool/src/main/java/org/wildfly/security/tool/FileSystemRealmCommand.java index 2bf21d4e484..aff167ece0b 100644 --- a/tool/src/main/java/org/wildfly/security/tool/FileSystemRealmCommand.java +++ b/tool/src/main/java/org/wildfly/security/tool/FileSystemRealmCommand.java @@ -48,7 +48,6 @@ import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.DefaultParser; -import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Option; import org.apache.commons.cli.Options; import org.apache.commons.lang3.ArrayUtils; @@ -63,6 +62,10 @@ import org.wildfly.security.password.interfaces.DigestPassword; import org.wildfly.security.password.spec.DigestPasswordSpec; import org.wildfly.security.password.spec.PasswordSpec; +import org.wildfly.security.tool.help.DescriptionSection; +import org.wildfly.security.tool.help.HelpCommand; +import org.wildfly.security.tool.help.OptionsSection; +import org.wildfly.security.tool.help.UsageSection; /** * Elytron-Tool command to convert legacy properties file into a FileSystemRealm. @@ -298,13 +301,15 @@ public void execute(String[] args) throws Exception { */ @Override public void help() { - HelpFormatter help = new HelpFormatter(); - help.setWidth(WIDTH); - help.printHelp(ElytronToolMessages.msg.cmdHelp(getToolCommand(), FILE_SYSTEM_REALM_COMMAND), - ElytronToolMessages.msg.cmdFileSystemRealmHelpHeader().concat(ElytronToolMessages.msg.cmdLineActionsHelpHeader()), - options, - "", - true); + OptionsSection optionsSection = new OptionsSection(ElytronToolMessages.msg.cmdLineActionsHelpHeader(), options); + UsageSection usageSection = new UsageSection(FILE_SYSTEM_REALM_COMMAND, null); + DescriptionSection descriptionSection = new DescriptionSection(ElytronToolMessages.msg.cmdFileSystemRealmHelpHeader()); + HelpCommand helpCommand = HelpCommand.HelpCommandBuilder.builder() + .description(descriptionSection) + .usage(usageSection) + .options(optionsSection) + .build(); + helpCommand.printHelp(); } @Override diff --git a/tool/src/main/java/org/wildfly/security/tool/FileSystemRealmIntegrityCommand.java b/tool/src/main/java/org/wildfly/security/tool/FileSystemRealmIntegrityCommand.java index 176b824dfd1..9f1f6db9be8 100644 --- a/tool/src/main/java/org/wildfly/security/tool/FileSystemRealmIntegrityCommand.java +++ b/tool/src/main/java/org/wildfly/security/tool/FileSystemRealmIntegrityCommand.java @@ -72,7 +72,6 @@ import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.DefaultParser; -import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Option; import org.apache.commons.cli.OptionGroup; import org.apache.commons.cli.Options; @@ -80,13 +79,17 @@ import org.wildfly.security.auth.realm.FileSystemSecurityRealm; import org.wildfly.security.auth.realm.FileSystemSecurityRealmBuilder; import org.wildfly.security.password.spec.Encoding; +import org.wildfly.security.tool.help.DescriptionSection; +import org.wildfly.security.tool.help.HelpCommand; +import org.wildfly.security.tool.help.OptionsSection; +import org.wildfly.security.tool.help.UsageSection; /** * Elytron Tool command to enable integrity checking in filesystem realms that previously did not have it enabled. If * any identities use a schema which doesn't support integrity checking ({@code urn:elytron:identity:1.1} or earlier), * they are also updated. * - * @author Cameron Rodriguez + * @author Jessica Rodriguez */ public class FileSystemRealmIntegrityCommand extends Command { static final String FILE_SYSTEM_REALM_INTEGRITY_COMMAND = "filesystem-realm-integrity"; @@ -610,13 +613,15 @@ public void execute(String[] args) throws Exception { /** Displays the help screen for the command */ @Override public void help() { - HelpFormatter help = new HelpFormatter(); - help.setWidth(WIDTH); - help.printHelp(ElytronToolMessages.msg.cmdHelp(getToolCommand(), FILE_SYSTEM_REALM_INTEGRITY_COMMAND), - ElytronToolMessages.msg.cmdFileSystemIntegrityHelpHeader(), - options, - "", - true); + OptionsSection optionsSection = new OptionsSection(ElytronToolMessages.msg.cmdLineActionsHelpHeader(), options); + UsageSection usageSection = new UsageSection(FILE_SYSTEM_REALM_INTEGRITY_COMMAND, null); + DescriptionSection descriptionSection = new DescriptionSection(ElytronToolMessages.msg.cmdFileSystemIntegrityHelpHeader()); + HelpCommand helpCommand = HelpCommand.HelpCommandBuilder.builder() + .description(descriptionSection) + .usage(usageSection) + .options(optionsSection) + .build(); + helpCommand.printHelp(); } /** diff --git a/tool/src/main/java/org/wildfly/security/tool/MaskCommand.java b/tool/src/main/java/org/wildfly/security/tool/MaskCommand.java index bf029f0e6ee..154a95d9582 100644 --- a/tool/src/main/java/org/wildfly/security/tool/MaskCommand.java +++ b/tool/src/main/java/org/wildfly/security/tool/MaskCommand.java @@ -23,9 +23,12 @@ import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.DefaultParser; -import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Option; import org.apache.commons.cli.Options; +import org.wildfly.security.tool.help.DescriptionSection; +import org.wildfly.security.tool.help.HelpCommand; +import org.wildfly.security.tool.help.OptionsSection; +import org.wildfly.security.tool.help.UsageSection; import org.wildfly.security.util.PasswordBasedEncryptionUtil; import static org.wildfly.security.tool.Params.DEBUG_PARAM; @@ -158,12 +161,14 @@ static char[] decryptMasked(String maskedPassword) throws GeneralSecurityExcepti */ @Override public void help() { - HelpFormatter help = new HelpFormatter(); - help.setWidth(WIDTH); - help.printHelp(ElytronToolMessages.msg.cmdHelp(getToolCommand(), MASK_COMMAND), - ElytronToolMessages.msg.cmdMaskHelpHeader().concat(ElytronToolMessages.msg.cmdLineActionsHelpHeader()), - options, - "", - true); + OptionsSection optionsSection = new OptionsSection(ElytronToolMessages.msg.cmdLineActionsHelpHeader(), options); + UsageSection usageSection = new UsageSection(MASK_COMMAND, null); + DescriptionSection descriptionSection = new DescriptionSection(ElytronToolMessages.msg.cmdMaskHelpHeader()); + HelpCommand helpCommand = HelpCommand.HelpCommandBuilder.builder() + .description(descriptionSection) + .usage(usageSection) + .options(optionsSection) + .build(); + helpCommand.printHelp(); } } diff --git a/tool/src/main/java/org/wildfly/security/tool/VaultCommand.java b/tool/src/main/java/org/wildfly/security/tool/VaultCommand.java index edf7fb18acb..3637c9ba667 100644 --- a/tool/src/main/java/org/wildfly/security/tool/VaultCommand.java +++ b/tool/src/main/java/org/wildfly/security/tool/VaultCommand.java @@ -54,7 +54,6 @@ import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.DefaultParser; -import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Option; import org.apache.commons.cli.Options; import org.wildfly.security.auth.SupportLevel; @@ -67,6 +66,10 @@ import org.wildfly.security.credential.store.impl.KeyStoreCredentialStore; import org.wildfly.security.credential.store.impl.VaultCredentialStore; import org.wildfly.security.password.interfaces.ClearPassword; +import org.wildfly.security.tool.help.DescriptionSection; +import org.wildfly.security.tool.help.HelpCommand; +import org.wildfly.security.tool.help.OptionsSection; +import org.wildfly.security.tool.help.UsageSection; import org.wildfly.security.util.PasswordBasedEncryptionUtil; /** @@ -245,13 +248,15 @@ private void checkInvalidOptions(String... invalidOptions) throws Exception { */ @Override public void help() { - HelpFormatter help = new HelpFormatter(); - help.setWidth(WIDTH); - help.printHelp(ElytronToolMessages.msg.cmdHelp(getToolCommand(), VAULT_COMMAND), - ElytronToolMessages.msg.cmdVaultHelpHeader().concat(ElytronToolMessages.msg.cmdLineActionsHelpHeader()), - options, - "", - true); + OptionsSection optionsSection = new OptionsSection(ElytronToolMessages.msg.cmdLineActionsHelpHeader(), options); + UsageSection usageSection = new UsageSection(VAULT_COMMAND, null); + DescriptionSection descriptionSection = new DescriptionSection(ElytronToolMessages.msg.cmdVaultHelpHeader()); + HelpCommand helpCommand = HelpCommand.HelpCommandBuilder.builder() + .description(descriptionSection) + .usage(usageSection) + .options(optionsSection) + .build(); + helpCommand.printHelp(); } private String convertedStoreName(String encryptionDirectory, Map implProps) { diff --git a/tool/src/main/java/org/wildfly/security/tool/help/CommandsSection.java b/tool/src/main/java/org/wildfly/security/tool/help/CommandsSection.java new file mode 100644 index 00000000000..46fa6086c9c --- /dev/null +++ b/tool/src/main/java/org/wildfly/security/tool/help/CommandsSection.java @@ -0,0 +1,114 @@ +/* + * JBoss, Home of Professional Open Source. + * Copyright 2024 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.security.tool.help; + +import java.util.Map; + +/** + * Command section of Elytron help command + * + * @author Petr Beran + */ +public class CommandsSection extends HelpSection { + + private final String sectionTitle; + private final Map sectionContent; + + public CommandsSection(Map commands) { + this.sectionTitle = "Commands"; + this.sectionContent = commands; + } + + @Override + public void printHelp() { + formatAndPrintTitle(sectionTitle); + if (sectionContent != null) { + + // Find the longest commandName + // This is needed to make sure that all descriptions start at the same index + int longestCommand = 0; + for (String command : sectionContent.keySet()) { + if (command.length() > longestCommand) { + longestCommand = command.length(); + } + } + for (Map.Entry command : sectionContent.entrySet()) { + formatAndPrintCommand(command.getKey(), command.getValue(), longestCommand); + } + } + } + + /** + * Formats and prints command and it's respective description + * + * @param commandName Command's name + * @param commandDescription Command's description + * @param longestCommand Length of the longest commands. Ensures that all descriptions start at the same column + */ + protected void formatAndPrintCommand(String commandName, final CharSequence commandDescription, final int longestCommand) { + CharSequence descriptionText = commandDescription; + final StringBuilder stringBuilder = new StringBuilder(); + + int minCommandAndDescGap = 4; // Gap between the longest commandName and its commandDescription + int commandDescriptionStartingIndex = longestCommand + minCommandAndDescGap + leftPadding; // Starting index of all commandDescriptions in the map + int commandDescriptionLength = lineWidth - commandDescriptionStartingIndex; + + appendGap(stringBuilder, leftPadding); + stringBuilder.append(commandName); + + // Append a gap so that all commandDescriptions in the map start at the same index + int realGap = commandDescriptionStartingIndex - leftPadding - commandName.length(); + appendGap(stringBuilder, realGap); + + // If the commandDescription fits one line, simply append it + if (descriptionText.length() <= commandDescriptionLength) { + stringBuilder.append(descriptionText); + stringBuilder.append(System.lineSeparator()); + } + else { + int lineIndex = checkForWhitespaceIndex(descriptionText, commandDescriptionLength); + + // Append the commandDescription that fits on a single line and remove it from the descriptionText + stringBuilder.append(descriptionText.subSequence(0,lineIndex)); + descriptionText = descriptionText.subSequence(lineIndex+1, descriptionText.length()); + stringBuilder.append(System.lineSeparator()); + + // Appends commandDescriptions from second row onward + while(0 < descriptionText.length()) { + + // Append a gap so that all commandDescriptions in the map start at the same index + appendGap(stringBuilder, commandDescriptionStartingIndex); + + // If the commandDescription fits one line, simply append it and end the while loop + if (descriptionText.length() <= commandDescriptionLength) { + stringBuilder.append(descriptionText); + stringBuilder.append(System.lineSeparator()); + break; + } + + lineIndex = checkForWhitespaceIndex(descriptionText, commandDescriptionLength); + + // Append the commandDescription that fits on a single line and remove it from the descriptionText + stringBuilder.append(descriptionText.subSequence(0,lineIndex)); + descriptionText = descriptionText.subSequence(lineIndex+1, descriptionText.length()); + stringBuilder.append(System.lineSeparator()); + } + } + printText(stringBuilder.toString()); + } +} diff --git a/tool/src/main/java/org/wildfly/security/tool/help/DescriptionSection.java b/tool/src/main/java/org/wildfly/security/tool/help/DescriptionSection.java new file mode 100644 index 00000000000..8721093e15f --- /dev/null +++ b/tool/src/main/java/org/wildfly/security/tool/help/DescriptionSection.java @@ -0,0 +1,43 @@ +/* + * JBoss, Home of Professional Open Source. + * Copyright 2024 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.security.tool.help; + +/** + * Description section of Elytron help command + * + * @author Petr Beran + */ +public class DescriptionSection extends HelpSection { + + private final String sectionTitle; + private final String sectionContent; + + + public DescriptionSection(String sectionContent) { + this.sectionTitle = "Description"; + this.sectionContent = sectionContent; + } + + @Override + public void printHelp() { + formatAndPrintTitle(sectionTitle); + if (sectionContent != null) { + formatAndPrintSectionContext(sectionContent); + } + } +} diff --git a/tool/src/main/java/org/wildfly/security/tool/help/HelpCommand.java b/tool/src/main/java/org/wildfly/security/tool/help/HelpCommand.java new file mode 100644 index 00000000000..342cd2457af --- /dev/null +++ b/tool/src/main/java/org/wildfly/security/tool/help/HelpCommand.java @@ -0,0 +1,115 @@ +/* + * JBoss, Home of Professional Open Source. + * Copyright 2024 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.security.tool.help; + +import org.aesh.readline.tty.terminal.TerminalConnection; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; + +/** + * Provides help for the Elytron Tool command + * + * @author Petr Beran + */ +public class HelpCommand { + + private final List helpSections; + private static TerminalConnection terminalConnection; + + private HelpCommand(HelpCommandBuilder helpCommandBuilder) { + this.helpSections = helpCommandBuilder.helpSections; + } + + /** + * Displays all sections for the help command + */ + public void printHelp() { + if (terminalConnection == null) { + try { + terminalConnection = new TerminalConnection(Charset.defaultCharset(), System.in, System.out); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + terminalConnection.write(System.lineSeparator()); + for (HelpSection helpSection : helpSections){ + helpSection.printHelp(); + } + terminalConnection.close(); + } + + public static TerminalConnection getTerminal() { + return terminalConnection; + } + + public static class HelpCommandBuilder { + + private UsageSection usageSection; + private DescriptionSection descriptionSection; + private CommandsSection commandsSection; + private OptionsSection optionsSection; + + private final List helpSections = new ArrayList<>(); + + private HelpCommandBuilder() {} + + public static HelpCommandBuilder builder() { + return new HelpCommandBuilder(); + } + + public HelpCommandBuilder usage(UsageSection usageSection) { + this.usageSection = usageSection; + return this; + } + + public HelpCommandBuilder description(DescriptionSection descriptionSection) { + this.descriptionSection = descriptionSection; + return this; + } + + public HelpCommandBuilder commands(CommandsSection commandsSection) { + this.commandsSection = commandsSection; + return this; + } + + public HelpCommandBuilder options(OptionsSection optionsSection) { + this.optionsSection = optionsSection; + return this; + } + + public HelpCommand build() { + // Ensures that all sections are in specific order and the order cannot be tampered with + if (descriptionSection != null) { + helpSections.add(descriptionSection); + } + if (usageSection != null) { + helpSections.add(usageSection); + } + if (commandsSection != null) { + helpSections.add(commandsSection); + } + if (optionsSection != null) { + helpSections.add(optionsSection); + } + return new HelpCommand(this); + } + } +} diff --git a/tool/src/main/java/org/wildfly/security/tool/help/HelpSection.java b/tool/src/main/java/org/wildfly/security/tool/help/HelpSection.java new file mode 100644 index 00000000000..a6f5a6727f4 --- /dev/null +++ b/tool/src/main/java/org/wildfly/security/tool/help/HelpSection.java @@ -0,0 +1,122 @@ +/* + * JBoss, Home of Professional Open Source. + * Copyright 2024 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.security.tool.help; + +import org.aesh.readline.terminal.formatting.CharacterType; +import org.aesh.readline.terminal.formatting.Color; +import org.aesh.readline.terminal.formatting.TerminalColor; +import org.aesh.readline.terminal.formatting.TerminalString; +import org.aesh.readline.terminal.formatting.TerminalTextStyle; +import org.aesh.readline.tty.terminal.TerminalConnection; + +/** + * General section of Elytron help command + * All Elytron help command sections should extend this one + * + * @author Petr Beran + */ +public abstract class HelpSection { + + final int leftPadding = 4; + final int lineWidth = 120; + final int textWidth = lineWidth - leftPadding; + + /** + * Displays help of specific section + */ + public abstract void printHelp(); + + /** + * Formats and prints a simple block of text + * For printing commands see {@link CommandsSection} + * + * @param text Text to print + */ + protected void formatAndPrintSectionContext(final CharSequence text) { + final StringBuilder stringBuilder = new StringBuilder(); + CharSequence contentText = text; + while(0 < contentText.length()) { + appendGap(stringBuilder, leftPadding); + // If the text fits one line, simply append it and end the while loop + if (contentText.length() <= textWidth) { + stringBuilder.append(contentText); + stringBuilder.append(System.lineSeparator()); + break; + } + int lineIndex = checkForWhitespaceIndex(contentText, textWidth); + // Append the text that fits on a single line and remove it from the contentText + stringBuilder.append(contentText.subSequence(0,lineIndex)); + contentText = contentText.subSequence(lineIndex+1, contentText.length()); + stringBuilder.append(System.lineSeparator()); + } + printText(stringBuilder.toString()); + } + + /** + * Formats and prints headers across all sections + * + * @param sectionTitle Title to format and print + */ + protected void formatAndPrintTitle(String sectionTitle) { + String titleText = new TerminalString(sectionTitle.toUpperCase(), + new TerminalColor(Color.CYAN, Color.DEFAULT, Color.Intensity.BRIGHT), + new TerminalTextStyle(CharacterType.BOLD)).toString(); + printText(titleText); + System.out.print(System.lineSeparator()); + } + + /** + * Finds the index of text that still fits on a single line and is a whitespace. + * We don't want to break words at the end of the line + * + * @param text Text to iterate + * @param maxWidth Max width of the line, start of the iteration + * @return Last whitespace index before the end of the line + */ + protected int checkForWhitespaceIndex(CharSequence text, int maxWidth) { + int lastWhitespaceIndex = maxWidth; + while (0 <= lastWhitespaceIndex && !Character.isWhitespace(text.charAt(lastWhitespaceIndex))) { + lastWhitespaceIndex--; + } + return lastWhitespaceIndex; + } + + /** + * Appends a gap of certain width + * + * @param text Text to which the gap should be appended + * @param gapWidth Width of the gap + */ + protected void appendGap(StringBuilder text, int gapWidth) { + for (int i = 0; i < gapWidth; i++){ + text.append(' '); + } + } + + /** + * Prints the text via system terminal and adds a line separator at the end. Doesn't add any formatting. + * + * @param text Text to print. Leave {@code null} for just a line separator. + */ + void printText(String text) { + TerminalConnection terminalConnection = HelpCommand.getTerminal(); + if (text != null) { + terminalConnection.write(text); + } + } +} diff --git a/tool/src/main/java/org/wildfly/security/tool/help/OptionsSection.java b/tool/src/main/java/org/wildfly/security/tool/help/OptionsSection.java new file mode 100644 index 00000000000..d82f0186619 --- /dev/null +++ b/tool/src/main/java/org/wildfly/security/tool/help/OptionsSection.java @@ -0,0 +1,55 @@ +/* + * JBoss, Home of Professional Open Source. + * Copyright 2024 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.security.tool.help; + +import org.apache.commons.cli.HelpFormatter; +import org.apache.commons.cli.Options; +import org.wildfly.security.tool.ElytronToolMessages; + +/** + * Options section of Elytron help tool + * @author Petr Beran + */ +public class OptionsSection extends HelpSection { + + private final String sectionTitle; + private final String sectionHeader; + private final Options sectionContent; + + public OptionsSection(String sectionHeader, Options options) { + this.sectionTitle = "Options"; + this.sectionHeader = sectionHeader; + this.sectionContent = options; + } + + @Override + public void printHelp() { + formatAndPrintTitle(sectionTitle); + if (sectionHeader != null) { + formatAndPrintSectionContext(sectionHeader); + } + if (sectionContent != null) { + HelpFormatter help = new HelpFormatter(); + help.setSyntaxPrefix(""); + help.setLeftPadding(4); + help.setWidth(120); + help.printHelp(ElytronToolMessages.msg.cmdHelp("", ""), sectionContent); + printText(null); + } + } +} diff --git a/tool/src/main/java/org/wildfly/security/tool/help/UsageSection.java b/tool/src/main/java/org/wildfly/security/tool/help/UsageSection.java new file mode 100644 index 00000000000..01c235c318d --- /dev/null +++ b/tool/src/main/java/org/wildfly/security/tool/help/UsageSection.java @@ -0,0 +1,56 @@ +/* + * JBoss, Home of Professional Open Source. + * Copyright 2024 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.security.tool.help; + +/** + * Usage section of Elytron help command + * + * @author Petr Beran + */ +public class UsageSection extends HelpSection { + + private final String sectionTitle; + private final String sectionContent; + + public UsageSection(String command, String option) { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("./elytron-tool.sh"); + + if (command != null) { + stringBuilder.append(" " + command); + } + else { + stringBuilder.append(" [command]"); + } + + if (option != null) { + stringBuilder.append(" " + option); + } + else { + stringBuilder.append(" [options]"); + } + this.sectionTitle = "Usage"; + this.sectionContent = stringBuilder.toString(); + } + + @Override + public void printHelp() { + formatAndPrintTitle(sectionTitle); + formatAndPrintSectionContext(sectionContent); + } +} diff --git a/tool/src/test/java/org/wildfly/security/tool/FileSystemEncryptRealmCommandTest.java b/tool/src/test/java/org/wildfly/security/tool/FileSystemEncryptRealmCommandTest.java index 32ff3c29f2d..e2c562d255a 100644 --- a/tool/src/test/java/org/wildfly/security/tool/FileSystemEncryptRealmCommandTest.java +++ b/tool/src/test/java/org/wildfly/security/tool/FileSystemEncryptRealmCommandTest.java @@ -45,7 +45,7 @@ /** * @author Ashpan Raskar - * @author Cameron Rodriguez + * @author Jessica Rodriguez */ public class FileSystemEncryptRealmCommandTest extends AbstractCommandTest { diff --git a/tool/src/test/java/org/wildfly/security/tool/FileSystemRealmIntegrityCommandTest.java b/tool/src/test/java/org/wildfly/security/tool/FileSystemRealmIntegrityCommandTest.java index 2d134d31d7f..c1c06365516 100644 --- a/tool/src/test/java/org/wildfly/security/tool/FileSystemRealmIntegrityCommandTest.java +++ b/tool/src/test/java/org/wildfly/security/tool/FileSystemRealmIntegrityCommandTest.java @@ -55,7 +55,7 @@ import org.apache.commons.lang3.tuple.ImmutablePair; import org.junit.Test; -/** @author Cameron Rodriguez */ +/** @author Jessica Rodriguez */ public class FileSystemRealmIntegrityCommandTest extends AbstractCommandTest { private static final String RELATIVE_BASE_DIR = "./target/test-classes/filesystem-integrity/"; diff --git a/util/pom.xml b/util/pom.xml index 5c4ad863994..4ee89f9b23a 100644 --- a/util/pom.xml +++ b/util/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT 4.0.0 diff --git a/wildfly-elytron/pom.xml b/wildfly-elytron/pom.xml index c4428245d15..2bf06d9be43 100644 --- a/wildfly-elytron/pom.xml +++ b/wildfly-elytron/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT 4.0.0 @@ -557,7 +557,7 @@ org.wildfly.security wildfly-elytron - 2.5.1.Final + 2.6.0.Final jar diff --git a/x500/base/pom.xml b/x500/base/pom.xml index b0b912c4974..740db174f50 100644 --- a/x500/base/pom.xml +++ b/x500/base/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../pom.xml diff --git a/x500/base/src/test/java/org/wildfly/security/x500/X500PrincipalBuilderTest.java b/x500/base/src/test/java/org/wildfly/security/x500/X500PrincipalBuilderTest.java index 1fd04e5449e..afd8f1916c0 100644 --- a/x500/base/src/test/java/org/wildfly/security/x500/X500PrincipalBuilderTest.java +++ b/x500/base/src/test/java/org/wildfly/security/x500/X500PrincipalBuilderTest.java @@ -18,7 +18,7 @@ package org.wildfly.security.x500; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; import java.util.Arrays; diff --git a/x500/cert/acme/pom.xml b/x500/cert/acme/pom.xml index 11e6eaf787c..c2040a3d5ed 100644 --- a/x500/cert/acme/pom.xml +++ b/x500/cert/acme/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../../pom.xml @@ -105,7 +105,7 @@ test - org.glassfish + org.eclipse.parsson jakarta.json test diff --git a/x500/cert/base/pom.xml b/x500/cert/base/pom.xml index 0a5baf9a738..6af3f479612 100644 --- a/x500/cert/base/pom.xml +++ b/x500/cert/base/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../../pom.xml diff --git a/x500/cert/base/src/test/java/org/wildfly/security/x500/cert/X509CertificateBuilderTest.java b/x500/cert/base/src/test/java/org/wildfly/security/x500/cert/X509CertificateBuilderTest.java index 741398b254a..d07539aa0e0 100644 --- a/x500/cert/base/src/test/java/org/wildfly/security/x500/cert/X509CertificateBuilderTest.java +++ b/x500/cert/base/src/test/java/org/wildfly/security/x500/cert/X509CertificateBuilderTest.java @@ -18,7 +18,10 @@ package org.wildfly.security.x500.cert; -import static org.junit.Assert.*; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import java.math.BigInteger; import java.security.KeyFactory; diff --git a/x500/cert/util/pom.xml b/x500/cert/util/pom.xml index 536305499c0..5a548aa9725 100644 --- a/x500/cert/util/pom.xml +++ b/x500/cert/util/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../../pom.xml @@ -55,7 +55,7 @@ org.jboss.logging jboss-logging-processor provided - + diff --git a/x500/deprecated/pom.xml b/x500/deprecated/pom.xml index f93de8dea27..27075a20280 100644 --- a/x500/deprecated/pom.xml +++ b/x500/deprecated/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../pom.xml diff --git a/x500/deprecated/src/main/java/org/wildfly/security/x500/X500AttributePrincipalDecoder.java b/x500/deprecated/src/main/java/org/wildfly/security/x500/X500AttributePrincipalDecoder.java index e311f0f2a21..13169db15af 100644 --- a/x500/deprecated/src/main/java/org/wildfly/security/x500/X500AttributePrincipalDecoder.java +++ b/x500/deprecated/src/main/java/org/wildfly/security/x500/X500AttributePrincipalDecoder.java @@ -31,7 +31,7 @@ * A principal decoder which decodes an attribute from an X.500 principal. * * @author David M. Lloyd - * @deprecated Use {@link org.wildfly.security.x500.principal.X500AttributePrincipalDecoder} instead + * @deprecated Use {@link org.wildfly.security.x500.principal.X500AttributePrincipalDecoder org.wildfly.security.x500.principal.X500AttributePrincipalDecoder} instead */ @Deprecated public final class X500AttributePrincipalDecoder implements PrincipalDecoder { diff --git a/x500/principal/pom.xml b/x500/principal/pom.xml index caf08adca64..341c8a24c22 100644 --- a/x500/principal/pom.xml +++ b/x500/principal/pom.xml @@ -24,7 +24,7 @@ org.wildfly.security wildfly-elytron-parent - 2.5.2.CR1-SNAPSHOT + 2.6.1.CR1-SNAPSHOT ../../pom.xml