+
Skip to content

set auto-mount service account token to false in keycloak pods #40605

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

Open
wants to merge 4 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
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,7 @@ spec:
limits:
cpu: "6"
memory: "2250M"
automountServiceAccountToken: true
db:
vendor: postgres
url: jdbc:aws-wrapper:postgresql://<AWS_AURORA_URL_HERE>:5432/keycloak
Expand Down
1 change: 1 addition & 0 deletions docs/guides/operator/advanced-configuration.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@ stringData:

When running on a Kubernetes or OpenShift environment well-known locations of trusted certificates are included automatically.
This includes `/var/run/secrets/kubernetes.io/serviceaccount/ca.crt` and the `/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt` when present.
In order to not include `/var/run/secrets/kubernetes.io/serviceaccount/ca.crt` in Keycloak pods, set the `automountServiceAccountToken` field in the spec to `false`

=== Admin Bootstrapping

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,12 @@ private StatefulSet createBaseDeployment(Keycloak keycloakCR, Context<Keycloak>
if (!specBuilder.hasDnsPolicy()) {
specBuilder.withDnsPolicy("ClusterFirst");
}
if (Boolean.TRUE.equals(keycloakCR.getSpec().getAutomountServiceAccountToken()) || keycloakCR.getSpec().getAutomountServiceAccountToken() == null) {
specBuilder.withAutomountServiceAccountToken(true);

} else if (Boolean.FALSE.equals(keycloakCR.getSpec().getAutomountServiceAccountToken())) {
specBuilder.withAutomountServiceAccountToken(false);
}
Comment on lines +304 to +309
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (Boolean.TRUE.equals(keycloakCR.getSpec().getAutomountServiceAccountToken()) || keycloakCR.getSpec().getAutomountServiceAccountToken() == null) {
specBuilder.withAutomountServiceAccountToken(true);
} else if (Boolean.FALSE.equals(keycloakCR.getSpec().getAutomountServiceAccountToken())) {
specBuilder.withAutomountServiceAccountToken(false);
}
boolean automount = !Boolean.FALSE.equals(keycloakCR.getSpec().getAutomountServiceAccountToken());
specBuilder.withAutomountServiceAccountToken(automount);

The assumption moving forward is that there will be no null case - we'll set the spec automountServiceAccountToken to true or false.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Allowing null to be the default handling would probably be best.

handleScheduling(keycloakCR, schedulingLabels, specBuilder);

// there isn't currently an editOrNewFirstContainer, so we need to do this manually
Expand Down Expand Up @@ -439,14 +445,18 @@ private void addEnvVars(StatefulSet baseDeployment, Keycloak keycloakCR, TreeSet
LinkedHashMap<String, EnvVar> varMap = Stream.concat(Stream.concat(env.stream(), firstClasssEnvVars.stream()), additionalEnvVars.stream())
.collect(Collectors.toMap(EnvVar::getName, Function.identity(), (e1, e2) -> e1, LinkedHashMap::new));

String truststores = SERVICE_ACCOUNT_DIR + "ca.crt";
String truststores = SERVICE_ACCOUNT_DIR;
if (baseDeployment.getSpec().getTemplate().getSpec().getAutomountServiceAccountToken()) {
truststores += "ca.crt";
}

if (useServiceCaCrt) {
truststores += "," + SERVICE_CA_CRT;
}

// include the kube CA if the user is not controlling KC_TRUSTSTORE_PATHS via the unsupported or the additional
varMap.putIfAbsent(KC_TRUSTSTORE_PATHS, new EnvVarBuilder().withName(KC_TRUSTSTORE_PATHS).withValue(truststores).build());
if (Boolean.TRUE.equals(baseDeployment.getSpec().getTemplate().getSpec().getAutomountServiceAccountToken()) || useServiceCaCrt) {
// include the kube CA if the user is not controlling KC_TRUSTSTORE_PATHS via the unsupported or the additional
varMap.putIfAbsent(KC_TRUSTSTORE_PATHS, new EnvVarBuilder().withName(KC_TRUSTSTORE_PATHS).withValue(truststores).build());
}
Comment on lines +456 to +459
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (Boolean.TRUE.equals(baseDeployment.getSpec().getTemplate().getSpec().getAutomountServiceAccountToken()) || useServiceCaCrt) {
// include the kube CA if the user is not controlling KC_TRUSTSTORE_PATHS via the unsupported or the additional
varMap.putIfAbsent(KC_TRUSTSTORE_PATHS, new EnvVarBuilder().withName(KC_TRUSTSTORE_PATHS).withValue(truststores).build());
}
if (!Boolean.FALSE.equals(keycloakCR.getSpec().getAutomountServiceAccountToken())) {
String truststores = SERVICE_ACCOUNT_DIR + "ca.crt";
if (useServiceCaCrt) {
truststores += "," + SERVICE_CA_CRT;
}
// include the kube CA if the user is not controlling KC_TRUSTSTORE_PATHS via the unsupported or the additional
varMap.putIfAbsent(KC_TRUSTSTORE_PATHS, new EnvVarBuilder().withName(KC_TRUSTSTORE_PATHS).withValue(truststores).build());
}

Switching to using the entire service account directory if automount is disabled doesn't seem like the right thing to do. How about updating the truststores only if automount is enabled.


setTracingEnvVars(keycloakCR, varMap);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,10 @@ public class KeycloakSpec {
@JsonPropertyDescription("Configuration for startup probe, by default it is 1 for periodSeconds and 600 for failureThreshold")
private ProbeSpec startupProbeSpec;

@JsonProperty("automountServiceAccountToken")
@JsonPropertyDescription("Set this to automount the default ServiceAccount Token and Service CA")
private Boolean automountServiceAccountToken;


public HttpSpec getHttpSpec() {
return httpSpec;
Expand Down Expand Up @@ -349,4 +353,9 @@ public void setReadinessProbeSpec(ProbeSpec readinessProbeSpec) {
public void setStartupProbeSpec(ProbeSpec startupProbeSpec) {
this.startupProbeSpec = startupProbeSpec;
}

public Boolean getAutomountServiceAccountToken() {
return automountServiceAccountToken;
}
public void setAutomountServiceAccountToken(Boolean automountServiceAccountToken) {this.automountServiceAccountToken = automountServiceAccountToken;}
}
Original file line number Diff line number Diff line change
Expand Up @@ -720,7 +720,16 @@ public void testApplyingResourcesDefaultValues() {
assertThat(limits).isNotNull();
assertThat(limits.get("memory")).isEqualTo(config.keycloak().resources().limits().memory());
}

@Test
public void testNoAutoMountServiceAccount() {
var kc = getTestKeycloakDeployment(true);
kc.getSpec().setAutomountServiceAccountToken(Boolean.FALSE);
deployKeycloak(k8sclient, kc, true);
var pods = k8sclient.pods().inNamespace(namespace).withLabels(Constants.DEFAULT_LABELS).list().getItems();
assertThat(pods).isNotNull();
assertThat(pods).isNotEmpty();
assertThat(pods.get(0).getSpec().getAutomountServiceAccountToken()).isEqualTo(Boolean.FALSE);
}
private void handleFakeImagePullSecretCreation(Keycloak keycloakCR,
String secretDescriptorFilename) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -313,5 +313,11 @@ private static void assertNetworkPolicyRules(Collection<NetworkPolicyPeer> rules
fail();
}
}

@Test
public void testNoAutoMountServiceAccountToken() {
var keycloak = Serialization.unmarshal(this.getClass().getResourceAsStream("/test-serialization-keycloak-cr-without-automount.yml"), Keycloak.class);
var keycloakSpec = keycloak.getSpec();
assertNotNull(keycloakSpec);
assertFalse(keycloakSpec.getAutomountServiceAccountToken());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
apiVersion: k8s.keycloak.org/v2alpha1
kind: Keycloak
metadata:
name: test-serialization-kc
spec:
instances: 3
image: my-image
automountServiceAccountToken: false
additionalOptions:
- name: key1
value: value1
- name: features
value: docker
db:
vendor: vendor
usernameSecret:
name: usernameSecret
key: usernameSecretKey
passwordSecret:
name: passwordSecret
key: passwordSecretKey
host: host
database: database
url: url
port: 123
schema: schema
poolInitialSize: 1
poolMinSize: 2
poolMaxSize: 3
ingress:
enabled: false
className: nginx
annotations:
myAnnotation: myValue
anotherAnnotation: anotherValue
readinessProbe:
periodSeconds: 50
failureThreshold: 3
livenessProbe:
periodSeconds: 60
failureThreshold: 1
startupProbe:
periodSeconds: 40
failureThreshold: 2
networkPolicy:
enabled: true
http:
- ipBlock:
cidr: 172.17.0.0/16
except:
- 172.17.1.0/24
- namespaceSelector:
matchLabels:
project: myproject
- podSelector:
matchLabels:
role: frontend
https:
- ipBlock:
cidr: 172.17.0.0/16
except:
- 172.17.1.0/24
- namespaceSelector:
matchLabels:
project: myproject
- podSelector:
matchLabels:
role: frontend
management:
- ipBlock:
cidr: 172.17.0.0/16
except:
- 172.17.1.0/24
- namespaceSelector:
matchLabels:
project: myproject
- podSelector:
matchLabels:
role: frontend
http:
httpEnabled: true
httpPort: 123
httpsPort: 456
tlsSecret: my-tls-secret
hostname:
hostname: my-hostname
admin: my-admin-hostname
adminUrl: https://www.my-admin-hostname.org:8448/something
strict: true
strictBackchannel: true
backchannelDynamic: true
cache:
configMapFile:
name: my-config-map
key: file.xml
features:
enabled:
- docker
- authorization
disabled:
- admin
- step-up-authentication
transaction:
xaEnabled: false
tracing:
enabled: true
endpoint: http://my-tracing:4317
serviceName: my-best-keycloak
protocol: http/protobuf
samplerType: parentbased_traceidratio
samplerRatio: 0.01
compression: gzip
resourceAttributes:
service.namespace: keycloak-namespace
service.name: custom-service-name
resources:
requests:
cpu: "500m"
memory: "500M"
limits:
cpu: "2"
memory: "1500M"
proxy:
headers: forwarded
truststores:
x:
secret:
name: my-secret
httpManagement:
port: 9003
bootstrapAdmin:
user:
secret: something
service:
secret: else
update:
strategy: Auto
revision: 1
unsupported:
podTemplate:
metadata:
labels:
my-label: "foo"
Loading
点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载