http basic auth example with nginx ingress controller (nginxinc) - nginx-config

I can't get http basic auth working with nginxinc ingress controller docs: https://docs.nginx.com/nginx/admin-guide/security-controls/configuring-http-basic-authentication
My usecase:
I have a Ingress running at web.mydomain.com. I need to add basic HTTP auth to this endpoint.
Does anyone have a running example for it?
Here's my basic web Ingress:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: cafe-ingress
annotations:
kubernetes.io/ingress.class: nginx
nginx.org/server-snippets: |
location /auth {
auth_basic "Administrator’s Area";
auth_basic_user_file "/home/madhu/auth";
}
spec:
ingressClassName: nginx # use only with k8s version >= 1.18.0
rules:
- host: web.mydomain.com
http:
paths:
- path: /
backend:
serviceName: web
servicePort: 80

You have to create a kubernetes secret :
$ htpasswd -c auth foo
New password: <bar>
New password:
Re-type new password:
Adding password for user foo
$ kubectl create secret generic basic-auth --from-file=auth
$ kubectl get secret basic-auth -o yaml
apiVersion: v1
data:
auth: Zm9vOiRhcHIxJE9GRzNYeWJwJGNrTDBGSERBa29YWUlsSDkuY3lzVDAK
kind: Secret
metadata:
name: basic-auth
namespace: default
type: Opaque
If you use helm copy this output in a file secret.yaml on template folder.
After that, you have to use the auth-secret annotation like this :
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-with-auth
annotations:
# type of authentication
nginx.ingress.kubernetes.io/auth-type: basic
# name of the secret that contains the user/password definitions
nginx.ingress.kubernetes.io/auth-secret: basic-auth
# message to display with an appropriate context why the authentication is required
nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - foo'
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /
backend:
serviceName: http-svc
servicePort: 80
To see more, read this documentation : https://kubernetes.github.io/ingress-nginx/examples/auth/basic/

Related

How to check the signature of a token in kubernetes ingress?

I have an application written in Java. I packaged it in docker and deploy it using kubernetes. We use keycloak for single sign-on. I want to check the signature of the token.
I have url with public a key and clientID. I want to do signature verification JWT.
How can I add ingress to make the token verification work?
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-name
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- host: myHost.com
http:
paths:
- path: /myPath(/|$)(.*)
pathType: Prefix
backend:
service:
name: my-service
port:
number: 81

How to deploy a letsencryp with cert-manager and HAProxy-ingress

Digging into www, didn't found an answer:
I want to know how I can use cert-manager with haproxy-ingress and lets encrypt.
Any documentation / guidelines?
Deploy Certmanager with:
kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.4.0/cert-manager.yaml
kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.4.0/cert-manager.crds.yaml
Deploy a ClusterIssuer (cluster issuers are namespace agnostic)
cat > prod-issuer.yaml <<EOF
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: email#example.com
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress:
class: haproxy
EOF
Apply the cluster issuer with kubectl apply -f prod-issuer.yaml
Create an Ingress Resource (namespace gnostic, this example is using Nginx backend service)
cat > nginx-ingress.yaml <<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-router
namespace: production
annotations:
kubernetes.io/ingress.class: "haproxy"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
tls:
- hosts:
- "example.com"
secretName: nginx-tls-secret
rules:
- host: example.com
http:
paths:
- pathType: ImplementationSpecific
path: "/"
backend:
service:
name: nginx
port:
number: 80
- host: www.example.com
http:
paths:
- pathType: ImplementationSpecific
path: "/"
backend:
service:
name: nginx
port:
number: 80
EOF
Apply the ingress recourse with kubectl apply -f nginx-ingress.yaml
The important piece of information here, is that the Haproxy controller does NOT need the annotation acme.cert-manager.io/http01-edit-in-place: "true"
that nginx-ingress controller does. It works as expected without any extra annotations.
When you apply the Ingress Resourse to the cluster, the certificate will be issued in 1-2 minutes tops.
Use kubectl describe certificate nginx-tls-secret -n production to check the status of the certificate, and look at the event to get the certificate.
For more debugging info incase something went wrong, refer here https://cert-manager.io/docs/faq/acme/
you can try installing cert manager provided by jetstack, can be found here and then you need to follow the steps mentioned in this stackoverflow post and this will get things sorted for you.
An internal acme-challenge will be done by cert manager and once you patch the secret name, mentioned in the certificate to the TLS of ingress then certificate status will get ready state, Note that the secret will get created automatically, you need not create it

Kubernetes's Ingress annotations for x509 certificate authentificate

I'm trying to use kubernetes ingress annotation rules in order to enable X509 authentication.
My ingress yaml file is defined below:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
namespace: bdf-opengie-test
name: keycloak-opengie-test-ssl
labels:
app: keycloak-opengie
annotations:
nginx.ingress.kubernetes.io/auth-tls-verify-client: "on"
nginx.ingress.kubernetes.io/auth-tls-secret: "opengie-tls-secret"
nginx.ingress.kubernetes.io/auth-tls-verify-depth: "3"
nginx.ingress.kubernetes.io/auth-tls-pass-certificate-to-upstream: "true"
spec:
rules:
- host: keycloak-opengie-test-ssl.bdf-clu4.paas.eclair.local
http:
paths:
- path: /
backend:
serviceName: keycloak-opengie
servicePort: http
tls:
- hosts:
- keycloak-opengie-test-ssl.bdf-clu4.paas.eclair.local
When I invoke my application url, I'm expecting to see a popup requesting for a certificate, but nothing happens.
It seems like the annotations has no effect in the ingress definition.
Can someone tell me what's going wrong in my ingress definition.
I'm using Nginx Ingress: 0.15.0 and Kubernetes 1.10.5
First of all you are missing the secret with SSL files issued for your domain. (if we are talking about a native k8s secret management) You secret should be created by:
kubectl --namespace bdf-opengie-test create secret tls <secret_name> --key <key_path> --cert <cert_path>
Then your Ingress .yml file should contain this secret:
...
tls:
- hosts:
- keycloak-opengie-test-ssl.<domain>
secretName: <secret_name>
Only after this you can think about any annotations for auth or something else which is not working
Note: the secret is a namespaced object.
ingress:
hostname: id.login.example.com
annotations:
nginx.ingress.kubernetes.io/configuration-snippet: "more_clear_input_headers \"x-forwarded-client-cert\";\n more_set_input_headers \"x-forwarded-client-cert: $ssl_client_cert\";\n"
nginx.ingress.kubernetes.io/server-snippet: |
ssl_verify_client on;
ssl_client_certificate /etc/nginx/truststore-development.crt;
ssl_verify_depth 2;
ssl_session_cache off;

traefik ingress custom error in kubernetes

I need to set a custom error in traefik ingress on kubernetes so that when there is no endpoint or when the status is "404", or "[500-600]" it redirects to another error service or another custom error message I used the annotation as it's in the documentation in the ingress file as this (Note: this a helm template output of passing the annotation as a yaml in the values.yaml file)
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: frontend
namespace: "default"
annotations:
external-dns.alpha.kubernetes.io/target: "domain.com"
kubernetes.io/ingress.class: "traefik"
traefik.ingress.kubernetes.io/error-pages: "map[/:map[backend:hello-world status:[502 503]]]"
spec:
rules:
- host: frontend.domain.com
http:
paths:
- backend:
serviceName: frontend
servicePort: 3000
path: /
The answer by ldez is correct, but there are a few caveats:
First off, these annotations only work for traefik >= 1.6.x (earlier versions may support error pages, but not for the kubernetes backend)
Second, the traefik backend must be configured through kubernetes. You cannot create a backend in a config file and use it with kubernetes, at least not in traefik 1.6.x
Here's how the complete thing looks like. foo is just a name, as explained in the other answer, and can be anything:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: frontend
namespace: "default"
annotations:
external-dns.alpha.kubernetes.io/target: "domain.com"
kubernetes.io/ingress.class: "traefik"
traefik.ingress.kubernetes.io/error-pages: |-
foo:
status:
- "404"
- "500"
# See below on where "error-pages" comes from
backend: error-pages
query: "/{{status}}.html"
spec:
rules:
# This creates an ingress on an non-existing host name,
# which binds to a service. As part of this a traefik
# backend "error-pages" will be created, which is the one
# we use above
- host: error-pages
http:
paths:
- backend:
serviceName: error-pages-service
servicePort: https
- host: frontend.domain.com
http:
# The configuration for your "real" Ingress goes here
# This is the service to back the ingress defined above
# Note that you can use anything for this, including an internal app
# Also: If you use https, the cert on the other side has to be valid
---
kind: Service
apiVersion: v1
metadata:
name: error-pages-service
namespace: default
spec:
ports:
- name: https
port: 443
type: ExternalName
externalName: my-awesome-errors.mydomain.test
If you use this configuration, and your app sends a 404, then https://my-awesome-errors.mydomain.test/404.html would be shown as the error page.
The correct syntax is:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: frontend
namespace: "default"
annotations:
external-dns.alpha.kubernetes.io/target: "domain.com"
kubernetes.io/ingress.class: "traefik"
traefik.ingress.kubernetes.io/error-pages: |-
foo:
status:
- "404"
backend: bar
query: /bar
fii:
status:
- "500-600"
backend: bar
query: /bir
spec:
rules:
- host: frontend.domain.com
http:
paths:
- backend:
serviceName: frontend
servicePort: 3000
path: /
https://docs.traefik.io/v1.6/configuration/backends/kubernetes/#general-annotations
Note that, currently, the Helm Charts doesn't support this feature.
Ingress does not support that annotations that you guys are using there!
That annotations are supported with Service only, Ingress is using host section.

Kubernetes basic authentication with Traefik

I am trying to configure Basic Authentication on a Nginx example with Traefik as Ingress controller.
I just create the secret "mypasswd" on the Kubernetes secrets.
This is the Ingress I am using:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginxingress
annotations:
ingress.kubernetes.io/auth-type: basic
ingress.kubernetes.io/auth-realm: traefik
ingress.kubernetes.io/auth-secret: mypasswd
spec:
rules:
- host: nginx.mycompany.com
http:
paths:
- path: /
backend:
serviceName: nginxservice
servicePort: 80
I check in the Traefik dashboard and it appear, if I access to nginx.mycompany.com I can check the Nginx webpage, but without the basic authentication.
This is my nginx deployment:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
Nginx service:
apiVersion: v1
kind: Service
metadata:
labels:
name: nginxservice
name: nginxservice
spec:
ports:
# The port that this service should serve on.
- port: 80
# Label keys and values that must match in order to receive traffic for this service.
selector:
app: nginx
type: ClusterIP
It is popular to use basic authentication. In reference to Kubernetes documentation, you should be able to protect access to Traefik using the following steps :
Create authentication file using htpasswd tool. You'll be asked for a password for the user:
htpasswd -c ./auth
Now use kubectl to create a secret in the monitoring namespace using the file created by htpasswd.
kubectl create secret generic mysecret --from-file auth
--namespace=monitoring
Enable basic authentication by attaching annotations to Ingress object:
ingress.kubernetes.io/auth-type: "basic"
ingress.kubernetes.io/auth-secret: "mysecret"
So, full example config of basic authentication can looks like:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: prometheus-dashboard
namespace: monitoring
annotations:
kubernetes.io/ingress.class: traefik
ingress.kubernetes.io/auth-type: "basic"
ingress.kubernetes.io/auth-secret: "mysecret"
spec:
rules:
- host: dashboard.prometheus.example.com
http:
paths:
- backend:
serviceName: prometheus
servicePort: 9090
You can apply the example as following:
kubectl create -f prometheus-ingress.yaml -n monitoring
This should work without any issues.
Basic Auth configuration for Kubernetes and Traefik 2 seems to have slightly changed. It took me some time to find the solution, that's why I want to share it. I use k3s btw.
Step 1 + 2 are identical to what #d0bry wrote, create the secret:
printf "my-username:`openssl passwd -apr1`\n" >> my-auth
kubectl create secret generic my-auth --from-file my-auth --namespace my-namespace
Step 3 is to create the ingress object and apply a middleware that will handle the authentication
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: my-auth-middleware
namespace: my-namespace
spec:
basicAuth:
removeHeader: true
secret: my-auth
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
namespace: my-namespace
annotations:
kubernetes.io/ingress.class: traefik
traefik.ingress.kubernetes.io/router.middlewares: my-namespace-my-auth-middleware#kubernetescrd
spec:
rules:
- host: my.domain.net
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-service
port:
number: 8080
And then of course apply the configuration
kubectl apply -f my-ingress.yaml
refs:
https://doc.traefik.io/traefik/routing/providers/kubernetes-ingress/
https://doc.traefik.io/traefik/middlewares/http/basicauth/
With the latest traefik (verified with 2.7) it got even simpler. Just create a secret of type kubernetes.io/basic-auth and use that in your middleware. No need to create the username:password string first and create a secret from that.
apiVersion: v1
kind: Secret
metadata:
name: my-auth
namespace: my-namespace
type: kubernetes.io/basic-auth
data:
username: <username in base64>
password: <password in base64>
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: my-auth-middleware
namespace: my-namespace
spec:
basicAuth:
removeHeader: true
secret: my-auth
Note that the password is not hashed as it is with htpasswd, but only base64 encoded.
Ref docs