Override Default Service account used by spring boot app deployed in Kubernetes - spring-boot

Problem statement :
I have deployed a spring boot app which when on starting always uses default compute engine service account credentials to authenticate the app , i have a created a seperate service account and key but not able to replace the default one. i tried specifying the new service account in deployement.yaml by using "serviceAccountName" field but still got the error saying service account eg :"xyz" not found.
serviceAccountName: {{ .Values.serviceAccountName }}
so how can i override default service account of compute engine with a specific service account and define it in deployment.yaml.
if i add the credentials of new service account in app code base it will work but that is not a best practice to do so , please someone help me on resolving this issue
snippet of my deployment.yaml file:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: helloworld
appVersion: {{ .Values.appVersion }}
name: helloworld
spec:
replicas: 1
selector:
matchLabels:
app: helloworld
template:
metadata:
labels:
app: helloworld
environment: {{ .Values.environment }}
spec:
containers:
- name: helloworld
image: {{ .Values.imageSha }}
imagePullPolicy: Always
securityContext:
allowPrivilegeEscalation: false
runAsUser: 1000
ports:
- containerPort: 8080
env:
- name: SPRING_CONFIG_LOCATION
value: "/app/deployments/config/"
volumeMounts:
- name: application-config
mountPath: "/app/deployments/config"
readOnly: true
volumes:
- name: application-config
configMap:
name: {{ .Values.configMapName }}
items:
- key: application.properties
path: application.properties

I think you should use Workload Identity which allows to access Google Cloud from outside.
Workload Identity is the recommended way to access Google Cloud services from applications running within GKE due to its improved security properties and manageability. For information about alternative ways to access Google Cloud APIs from GKE, refer to the alternatives section below.
Above guide is well described and I think it should resolve your issue.
For additional example, you can check one of the Community Tutorial - Using Kubernetes Workload Identity for client-server authorization.
In GKE, the Workload Identity feature allows these identities to also be associated with IAM service accounts. This allows a pod running as a Kubernetes service account to act as the associated service account for authorized access to Google APIs and to services that verify identity based on Google Cloud-specific OIDC.
Both docs have examples which should help you to adjust Workload Identity to your needs.

Related

Websocket calls are not reaching to middleware via ingressRoute in k8s

I am trying to integrate traefik ingress route with middleware (forward-auth) for wss (secure websocket protocol).
For https requests ingressRoute works fine with forward-auth,
but for wss its not reaching to forward-auth, it's bypassing the middleware.
Tried many ingressRoutes with different pathprefix so that it can route to specific middleware which will forward to helidon app for authentication.
I am trying to setup ForwardAuth for wss incoming requests in traefik Ingress, but it's forwarding/bypassing to actual server without reaching to middleware, same thing works fine for usual https calls.
My websocket url: wss://ip:443/ws/guest
How to fix wss traffic for ingressRoute?
IngressRoute.yaml
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
annotations:
kubernetes.io/ingress.class: traefik
name: traefik-tls
namespace: sample-domain1-ns
spec:
entryPoints:
- websecure
routes:
- kind: Rule
match: PathPrefix(`/ws`)
middlewares:
- name: test-auth-tls
namespace: sample-domain1-ns
services:
- kind: Service
name: sample-domain1-cluster
port: 8001
tls:
certResolver: default
forward-auth.yaml
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-auth-tls
namespace: sample-domain1-ns
spec:
headers:
customRequestHeaders:
X-Forwarded-Proto: https
forwardAuth:
address: https://sample-domain1-lb.sample-domain1-ns.svc.cluster.local:8080/auth
tls:
insecureSkipVerify: true
It seem's like, some forward-auth configuration parameter's are require for websocket.
Please try with authRequestHeaders, authResponseHeaders (https://doc.traefik.io/traefik/middlewares/http/forwardauth/).
You tagged this question with helidon, and while it's great if you're using Helidon I'm not seeing how your issue relates to Helidon specifically, rather than (as you described) ingress set-up, etc. Please correct me if I've missed a Helidon aspect here. And apart from that, I'm sorry, I don't have any suggestions for you.

NGINX Ingress Controller - 405 Not Allowed

I have developed a spring boot app (User Registration app) that has one rest API. The rest API inserts the data in a MySQL.
The application and database have been deployed in GCP Kubernetes and everything was working fine as I was using network load balancer.
Now I am trying to use NGINX Ingress Controller and Path-based Ingress routing. A network load balancer is pointing to NGINX Ingress Controller and Load Balancer IP is tagged to a wild card host name in Cloud DNS.
From PostMan application whenever I am trying to hit the "User Registration App" using the DNS url it's throwing an error:
<html>
<head>
<title>405 Not Allowed</title>
</head>
<body>
<center>
<h1>405 Not Allowed</h1>
</center>
<hr>
<center>openresty</center>
</body>
</html>
I am trying to provide all the details I have right. Can provide more details if required. I am not able to understand why NGINX server is throwing "405 Not allowed error".
User Registration Spring Boot App
Spring Boot App Controller - POST method receive the input data
NGINX Controller
Followed the steps mentioned here: https://kubernetes.github.io/ingress-nginx/deploy/#detect-installed-version
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml
Ingress Controller Service
Kubernetes Services:
Services Running in Kubernetes Cluster - Refer Yellow marked
Kubernetes Pods:
Pods running in Kubernetes Cluster - Refer Yellow marked
Ingress YML:
`
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: fanout-ingress
namespace: xyz-product
labels: # Labels that will be applied to this resource
app: prod-user-reg-app
annotations:
kubernetes.io/ingress.class: "nginx"
ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-methods: "PUT, GET, POST, OPTIONS"
spec:
rules:
- host: test.apps.myproduct.com
http:
paths:
- path: /user-reg/create/*
backend:
serviceName: prod-user-reg-create-app
servicePort: 8081`
Kubctl Describe Ingress
GCP Cloud DNS
How do solve the issue? And where is the problem? In NGINX Controller service?
Please help.
The resolution is here. Changed the URL path and used a registered domain to access via the internet.
https://github.com/kubernetes/ingress-nginx/issues/4772 and
https://github.com/kubernetes/ingress-nginx/issues/4776

App deployed on PCF trying to find config at localhost:8888 even when the cloud foundry provided config server is binded with app

How do we make use of Spring Cloud Services like Config Services/ Hystrix at PCF? I have one app deployed on PCF and i am trying to bind a Config server service from CF marketplace to it. But when i start the app it tries to connect localhost:8888. Any Idea what can be done?
manifest.yml
---
applications:
- name: demo
memory: 4096M
host: demo
domain: apps.pcf.devfg.***.com
services:
- ps-config-server-pcf
Ensure that you have these two Libraries in your build.gradle and the bind your App to the Marketplace service
io.pivotal.spring.cloud:spring-cloud-services-starter-config-client
org.springframework.cloud:spring-cloud-config-server
Also, remove all your local configurations from your bootstrap.yml (however PCF will over ride your values, this is a good practice to do)

Traefik doesn't pick TLS certificates secrets from the ingress definition in Kubernetes

When I only add the TLS secret to the Ingress, Traefik serves it's default certificate.
kind: Ingress
spec:
rules:
....
tls:
- secretName: ingress-mgt-server-keys
Only when I mount the secret and add below parameter, does Traefik start serving the real certificate.
entryPoints.https.tls.certificates
Are TLS secrets to be define in both Ingress and Ingress-controller? This forces me to repeat the keys as secrets to all the ingress namespaces as well as the ingress-controller namespace.
[Update]: Traefik has RBAC to read secrets from the target namespace.
Hmm, that does not seem to be the case.
https://docs.traefik.io/user-guide/kubernetes/#add-a-tls-certificate-to-the-ingress
In addition to the modified ingress you need to provide the TLS certificate via a Kubernetes secret in the same namespace as the ingress.
The TLS Secret isn't needed to be set up in the target (ingress) namespaces.
Only the ingress controller namespace needs the TLS Secret.

Kubernetes expose ingress resource (API object) with load balancer?

I have a kubernetes cluster on amazon ews on which I intend to run multiple applications.
I have multiple services which make up one such application and I want to expose them to the internet using an amazon load balancer (elb). I want to use the ELB because I don't want to use port 80 directly as many applications share this port and I want each one of them to define their ingress resource independent of others.
I read about kubernetes ingress resources and thought that is exactly what I'm looking for. However I didn't manage to expose it through a service with load balancer. Now when I read the documentation Services are meant to expose pods but an ingress is:
An API object that manages external access to the services in a cluster, typically HTTP.
Is what I'm trying to do possible or did I not grasp some concept and trying to do something impossible or wrong?
My code:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
labels:
id: ingress
spec:
rules:
- http:
paths:
- path: /api/devices
backend:
serviceName: device-management
servicePort: 3001
- path: /api/datasources
backend:
serviceName: data-acquisition
servicePort: 3001
- path: /auth,/account,/api/tenants,/api/users
backend:
serviceName: device-management
servicePort: 3001
## TODO: Find out how to add subdomain entry for auth.domain and s3.domain
---
apiVersion: v1
kind: Service
metadata:
name: ingress
labels:
id: ingress
spec:
type: LoadBalancer
ports:
- name: http
port: 80
targetPort: 80
- name: https
port: 443
targetPort: 443
selector:
id: ingress
Output from kubectl describe service ingress contains
Endpoints: none
The problem is that I didn't install an ingress controller. The documentation states:
You need an Ingress controller to satisfy an Ingress, simply creating the resource will have no effect.
The ingress controller creates an nginx pod and a service (load balancer) which will then implement the rules described in all ingress resources. The installation guide gives further information on how to install it on different platforms.
The ingress controller replaces the service which I desribed above and implements all ingress resources desribed in the cluster.

Resources