diff --git a/docs/documentation/release_notes/topics/26_2_0.adoc b/docs/documentation/release_notes/topics/26_2_0.adoc index e3630348940..8bb1355486c 100644 --- a/docs/documentation/release_notes/topics/26_2_0.adoc +++ b/docs/documentation/release_notes/topics/26_2_0.adoc @@ -67,8 +67,19 @@ link:{grafanadashboards_link}[The guide] contains two dashboards. * Keycloak troubleshooting dashboard - showing metrics related to service level indicators and troubleshooting. * Keycloak capacity planning dashboard - showing metrics related to estimating the load handled by Keycloak. += Operator creates NetworkPolicies to restrict traffic + +The {project_name} Operator now creates by default a NetworkPolicy to restrict traffic to internal ports used for {project_name}'s distributed caches. + +This strengthens a secure-by-default setup and minimizes the configuration steps of new setups. + +You can restrict the access to the management and HTTP endpoints further using the Kubernetes NetworkPolicies rule syntax. + +Read more about this in the https://www.keycloak.org/operator/advanced-configuration[Operator Advanced configuration]. + = Removal of the `X-XSS-Protection` header Because the https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection[`X-XSS-Protection` header] is no longer supported by any user agents that are supported by Keycloak, it has been removed. This header was a feature of Internet Explorer, Chrome, and Safari that stopped pages from loading when they detected reflected cross-site scripting (XSS) attacks. We don't expect that this will impact any deployments due to the lack of support in user agents, as well as this feature being supplanted by https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP[Content Security Policy (CSP)]. + diff --git a/docs/documentation/upgrading/topics/changes/changes-26_2_0.adoc b/docs/documentation/upgrading/topics/changes/changes-26_2_0.adoc index 1495fc4cfe7..91bc38d3567 100644 --- a/docs/documentation/upgrading/topics/changes/changes-26_2_0.adoc +++ b/docs/documentation/upgrading/topics/changes/changes-26_2_0.adoc @@ -31,3 +31,15 @@ If you provided your own keystore and truststore to secure the TCP transport sta If you are using a custom transport stack, this default behavior can be disabled by setting the option `cache-embedded-mtls-enabled` to `false`. For more information, check the link:https://www.keycloak.org/server/caching#_securing_transport_stacks[Securing Transport Stacks] in the distributed caches guide. + += Operator creates NetworkPolicies to restrict traffic + +The {project_name} Operator now creates by default a NetworkPolicy to restrict traffic to internal ports used for {project_name}'s distributed caches. + +This strengthens a secure-by-default setup and minimizes the configuration steps of new setups. +We expect this to be backwards compatible to existing deployment, so no additional steps are necessary at the time of the upgrade. +You can return to the previous behavior by disabling the creation of NetworkPolicies in the Keycloak CR. + +If your deployment scripts add explicit NetworkPolicies for {project_name}, you should consider removing those and migrate to the new functionality provided in the Keycloak CR as a follow-up to the upgrade. + +Read more about this in the https://www.keycloak.org/operator/advanced-configuration[Operator Advanced configuration]. diff --git a/docs/guides/operator/advanced-configuration.adoc b/docs/guides/operator/advanced-configuration.adoc index 3236c689c40..88688e0834d 100644 --- a/docs/guides/operator/advanced-configuration.adoc +++ b/docs/guides/operator/advanced-configuration.adoc @@ -382,14 +382,15 @@ NOTE: The `tracing-jdbc-enabled` is not promoted as a first-class citizen as it For more details about tracing, see <@links.observability id="tracing" />. -=== Network Policies (Preview) +=== Network Policies NetworkPolicies allow you to specify rules for traffic flow within your cluster, and also between Pods and the outside world. -Your cluster must use a network plugin that supports NetworkPolicy enforcement. +Your cluster must use a network plugin that supports NetworkPolicy enforcement to restrict the network traffic. -The operator can automatically create a NetworkPolicy to deny access to the clustering port of your {project_name} Pods. +The operator automatically creates a NetworkPolicy to deny access to the clustering port of your {project_name} Pods. The HTTP(S) endpoint is open to traffic from any namespace and the outside world. -To enable the NetworkPolicy, set `spec.networkPolicy.enabled` in your Keycloak CR, as shown in the example below. + +To disable the NetworkPolicy, set `spec.networkPolicy.enabled` in your Keycloak CR, as shown in the example below. .Keycloak CR with Network Policies enabled [source,yaml] @@ -400,12 +401,12 @@ metadata: name: example-kc spec: networkPolicy: - enabled: true + enabled: false ---- -The above example allows traffic from all sources. +By default, traffic to the HTTP endpoints and the management endpoint is allowed from all sources. The Keycloak CR can be extended to include a list of rules for each of the endpoints exposed by {project_name}. -These rules specify from where (the source) the traffic is allowed and it's possible to communicate with the {project_name} Pods. +These rules specify from where (the source) the traffic is allowed, and it is possible to communicate with the {project_name} Pods. .Extended Network Policy configuration [source,yaml] diff --git a/operator/src/main/java/org/keycloak/operator/crds/v2alpha1/deployment/spec/NetworkPolicySpec.java b/operator/src/main/java/org/keycloak/operator/crds/v2alpha1/deployment/spec/NetworkPolicySpec.java index fac1a515158..48cbb6fbea9 100644 --- a/operator/src/main/java/org/keycloak/operator/crds/v2alpha1/deployment/spec/NetworkPolicySpec.java +++ b/operator/src/main/java/org/keycloak/operator/crds/v2alpha1/deployment/spec/NetworkPolicySpec.java @@ -23,6 +23,7 @@ import java.util.Optional; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyDescription; +import io.fabric8.generator.annotation.Default; import io.fabric8.kubernetes.api.model.networking.v1.NetworkPolicyPeer; import io.sundr.builder.annotations.Buildable; import org.keycloak.operator.Constants; @@ -41,8 +42,9 @@ public class NetworkPolicySpec { "If this field is present and contains at least one item, this rule allows traffic only if the traffic matches at least one item in the from list."; @JsonProperty("enabled") - @JsonPropertyDescription("Enables or disable the ingress traffic control.") - private boolean networkPolicyEnabled = false; + @JsonPropertyDescription("Enables or disables the ingress traffic control.") + @Default("true") + private boolean networkPolicyEnabled = true; @JsonProperty("http") @JsonPropertyDescription(RULE_DESCRIPTION) @@ -96,7 +98,7 @@ public class NetworkPolicySpec { public static boolean isNetworkPolicyEnabled(Keycloak keycloak) { return networkPolicySpecOf(keycloak) .map(NetworkPolicySpec::isNetworkPolicyEnabled) - .orElse(false); + .orElse(true); } public static String networkPolicyName(Keycloak keycloak) { diff --git a/operator/src/test/java/org/keycloak/operator/testsuite/unit/NetworkPolicyLogicTest.java b/operator/src/test/java/org/keycloak/operator/testsuite/unit/NetworkPolicyLogicTest.java index 11412c9eb2e..dba235cf8fd 100644 --- a/operator/src/test/java/org/keycloak/operator/testsuite/unit/NetworkPolicyLogicTest.java +++ b/operator/src/test/java/org/keycloak/operator/testsuite/unit/NetworkPolicyLogicTest.java @@ -59,6 +59,18 @@ public class NetworkPolicyLogicTest { @Test public void testDefaults() { var keycloak = K8sUtils.getDefaultKeycloakDeployment(); + var controller = new MockKeycloakNetworkPolicy(keycloak); + assertTrue(controller.isEnabled()); + assertTrue(controller.reconciled()); + assertFalse(controller.deleted()); + assertEnabledAndGet(keycloak); + } + + @Test + public void testNetworkPolicyDisabled() { + var keycloak = K8sUtils.getDefaultKeycloakDeployment(); + K8sUtils.disableNetworkPolicy(keycloak); + var controller = new MockKeycloakNetworkPolicy(keycloak); assertFalse(controller.isEnabled()); assertFalse(controller.reconciled()); @@ -165,6 +177,17 @@ public class NetworkPolicyLogicTest { return networkPolicy.get(); } + private static void assertDisabled(Keycloak keycloak) { + var controller = new MockKeycloakNetworkPolicy(keycloak); + + assertTrue(controller.isEnabled()); + assertTrue(controller.reconciled()); + assertFalse(controller.deleted()); + + var networkPolicy = controller.getReconciledResource(); + assertTrue(networkPolicy.isEmpty()); + } + private static void disableManagement(Keycloak keycloak, boolean legacyOption) { if (legacyOption) { keycloak.getSpec().getAdditionalOptions().add(new ValueOrSecret("legacy-observability-interface", "true")); diff --git a/operator/src/test/java/org/keycloak/operator/testsuite/utils/K8sUtils.java b/operator/src/test/java/org/keycloak/operator/testsuite/utils/K8sUtils.java index 62d02b8b024..a32e77a764a 100644 --- a/operator/src/test/java/org/keycloak/operator/testsuite/utils/K8sUtils.java +++ b/operator/src/test/java/org/keycloak/operator/testsuite/utils/K8sUtils.java @@ -177,7 +177,12 @@ public final class K8sUtils { public static void enableNetworkPolicy(Keycloak keycloak) { var builder = new NetworkPolicySpecBuilder(); - builder.withNetworkPolicyEnabled(true); + keycloak.getSpec().setNetworkPolicySpec(builder.build()); + } + + public static void disableNetworkPolicy(Keycloak keycloak) { + var builder = new NetworkPolicySpecBuilder(); + builder.withNetworkPolicyEnabled(false); keycloak.getSpec().setNetworkPolicySpec(builder.build()); }