How to configure kubernetes to allow usage of ConfingMaps with SpringBoot

4/24/2020

I used the following config:

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: api-role
  namespace: default
  labels:
    app: tools-rbac
rules:
  - apiGroups: [""]
    resources: ["configmaps"]
    verbs: ["get"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: global-rolebinding
  namespace: default
  labels:
    type: spring-app
subjects:
  - kind: Group
    name: system:serviceaccounts
    apiGroup: rbac.authorization.k8s.io
    namespace: default
roleRef:
  kind: Role
  name: api-role
  apiGroup: ""

And got this exception:

2020-04-24 23:51:49.359  WARN 1 --- [           main] o.s.c.k.config.ConfigMapPropertySource   : Can't read configMap with name: [ribbon-config] in namespace:[default]. Ignoring.

io.fabric8.kubernetes.client.KubernetesClientException: Operation: [get]  for kind: [ConfigMap]  with name: [ribbon-config]  in namespace: [default]  failed.
    at io.fabric8.kubernetes.client.KubernetesClientException.launderThrowable(KubernetesClientException.java:64) ~[kubernetes-client-4.4.1.jar!/:na]
    at io.fabric8.kubernetes.client.KubernetesClientException.launderThrowable(KubernetesClientException.java:72) ~[kubernetes-client-4.4.1.jar!/:na]
    at io.fabric8.kubernetes.client.dsl.base.BaseOperation.getMandatory(BaseOperation.java:229) ~[kubernetes-client-4.4.1.jar!/:na]
    at io.fabric8.kubernetes.client.dsl.base.BaseOperation.get(BaseOperation.java:162) ~[kubernetes-client-4.4.1.jar!/:na]
    at org.springframework.cloud.kubernetes.config.ConfigMapPropertySource.getData(ConfigMapPropertySource.java:95) [spring-cloud-kubernetes-config-1.1.2.RELEASE.jar!/:1.1.2.RELEASE]
    at org.springframework.cloud.kubernetes.config.ConfigMapPropertySource.<init>(ConfigMapPropertySource.java:76) [spring-cloud-kubernetes-config-1.1.2.RELEASE.jar!/:1.1.2.RELEASE]
    at org.springframework.cloud.kubernetes.config.ConfigMapPropertySourceLocator.getMapPropertySourceForSingleConfigMap(ConfigMapPropertySourceLocator.java:95) [spring-cloud-kubernetes-config-1.1.2.RELEASE.jar!/:1.1.2.RELEASE]
    at org.springframework.cloud.kubernetes.config.ConfigMapPropertySourceLocator.lambda$locate$0(ConfigMapPropertySourceLocator.java:78) [spring-cloud-kubernetes-config-1.1.2.RELEASE.jar!/:1.1.2.RELEASE]
    at java.util.ArrayList.forEach(ArrayList.java:1257) ~[na:1.8.0_252]
    at org.springframework.cloud.kubernetes.config.ConfigMapPropertySourceLocator.locate(ConfigMapPropertySourceLocator.java:77) [spring-cloud-kubernetes-config-1.1.2.RELEASE.jar!/:1.1.2.RELEASE]
    at org.springframework.cloud.bootstrap.config.PropertySourceLocator.locateCollection(PropertySourceLocator.java:52) ~[spring-cloud-context-2.2.2.RELEASE.jar!/:2.2.2.RELEASE]
    at org.springframework.cloud.bootstrap.config.PropertySourceLocator.locateCollection(PropertySourceLocator.java:47) ~[spring-cloud-context-2.2.2.RELEASE.jar!/:2.2.2.RELEASE]
    at org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfiguration.initialize(PropertySourceBootstrapConfiguration.java:97) ~[spring-cloud-context-2.2.2.RELEASE.jar!/:2.2.2.RELEASE]
    at org.springframework.boot.SpringApplication.applyInitializers(SpringApplication.java:626) ~[spring-boot-2.2.6.RELEASE.jar!/:2.2.6.RELEASE]
    at org.springframework.boot.SpringApplication.prepareContext(SpringApplication.java:370) ~[spring-boot-2.2.6.RELEASE.jar!/:2.2.6.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:314) ~[spring-boot-2.2.6.RELEASE.jar!/:2.2.6.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) ~[spring-boot-2.2.6.RELEASE.jar!/:2.2.6.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) ~[spring-boot-2.2.6.RELEASE.jar!/:2.2.6.RELEASE]
    at com.github.saphyra.apphub.service.platform.main_gateway.MainGatewayApplication.main(MainGatewayApplication.java:9) ~[classes!/:0.0.1-SNAPSHOT]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_252]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_252]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_252]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_252]
    at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48) ~[application.jar:0.0.1-SNAPSHOT]
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:87) ~[application.jar:0.0.1-SNAPSHOT]
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:51) ~[application.jar:0.0.1-SNAPSHOT]
    at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:52) ~[application.jar:0.0.1-SNAPSHOT]
Caused by: java.net.SocketException: Broken pipe (Write failed)
    at java.net.SocketOutputStream.socketWrite0(Native Method) ~[na:1.8.0_252]
    at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:111) ~[na:1.8.0_252]
    at java.net.SocketOutputStream.write(SocketOutputStream.java:155) ~[na:1.8.0_252]
    at sun.security.ssl.OutputRecord.writeBuffer(OutputRecord.java:431) ~[na:1.8.0_252]
    at sun.security.ssl.OutputRecord.write(OutputRecord.java:417) ~[na:1.8.0_252]
    at sun.security.ssl.SSLSocketImpl.writeRecordInternal(SSLSocketImpl.java:894) ~[na:1.8.0_252]
    at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:865) ~[na:1.8.0_252]
    at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:123) ~[na:1.8.0_252]
    at okio.Okio$1.write(Okio.java:79) ~[okio-1.17.2.jar!/:na]
    at okio.AsyncTimeout$1.write(AsyncTimeout.java:180) ~[okio-1.17.2.jar!/:na]
    at okio.RealBufferedSink.flush(RealBufferedSink.java:224) ~[okio-1.17.2.jar!/:na]
    at okhttp3.internal.http2.Http2Writer.settings(Http2Writer.java:185) ~[okhttp-3.14.7.jar!/:na]
    at okhttp3.internal.http2.Http2Connection.start(Http2Connection.java:531) ~[okhttp-3.14.7.jar!/:na]
    at okhttp3.internal.http2.Http2Connection.start(Http2Connection.java:521) ~[okhttp-3.14.7.jar!/:na]
    at okhttp3.internal.connection.RealConnection.startHttp2(RealConnection.java:315) ~[okhttp-3.14.7.jar!/:na]
    at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.java:304) ~[okhttp-3.14.7.jar!/:na]
    at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:185) ~[okhttp-3.14.7.jar!/:na]
    at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.java:224) ~[okhttp-3.14.7.jar!/:na]
    at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.java:108) ~[okhttp-3.14.7.jar!/:na]
    at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.java:88) ~[okhttp-3.14.7.jar!/:na]
    at okhttp3.internal.connection.Transmitter.newExchange(Transmitter.java:169) ~[okhttp-3.14.7.jar!/:na]
    at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:41) ~[okhttp-3.14.7.jar!/:na]
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142) ~[okhttp-3.14.7.jar!/:na]
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117) ~[okhttp-3.14.7.jar!/:na]
    at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:94) ~[okhttp-3.14.7.jar!/:na]
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142) ~[okhttp-3.14.7.jar!/:na]
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117) ~[okhttp-3.14.7.jar!/:na]
    at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93) ~[okhttp-3.14.7.jar!/:na]
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142) ~[okhttp-3.14.7.jar!/:na]
    at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:88) ~[okhttp-3.14.7.jar!/:na]
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142) ~[okhttp-3.14.7.jar!/:na]
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117) ~[okhttp-3.14.7.jar!/:na]
    at io.fabric8.kubernetes.client.utils.BackwardsCompatibilityInterceptor.intercept(BackwardsCompatibilityInterceptor.java:119) ~[kubernetes-client-4.4.1.jar!/:na]
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142) ~[okhttp-3.14.7.jar!/:na]
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117) ~[okhttp-3.14.7.jar!/:na]
    at io.fabric8.kubernetes.client.utils.ImpersonatorInterceptor.intercept(ImpersonatorInterceptor.java:68) ~[kubernetes-client-4.4.1.jar!/:na]
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142) ~[okhttp-3.14.7.jar!/:na]
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117) ~[okhttp-3.14.7.jar!/:na]
    at io.fabric8.kubernetes.client.utils.HttpClientUtils.lambda$createHttpClient$3(HttpClientUtils.java:110) ~[kubernetes-client-4.4.1.jar!/:na]
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142) ~[okhttp-3.14.7.jar!/:na]
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117) ~[okhttp-3.14.7.jar!/:na]
    at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:229) ~[okhttp-3.14.7.jar!/:na]
    at okhttp3.RealCall.execute(RealCall.java:81) ~[okhttp-3.14.7.jar!/:na]
    at io.fabric8.kubernetes.client.dsl.base.OperationSupport.handleResponse(OperationSupport.java:404) ~[kubernetes-client-4.4.1.jar!/:na]
    at io.fabric8.kubernetes.client.dsl.base.OperationSupport.handleResponse(OperationSupport.java:365) ~[kubernetes-client-4.4.1.jar!/:na]
    at io.fabric8.kubernetes.client.dsl.base.OperationSupport.handleGet(OperationSupport.java:330) ~[kubernetes-client-4.4.1.jar!/:na]
    at io.fabric8.kubernetes.client.dsl.base.OperationSupport.handleGet(OperationSupport.java:311) ~[kubernetes-client-4.4.1.jar!/:na]
    at io.fabric8.kubernetes.client.dsl.base.BaseOperation.handleGet(BaseOperation.java:810) ~[kubernetes-client-4.4.1.jar!/:na]
    at io.fabric8.kubernetes.client.dsl.base.BaseOperation.getMandatory(BaseOperation.java:218) ~[kubernetes-client-4.4.1.jar!/:na]
    ... 24 common frames omitted

I also tried many other configurations, but could not find out what is wrong.

I'm using Minikube on Windows.

I'd appreciate a solution what works for random namespaces (My plan is to set up a namespace with a random name for testing purposes during the deployment)

EDIT: I changed to using ClusterRoles for cross-namespace solution:

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: global-config-role
rules:
  - apiGroups: [""]
    resources: ["configmaps"]
    verbs: ["get"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: global-config-binding
subjects:
  - kind: Group
    name: system:serviceaccounts
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: global-config-role
  apiGroup: rbac.authorization.k8s.io

Command kubectl auth can-i get configmap --as=system:serviceaccount:default:default Returned true for both default and test-0 namespace.

-- Saphyra
kubernetes
rbac
spring-boot

1 Answer

4/25/2020

Check the permission of the service account(default) used by spring boot app

kubectl auth can-i get configmap --as=system:serviceaccount:default:default -n default

If the above command returns true then permission is setup properly.Maybe then the spring boot app is not using the service account default

Edit:

As per the doc the role and rolebinding should be as below.

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: YOUR-NAME-SPACE
  name: namespace-reader
rules:
  - apiGroups: ["", "extensions", "apps"]
    resources: ["configmaps", "pods", "services", "endpoints", "secrets"]
    verbs: ["get", "list", "watch"]

---

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: namespace-reader-binding
  namespace: YOUR-NAME-SPACE
subjects:
- kind: ServiceAccount
  name: default
  apiGroup: ""
roleRef:
  kind: Role
  name: namespace-reader
  apiGroup: ""
-- Arghya Sadhu
Source: StackOverflow