diff --git a/common/src/main/java/org/keycloak/common/Profile.java b/common/src/main/java/org/keycloak/common/Profile.java index faad755025..dd5dd61da7 100755 --- a/common/src/main/java/org/keycloak/common/Profile.java +++ b/common/src/main/java/org/keycloak/common/Profile.java @@ -48,37 +48,43 @@ public class Profile { } public enum Feature { - AUTHORIZATION(Type.DEFAULT), - ACCOUNT2(Type.DEFAULT), - ACCOUNT_API(Type.DEFAULT), - ADMIN_FINE_GRAINED_AUTHZ(Type.PREVIEW), - ADMIN2(Type.EXPERIMENTAL), - DOCKER(Type.DISABLED_BY_DEFAULT), - IMPERSONATION(Type.DEFAULT), - OPENSHIFT_INTEGRATION(Type.PREVIEW), - SCRIPTS(Type.PREVIEW), - TOKEN_EXCHANGE(Type.PREVIEW), - UPLOAD_SCRIPTS(DEPRECATED), - WEB_AUTHN(Type.DEFAULT, Type.PREVIEW), - CLIENT_POLICIES(Type.DEFAULT), - CIBA(Type.DEFAULT), - MAP_STORAGE(Type.EXPERIMENTAL), - PAR(Type.DEFAULT), - DECLARATIVE_USER_PROFILE(Type.PREVIEW), - DYNAMIC_SCOPES(Type.EXPERIMENTAL); + AUTHORIZATION("Authorization Service", Type.DEFAULT), + ACCOUNT2("New Account Management Console", Type.DEFAULT), + ACCOUNT_API("Account Management REST API", Type.DEFAULT), + ADMIN_FINE_GRAINED_AUTHZ("Fine-Grained Admin Permissions", Type.PREVIEW), + ADMIN2("New Admin Console", Type.EXPERIMENTAL), + DOCKER("Docker Registry protocol", Type.DISABLED_BY_DEFAULT), + IMPERSONATION("Ability for admins to impersonate users", Type.DEFAULT), + OPENSHIFT_INTEGRATION("Extension to enable securing OpenShift", Type.PREVIEW), + SCRIPTS("Write custom authenticators using JavaScript", Type.PREVIEW), + TOKEN_EXCHANGE("Token Exchange Service", Type.PREVIEW), + UPLOAD_SCRIPTS("Ability to upload custom JavaScript through Admin REST API", DEPRECATED), + WEB_AUTHN("W3C Web Authentication (WebAuthn)", Type.DEFAULT, Type.PREVIEW), + CLIENT_POLICIES("Client configuration policies", Type.DEFAULT), + CIBA("OpenID Connect Client Initiated Backchannel Authentication (CIBA)", Type.DEFAULT), + MAP_STORAGE("New store", Type.EXPERIMENTAL), + PAR("OAuth 2.0 Pushed Authorization Requests (PAR)", Type.DEFAULT), + DECLARATIVE_USER_PROFILE("Configure user profiles using a declarative style", Type.PREVIEW), + DYNAMIC_SCOPES("Dynamic OAuth 2.0 scopes", Type.EXPERIMENTAL); + private String label; private final Type typeProject; private final Type typeProduct; - Feature(Type type) { - this(type, type); + Feature(String label, Type type) { + this(label, type, type); } - Feature(Type typeProject, Type typeProduct) { + Feature(String label, Type typeProject, Type typeProduct) { + this.label = label; this.typeProject = typeProject; this.typeProduct = typeProduct; } + public String getLabel() { + return label; + } + public Type getTypeProject() { return typeProject; } diff --git a/docs/guides/src/main/server/features.adoc b/docs/guides/src/main/server/features.adoc new file mode 100644 index 0000000000..c8cd814609 --- /dev/null +++ b/docs/guides/src/main/server/features.adoc @@ -0,0 +1,78 @@ +<#import "/templates/guide.adoc" as tmpl> +<#import "/templates/kc.adoc" as kc> +<#import "/templates/options.adoc" as opts> + +<@tmpl.guide +title="Enabling and disabling features" +summary="Understand how to configure Keycloak to use optional features"> + +Keycloak has packed some functionality in features, some of them not enabled by default. These features include features that are in tech preview or deprecated features. In addition there are some features that are enabled by default, but can be disabled if you don't need them for your specific usage scenario. + +== Enabling features + +Some supported features, and all preview features, are not enabled by default. To enable a feature use: + +<@kc.build parameters="--features=[,]"/> + +For example to enable `docker` and `token-exchange` use: + +<@kc.build parameters="--features=docker,token-exchange"/> + +All preview features can be enabled with the special name `preview`: + +<@kc.build parameters="--features=preview"/> + +== Disabling features + +To disable a feature that is enabled by default use: + +<@kc.build parameters="--features-disabled=[,]"/> + +For example to disable `impersonation` use: + +<@kc.build parameters="--features-disabled=impersonation"/> + +It is also possible to disable all default features with: + +<@kc.build parameters="--features-disabled=default"/> + +This can be used in combination with `features` to explicitly set what features should be available. If a feature is +added both to the `features-disabled` list and the `features` list it will be enabled. + +== Supported features + +The following list contains supported features that are enabled by default, and can be disabled if not needed. + +<@showFeatures ctx.features.supported/> + +=== Disabled by default + +The following list contains supported features that are not enabled by default, and can be enabled if needed. + +<@showFeatures ctx.features.supportedDisabledByDefault/> + +== Preview features + +Preview features are not enabled by default, and are not recommended for use in production. These features may change, or +even be removed, in a future release. + +<@showFeatures ctx.features.preview/> + +== Deprecated features + +The following list contains deprecated features that will be removed in a future release. These features are not enabled by default. + +<@showFeatures ctx.features.deprecated/> + + + +<#macro showFeatures features> +[cols="1,3",role="features"] +|=== +<#list features as feature> + +|[.features-name]#${feature.name}# +|[.features-description]#${feature.description}# + +|=== + \ No newline at end of file diff --git a/docs/maven-plugin/pom.xml b/docs/maven-plugin/pom.xml index 88a864b7c1..c6130e9f8a 100644 --- a/docs/maven-plugin/pom.xml +++ b/docs/maven-plugin/pom.xml @@ -69,6 +69,16 @@ + + org.keycloak + keycloak-common + + + * + * + + + io.quarkus quarkus-core @@ -83,4 +93,4 @@ - \ No newline at end of file + diff --git a/docs/maven-plugin/src/main/java/org/keycloak/guides/maven/Context.java b/docs/maven-plugin/src/main/java/org/keycloak/guides/maven/Context.java index 34f1da7de4..4cfea1b75d 100644 --- a/docs/maven-plugin/src/main/java/org/keycloak/guides/maven/Context.java +++ b/docs/maven-plugin/src/main/java/org/keycloak/guides/maven/Context.java @@ -11,11 +11,13 @@ public class Context { private File srcDir; private Options options; + private Features features; private List guides; public Context(File srcDir) throws IOException { this.srcDir = srcDir; this.options = new Options(); + this.features = new Features(); this.guides = new LinkedList<>(); @@ -34,7 +36,12 @@ public class Context { return options; } + public Features getFeatures() { + return features; + } + public List getGuides() { return guides; } + } diff --git a/docs/maven-plugin/src/main/java/org/keycloak/guides/maven/Features.java b/docs/maven-plugin/src/main/java/org/keycloak/guides/maven/Features.java new file mode 100644 index 0000000000..7da37356ea --- /dev/null +++ b/docs/maven-plugin/src/main/java/org/keycloak/guides/maven/Features.java @@ -0,0 +1,60 @@ +package org.keycloak.guides.maven; + +import org.keycloak.common.Profile; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; + +public class Features { + + private List features; + + public Features() { + this.features = Arrays.stream(Profile.Feature.values()) + .filter(f -> !f.getTypeProject().equals(Profile.Type.EXPERIMENTAL)) + .map(f -> new Feature(f)) + .sorted(Comparator.comparing(Feature::getName)) + .collect(Collectors.toList()); + } + + public List getSupported() { + return features.stream().filter(f -> f.getType().equals(Profile.Type.DEFAULT)).collect(Collectors.toList()); + } + + public List getSupportedDisabledByDefault() { + return features.stream().filter(f -> f.getType().equals(Profile.Type.DISABLED_BY_DEFAULT)).collect(Collectors.toList()); + } + + public List getDeprecated() { + return features.stream().filter(f -> f.getType().equals(Profile.Type.DEPRECATED)).collect(Collectors.toList()); + } + + public List getPreview() { + return features.stream().filter(f -> f.getType().equals(Profile.Type.PREVIEW)).collect(Collectors.toList()); + } + + public class Feature { + + private Profile.Feature profileFeature; + + public Feature(Profile.Feature profileFeature) { + this.profileFeature = profileFeature; + } + + public String getName() { + return profileFeature.name().toLowerCase().replaceAll("_", "-"); + } + + public String getDescription() { + return profileFeature.getLabel(); + } + + private Profile.Type getType() { + return profileFeature.getTypeProject(); + } + + } + +}