Make NetworkPolicy supported and enabled by default

Closes #36036

Signed-off-by: Alexander Schwartz <aschwart@redhat.com>
Signed-off-by: Alexander Schwartz <alexander.schwartz@gmx.net>
Co-authored-by: Pedro Ruivo <pruivo@users.noreply.github.com>
This commit is contained in:
Alexander Schwartz 2025-03-10 11:12:38 +01:00 committed by GitHub
parent 20a939b79e
commit 151e019935
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 65 additions and 11 deletions

View file

@ -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)].

View file

@ -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].

View file

@ -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]

View file

@ -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) {

View file

@ -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"));

View file

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