Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[WFCORE-5691][Preview] Allow setting timeout for token introspection #6033

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions elytron/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,7 @@
<exclude>jacc-with-providers.xml</exclude>
<exclude>legacy*.xml</exclude>
<exclude>elytron-subsystem-community*.xml</exclude>
<exclude>elytron-subsystem-preview*.xml</exclude>
</excludes>
<systemId>src/main/resources/schema/wildfly-elytron_18_0.xsd</systemId>
</validationSet>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,9 @@ public class ElytronExtension implements Extension {
static final ModelVersion ELYTRON_17_0_0 = ModelVersion.create(17);
static final ModelVersion ELYTRON_18_0_0 = ModelVersion.create(18);
static final ModelVersion ELYTRON_19_0_0 = ModelVersion.create(19);
static final ModelVersion ELYTRON_20_0_0 = ModelVersion.create(20);

private static final ModelVersion ELYTRON_CURRENT = ELYTRON_19_0_0;
private static final ModelVersion ELYTRON_CURRENT = ELYTRON_20_0_0;

static final String ISO_8601_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,9 @@ public enum ElytronSubsystemSchema implements PersistentSubsystemSchema<ElytronS
VERSION_17_0(17),
VERSION_18_0(18),
VERSION_18_0_COMMUNITY(18, Stability.COMMUNITY),
VERSION_18_0_PREVIEW(18, Stability.PREVIEW),
;
static final Map<Stability, ElytronSubsystemSchema> CURRENT = Feature.map(EnumSet.of(VERSION_18_0, VERSION_18_0_COMMUNITY));
static final Map<Stability, ElytronSubsystemSchema> CURRENT = Feature.map(EnumSet.of(VERSION_18_0, VERSION_18_0_COMMUNITY, VERSION_18_0_PREVIEW));

private final VersionedNamespace<IntVersion, ElytronSubsystemSchema> namespace;

Expand Down Expand Up @@ -231,7 +232,9 @@ private void addMapperParser(PersistentResourceXMLDescription.PersistentResource

private void addRealmParser(PersistentResourceXMLDescription.PersistentResourceXMLBuilder builder) {
RealmParser realmParser = new RealmParser();
if (this.since(ElytronSubsystemSchema.VERSION_18_0)) {
if (this.since(ElytronSubsystemSchema.VERSION_18_0_PREVIEW)) {
builder.addChild(realmParser.realmParserPreview_18_0);
} else if (this.since(ElytronSubsystemSchema.VERSION_18_0)) {
builder.addChild(realmParser.realmParser_18);
} else if (this.since(ElytronSubsystemSchema.VERSION_16_0)) {
builder.addChild(realmParser.realmParser_16);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ public String getSubsystemName() {
public void registerTransformers(SubsystemTransformerRegistration registration) {
ChainedTransformationDescriptionBuilder chainedBuilder = TransformationDescriptionBuilder.Factory.createChainedSubystemInstance(registration.getCurrentSubsystemVersion());

// 20.0.0 (WildFly 34) to 19.0.0 (WildFly 32)
from20(chainedBuilder);
// 19.0.0 (WildFly 32) to 18.0.0 (WildFly 29)
from19(chainedBuilder);
// 18.0.0 (WildFly 29) to 17.0.0 (WildFly 28)
Expand Down Expand Up @@ -145,10 +147,15 @@ public void registerTransformers(SubsystemTransformerRegistration registration)
// 2.0.0 (WildFly 12) to 1.2.0, (WildFly 11 and EAP 7.1.0)
from2(chainedBuilder);

chainedBuilder.buildAndRegister(registration, new ModelVersion[] { ELYTRON_18_0_0, ELYTRON_17_0_0, ELYTRON_16_0_0, ELYTRON_15_1_0, ELYTRON_15_0_0, ELYTRON_14_0_0, ELYTRON_13_0_0, ELYTRON_12_0_0, ELYTRON_11_0_0, ELYTRON_10_0_0, ELYTRON_9_0_0,
chainedBuilder.buildAndRegister(registration, new ModelVersion[] { ELYTRON_19_0_0, ELYTRON_18_0_0, ELYTRON_17_0_0, ELYTRON_16_0_0, ELYTRON_15_1_0, ELYTRON_15_0_0, ELYTRON_14_0_0, ELYTRON_13_0_0, ELYTRON_12_0_0, ELYTRON_11_0_0, ELYTRON_10_0_0, ELYTRON_9_0_0,
ELYTRON_8_0_0, ELYTRON_7_0_0, ELYTRON_6_0_0, ELYTRON_5_0_0, ELYTRON_4_0_0, ELYTRON_3_0_0, ELYTRON_2_0_0, ELYTRON_1_2_0 });
}

private static void from20(ChainedTransformationDescriptionBuilder chainedBuilder) {
ResourceTransformationDescriptionBuilder builder = chainedBuilder.createBuilder(ELYTRON_19_0_0, ELYTRON_18_0_0);

}

private static void from19(ChainedTransformationDescriptionBuilder chainedBuilder) {
ResourceTransformationDescriptionBuilder builder = chainedBuilder.createBuilder(ELYTRON_19_0_0, ELYTRON_18_0_0);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@ class RealmParser {
private final PersistentResourceXMLDescription tokenRealmParser = builder(PathElement.pathElement(ElytronDescriptionConstants.TOKEN_REALM))
.addAttributes(TokenRealmDefinition.ATTRIBUTES)
.build();
private final PersistentResourceXMLDescription tokenRealmParserPreview_18_0 = builder(PathElement.pathElement(ElytronDescriptionConstants.TOKEN_REALM))
.addAttributes(TokenRealmDefinition.ATTRIBUTES)
.build();
private final PersistentResourceXMLDescription cachingRealmParser = builder(PathElement.pathElement(ElytronDescriptionConstants.CACHING_REALM))
.addAttributes(CachingRealmDefinition.ATTRIBUTES)
.build();
Expand Down Expand Up @@ -272,6 +275,23 @@ class RealmParser {
.addChild(jaasRealmParser)
.build();

final PersistentResourceXMLDescription realmParserPreview_18_0 = decorator(ElytronDescriptionConstants.SECURITY_REALMS)
.addChild(aggregateRealmParser_8_0)
.addChild(customRealmParser)
.addChild(customModifiableRealmParser)
.addChild(identityRealmParser)
.addChild(jdbcRealmParser_14_0)
.addChild(keyStoreRealmParser)
.addChild(propertiesRealmParser_14_0)
.addChild(ldapRealmParser)
.addChild(filesystemRealmParser_16)
.addChild(tokenRealmParserPreview_18_0)
.addChild(cachingRealmParser)
.addChild(distributedRealmParser_18)
.addChild(failoverRealmParser)
.addChild(jaasRealmParser)
.build();

RealmParser() {

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,13 @@
import org.jboss.as.controller.StringListAttributeDefinition;
import org.jboss.as.controller.capability.RuntimeCapability;
import org.jboss.as.controller.operations.validation.EnumValidator;
import org.jboss.as.controller.operations.validation.IntRangeValidator;
import org.jboss.as.controller.operations.validation.StringLengthValidator;
import org.jboss.as.controller.parsing.ParseUtils;
import org.jboss.as.controller.registry.AttributeAccess;
import org.jboss.as.controller.registry.ManagementResourceRegistration;
import org.jboss.as.controller.registry.OperationEntry;
import org.jboss.as.version.Stability;
import org.jboss.dmr.ModelNode;
import org.jboss.dmr.ModelType;
import org.jboss.msc.service.ServiceBuilder;
Expand Down Expand Up @@ -148,6 +150,20 @@ static class JwtValidatorAttributes {
.setMinSize(1)
.build();

static final SimpleAttributeDefinition CONNECTION_TIMEOUT = new SimpleAttributeDefinitionBuilder(ElytronDescriptionConstants.CONNECTION_TIMEOUT, ModelType.INT, true)
.setStability(Stability.PREVIEW)
.setAllowExpression(true)
.setValidator(new IntRangeValidator(0))
.setRestartAllServices()
.build();

static final SimpleAttributeDefinition READ_TIMEOUT = new SimpleAttributeDefinitionBuilder(ElytronDescriptionConstants.READ_TIMEOUT, ModelType.INT, true)
.setStability(Stability.PREVIEW)
.setAllowExpression(true)
.setValidator(new IntRangeValidator(0))
.setRestartAllServices()
.build();

static final PropertiesAttributeDefinition KEY_MAP = new PropertiesAttributeDefinition.Builder(ElytronDescriptionConstants.KEY_MAP, true)
.setAllowExpression(true)
.setMinSize(1)
Expand All @@ -171,7 +187,7 @@ public void marshallSingleElement(AttributeDefinition attribute, ModelNode prope
.setRestartAllServices()
.build();

static final ObjectTypeAttributeDefinition JWT_VALIDATOR = new ObjectTypeAttributeDefinition.Builder(JWT, ISSUER, AUDIENCE, PUBLIC_KEY, KEY_STORE, CERTIFICATE, SSL_CONTEXT, HOSTNAME_VERIFICATION_POLICY, KEY_MAP)
static final ObjectTypeAttributeDefinition JWT_VALIDATOR = new ObjectTypeAttributeDefinition.Builder(JWT, ISSUER, AUDIENCE, PUBLIC_KEY, KEY_STORE, CERTIFICATE, SSL_CONTEXT, HOSTNAME_VERIFICATION_POLICY, KEY_MAP, CONNECTION_TIMEOUT, READ_TIMEOUT)
.setRequired(false)
.setRestartAllServices()
.build();
Expand All @@ -198,9 +214,23 @@ static class OAuth2IntrospectionValidatorAttributes {
.setFlags(AttributeAccess.Flag.RESTART_RESOURCE_SERVICES)
.build();

static final AttributeDefinition[] ATTRIBUTES = new AttributeDefinition[]{CLIENT_ID, CLIENT_SECRET, INTROSPECTION_URL, SSL_CONTEXT, HOSTNAME_VERIFICATION_POLICY};
static final SimpleAttributeDefinition CONNECTION_TIMEOUT = new SimpleAttributeDefinitionBuilder(ElytronDescriptionConstants.CONNECTION_TIMEOUT, ModelType.INT, true)
.setStability(Stability.PREVIEW)
.setAllowExpression(true)
.setValidator(new IntRangeValidator(0))
.setRestartAllServices()
.build();

static final SimpleAttributeDefinition READ_TIMEOUT = new SimpleAttributeDefinitionBuilder(ElytronDescriptionConstants.READ_TIMEOUT, ModelType.INT, true)
.setStability(Stability.PREVIEW)
.setAllowExpression(true)
.setValidator(new IntRangeValidator(0))
.setRestartAllServices()
.build();

static final AttributeDefinition[] ATTRIBUTES = new AttributeDefinition[]{CLIENT_ID, CLIENT_SECRET, INTROSPECTION_URL, SSL_CONTEXT, HOSTNAME_VERIFICATION_POLICY, CONNECTION_TIMEOUT, READ_TIMEOUT};

static final ObjectTypeAttributeDefinition OAUTH2_INTROSPECTION_VALIDATOR = new ObjectTypeAttributeDefinition.Builder(OAUTH2_INTROSPECTION, CLIENT_ID, CLIENT_SECRET, INTROSPECTION_URL, SSL_CONTEXT, HOSTNAME_VERIFICATION_POLICY)
static final ObjectTypeAttributeDefinition OAUTH2_INTROSPECTION_VALIDATOR = new ObjectTypeAttributeDefinition.Builder(OAUTH2_INTROSPECTION, CLIENT_ID, CLIENT_SECRET, INTROSPECTION_URL, SSL_CONTEXT, HOSTNAME_VERIFICATION_POLICY, CONNECTION_TIMEOUT, READ_TIMEOUT)
.setRequired(false)
.setRestartAllServices()
.build();
Expand Down Expand Up @@ -271,6 +301,8 @@ protected void performRuntime(OperationContext context, ModelNode operation, Mod
String sslContextRef = SSL_CONTEXT.resolveModelAttribute(context, jwtValidatorNode).asStringOrNull();
String hostNameVerificationPolicy = HOSTNAME_VERIFICATION_POLICY.resolveModelAttribute(context, jwtValidatorNode).asStringOrNull();
InjectedValue<SSLContext> sslContextInjector = new InjectedValue<>();
Integer connectionTimeout = JwtValidatorAttributes.CONNECTION_TIMEOUT.resolveModelAttribute(context, jwtValidatorNode).asIntOrNull();
Integer readTimeout = JwtValidatorAttributes.READ_TIMEOUT.resolveModelAttribute(context, jwtValidatorNode).asIntOrNull();
ModelNode keyMap = KEY_MAP.resolveModelAttribute(context, jwtValidatorNode);
Map<String, PublicKey> namedKeys = new LinkedHashMap<>();
if (keyMap.isDefined()) {
Expand Down Expand Up @@ -320,6 +352,12 @@ public SecurityRealm get() throws StartException {
if (namedKeys.size() > 0) {
jwtValidatorBuilder.publicKeys(namedKeys);
}
if (connectionTimeout != null) {
jwtValidatorBuilder.connectionTimeout(connectionTimeout);
}
if (readTimeout != null) {
jwtValidatorBuilder.readTimeout(readTimeout);
}
KeyStore keyStore = keyStoreInjector.getOptionalValue();

if (keyStore != null) {
Expand Down Expand Up @@ -375,6 +413,8 @@ public void dispose() {
String introspectionUrl = OAuth2IntrospectionValidatorAttributes.INTROSPECTION_URL.resolveModelAttribute(context, oAuth2IntrospectionNode).asString();
String sslContextRef = SSL_CONTEXT.resolveModelAttribute(context, oAuth2IntrospectionNode).asStringOrNull();
String hostNameVerificationPolicy = HOSTNAME_VERIFICATION_POLICY.resolveModelAttribute(context, oAuth2IntrospectionNode).asStringOrNull();
Integer connectionTimeout = OAuth2IntrospectionValidatorAttributes.CONNECTION_TIMEOUT.resolveModelAttribute(context, oAuth2IntrospectionNode).asIntOrNull();
Integer readTimeout = OAuth2IntrospectionValidatorAttributes.READ_TIMEOUT.resolveModelAttribute(context, oAuth2IntrospectionNode).asIntOrNull();
InjectedValue<SSLContext> sslContextInjector = new InjectedValue<>();

service = new TrivialService<>(new TrivialService.ValueSupplier<SecurityRealm>() {
Expand All @@ -389,6 +429,12 @@ public SecurityRealm get() throws StartException {
.tokenIntrospectionUrl(new URL(introspectionUrl))
.useSslContext(sslContextInjector.getOptionalValue())
.useSslHostnameVerifier(verifier);
if (connectionTimeout != null) {
builder.connectionTimeout(connectionTimeout);
}
if (readTimeout != null) {
builder.readTimeout(readTimeout);
}
return TokenSecurityRealm.builder().principalClaimName(principalClaimNode.asString())
.validator(builder.build())
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -932,13 +932,17 @@ elytron.token-realm.jwt.key-map=A map of named public keys for token verificatio
elytron.token-realm.jwt.certificate=The name of the certificate with a public key to load from the key store.
elytron.token-realm.jwt.client-ssl-context=The SSL context to be used for fetching jku keys using HTTPS.
elytron.token-realm.jwt.host-name-verification-policy=A policy that defines how host names should be verified when using HTTPS.
elytron.token-realm.jwt.connection-timeout=The timeout for connecting in milliseconds. A non-zero value specifies the timeout when connecting to a resource. A timeout of zero is interpreted as an infinite timeout.
elytron.token-realm.jwt.read-timeout=The read timeout in milliseconds. A non-zero value specifies the timeout when reading from Input stream when a connection is established to a resource. A timeout of zero is interpreted as an infinite timeout.
# OAuth2 Introspection Validator Complex Attribute
elytron.token-realm.oauth2-introspection=A token validator to be used in conjunction with a token-based realm that handles OAuth2 Access Tokens and validates them using an endpoint compliant with OAuth2 Token Introspection specification(RFC-7662).
elytron.token-realm.oauth2-introspection.client-id=The identifier of the client on the OAuth2 Authorization Server.
elytron.token-realm.oauth2-introspection.client-secret=The secret of the client.
elytron.token-realm.oauth2-introspection.introspection-url=The URL of token introspection endpoint.
elytron.token-realm.oauth2-introspection.client-ssl-context=The SSL context to be used if the introspection endpoint is using HTTPS.
elytron.token-realm.oauth2-introspection.host-name-verification-policy=A policy that defines how host names should be verified when using HTTPS. Allowed values: 'ANY'.
elytron.token-realm.oauth2-introspection.connection-timeout=The timeout for connecting in milliseconds. A non-zero value specifies the timeout when connecting to a resource. A timeout of zero is interpreted as an infinite timeout.
elytron.token-realm.oauth2-introspection.read-timeout=The read timeout in milliseconds. A non-zero value specifies the timeout when reading from Input stream when a connection is established to a resource. A timeout of zero is interpreted as an infinite timeout.

# Identity management descriptions
elytron.modifiable-security-realm.add-identity=Add an identity to a security realm.
Expand Down
Loading
Loading