How to setup basic auth in ingress for included url rules? - kubernetes

I have a project on k8s with 3 services, that I want to cover with basic auth, and 1 service that I'd like to be public.
In ingress 4 services devided by url rules, that have different prefixes.
I had found tutorial about basic auth setup in ingress for all rules, but not about excluded, included urls.

Unfortunately GCP Ingress does not provide basic auth authentication as this feature is specific for Nginx Ingress.
As workaround for basic auth in GCP Ingress you can use IAP. Detailed How To information can be found in Enabling IAP for GKE article.
If you would still like to use Nginx Ingress basic auth you can do it on GKE but you need specify nginx annotation.
metadata:
name: foo
annotations:
kubernetes.io/ingress.class: "nginx"
Regarding using basic auth on only one service out of four, you can createa 2 Ingress. Very similar issue was discussed in another stackoverflow thread, which contains good solution - Nginx-ingress Kubernetes routing with basic auth.
Basic Auth Ingress
First Ingress should be without annotations:
nginx.ingress.kubernetes.io/auth-type
nginx.ingress.kubernetes.io/auth-secret
nginx.ingress.kubernetes.io/auth-realm
Second Ingress should contain proper annotations and should look similar to below YAML.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: auth-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/auth-secret: basic-auth
nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required'
#cert-manager.io/cluster-issuer: if you would use cert manager like letsencrypt
spec:
tls:
- hosts:
- example.com
secretName: example-tls
rules:
- host: example.com
http:
paths:
- path: /auth
backend:
serviceName: auth-service
servicePort: <auth-service-port>
Aditional information
There is an option to deny all traffic to specific path. It can be achieved by configuration-snippet annotation.
annotations:
nginx.ingress.kubernetes.io/configuration-snippet: |
location /specificpath {
deny all;
}

Related

How to setup a domain in GKE ingress nginx

I have a cluster in GKE and it is working, everything seems to be working. If I forward the ports I am able to see that the containers are working.
I am not able to setup a domain I own from namecheap.
These are the steps I followed
In Namecheap I setup a custom dns for the domain
ns-cloud-c1.googledomains.com.
ns-cloud-c2.googledomains.com.
ns-cloud-c3.googledomains.com.
ns-cloud-c3.googledomains.com.
I used the letter c because the cluster is in a c zone (I am not sure if this is right)
Because I am trying to setup as secure website I installed nginx ingress controller
kubectl create clusterrolebinding cluster-admin-binding \
--clusterrole cluster-admin \
--user $(gcloud config get-value account)
and
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.46.0/deploy/static/provider/cloud/deploy.yaml
I applied the issuer.yml
apiVersion: cert-manager.io/v1alpha2
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
namespace: cert-manager
spec:
acme:
# The ACME server URL
server: https://acme-v02.api.letsencrypt.org/directory
# Email address used for ACME registration
email: example#email.com
# Name of a secret used to store the ACME account private key
privateKeySecretRef:
name: letsencrypt-prod
# Enable the HTTP-01 challenge provider
solvers:
- http01:
ingress:
class: nginx
I applied ingress
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
namespace: staging
name: ingress
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
tls:
- hosts:
- www.stagingmyappsrl.com
- api.stagingmyappsrl.com
secretName: stagingmyappsrl-tls
rules:
- host: wwwstaging.myappsrl.com
http:
paths:
- backend:
serviceName: myappcatalogo-svc
servicePort: 80
- host: apistaging.stagingmyappsrl.com
http:
paths:
- backend:
serviceName: myappnodeapi-svc
servicePort: 80
It seems that everything is created and working if I check in GKE website, but when I try to access I get DNS_PROBE_FINISHED_NXDOMAIN
I am not sure if I am missing an step or if I am setting up something wrong
GKE should have created a cloud load balancer for your ingress service. Depending on your config, the LB can be internal or external. You can get your LB information by looking at the services:
kubectl get svc -n ingress-nginx
Create a CNAME record in your DNS (namecheap) with the LB address and that should do it. Alternatively, if you have an IP address of the LB, create an A record in your DNS.
Cert-manager will create an ingress resource to resolve HTTPS01 challenges. Make sure your ingresses are reachable over the Internet for the HTTPS01 challenges to work. Alternatively, you could explore other solvers.

Creating a path based Ingress on a GKE cluster

So I am in the process of migrating my bare metal cluster onto GKE and ran into an issue with the ingress. On my bare metal cluster, I used the ingress controller from nginxinc which worked fine. Below is a sample of an Ingress file of a particular deployment:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
namespace: mynamespace
name: app-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- host: myhost
http:
paths:
- path: /dev/appname(/|$)(.*)
backend:
serviceName: app
servicePort: 80
Basically, when a user types in myhost/dev/appname, myhost is resolved to a HAProxy server. The proxy then routes the request to the NodePort that the ingress service is running on.
I tried to do the same thing on my GKE cluster with the only exception being that the Ingress controller on the GKE cluster is exposed using a LoadBalancer as per the documentation
However I get a 502 error if I try to access the URL.
TL;DR: Looking for the best way to access various applications (deployments) deployed on a GKE cluster using URL's like: myhost/dev/firstapp and myhost/dev/secondapp etc.
You can use Kong Ingress as your ingress controller on GKE for your path based ingresses. You can install Kong Ingress from GCP Marketplace. It is easy to integrate and also supports various plugins for authenticating, monitoring etc.
You'll get detailed information and installation instructions from https://github.com/Kong/google-marketplace-kong-app#basic-usage
I would follow this guide on setting up Nginx on GKE. The ingress looks like below:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-resource
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
rules:
- http:
paths:
- path: /hello
backend:
serviceName: hello-app
servicePort: 8080
You should be able to access your app externally http://external-ip-of-ingress-controller/hello
Now to debug 502 issue verify that the health-checks from the Loadbalancer to your app is passing or not.

Expose ingress path inside cluster but not on public?

I have a pod that has following chart:
ingress:
enabled: true
annotations:
kubernetes.io/ingress.class: nginx
// ...
paths:
- /api/myservice
My pod exposes api and additionally a /prometheus endpoint that is accessible through /api/myservice/prometheus.
I would like to have prometheus visible inside my cluster but not from /api/myservice/prometheus. How I can achieve that?
You can add an Ingress rule that redirects the endpoint to the default-backend:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: block
annotations:
ingress.kubernetes.io/ssl-redirect: "true"
ingress.kubernetes.io/rewrite-target: /
spec:
tls:
- hosts:
- myapp.to
rules:
- host: myapp.to
http:
paths:
- path: /metrics
backend:
serviceName: ingress-default-backend
servicePort: 8080
If you just need internal access, I don't think you should put it into ingress. You could make use of the DNS Service together with Kubernetes cluster already.
If your prometheus service is running the same namespace as your working pod, you could use following address to access it.
http://prometheus-svc-name
If your prometheus service is running in a different namespace, you could use:
http://prometheus-svc-name.prometheus-namespace.svc.cluster.local
to access the service.
Update:
More clear about the question after comments.
You could write another rule to hide your /prometheus endpoint like this:
ingress:
enabled: true
annotations:
kubernetes.io/ingress.class: nginx
// ...
paths:
- /api/myservice => myservice
- /api/myservice/prometheus => 404 default backend.
nginx-ingress will match the longest route first. It will route /api/myservice/prometheus to 404. See this documentation
Best way to achieve this would be to remove the prometheus endpoint from ingress and if you are aware prometheus supports auto discovery using annotations on the service, configure prometheus for k8s auto discovery and then add annotations in you service yaml file.
https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kubernetes_sd_config
change the endpoint to point to your API.
/api/myservice/my-api or use app-root annotation, to point to your api inside /api/myservice:
nginx.ingress.kubernetes.io/app-root: /path/to/my/app/root/dir
more details here: https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#rewrite

Ingress and SSL Passthrough

I have recently been using the nginxdemo/nginx-ingress controller.
As I understand it this controller cannot do SSL Passthrough (by that I mean pass the client certificate all the way through to the backend service for authentication), so instead I have been passing the clients subject DN through a header.
Ultimately I would prefer SSL-Passthrough and have been looking at the kubernetes/ingress-nginx project which apparently supports SSL passthrough.
Does anyone have an experience with this controller and SSL Passthrough.
The few Ingress examples showing passthrough that I have found leave the path setting blank.
Is this because passthrough has to take place at the TCP level (4) rather then at HTTP (7)?
Right now, I have a single host rule that services mutiple paths.
completing on lch answer I would like to add that I had the same problem recently and I sorted it out modifiying the ingress-service deployment (I know, it should be a DaemonSet but that's a different story)
The change was adding the parameter to spec.containers.args:
--enable-ssl-passthrough
Then I've added the following annotations to my ingress:
kubernetes.io/ingress.allow-http: "false"
nginx.ingress.kubernetes.io/secure-backends: "true"
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
The important one are secure-backends and ssl-passthrough but I think the rest are a good idea, provided you're not expecting http traffic there
SSH-Passthrough is working fine for me. Here is the Official Documentation
And here is an example usage:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: my-service-ingress
namespace: my-service
annotations:
kubernetes.io/ingress.allow-http: "false"
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
nginx.ingress.kubernetes.io/secure-backends: "true"
spec:
rules:
- host: my.example.com
http:
paths:
- backend:
serviceName: my-service

GKE Ingress Basic Authentication (ingress.kubernetes.io/auth-type)

I'm trying to get a GKE ingress to require basic auth like this example from github.
The ingress works fine. It routes to the service. But the authentication isn't working. Allows all traffic right through. Has GKE not rolled this feature out yet? Something obviously wrong in my specs?
Here's the ingress:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: super-ingress
annotations:
ingress.kubernetes.io/auth-type: basic
ingress.kubernetes.io/auth-secret: basic-auth
ingress.kubernetes.io/auth-realm: "Authentication Required"
spec:
rules:
- host: zzz.host.com
http:
paths:
- backend:
serviceName: super-service
servicePort: 9000
path: /*
And the basic-auth secret:
$ kubectl get secret/basic-auth -o yaml
apiVersion: v1
data:
auth: XXXXXXXXXXXXXXXXXXX
kind: Secret
metadata:
creationTimestamp: 2016-10-03T21:21:52Z
name: basic-auth
namespace: default
resourceVersion: "XXXXX"
selfLink: /api/v1/namespaces/default/secrets/basic-auth
uid: XXXXXXXXXXX
type: Opaque
Any insights are greatly appreciated!
The example you linked to is for nginx ingress controller. GKE uses GLBC, which doesn't support auth.
You can deploy an nginx ingress controller in your gke cluster. Note that you need to annotate your ingress to avoid the GLBC claiming the ingress. Then you can expose the nginx controller directly, or create a glbc ingress to redirect traffic to the nginx ingress (see this snippet written by bprashanh).