Security and Network Policy
Ingress Authentication
If user wants to utilize basic auth or oauth at ingress, it can be done as described in official documentation or in our documentation.
This approach has one big security flaw. Authentication is required when connecting via ingress only, e.g., from outside of Kubernetes cluster. However, user of the platform can also connect from inside cluster directly to the corresponding service (they need to guess it IP though) and in such a case, there is no authentication required.
This flaw can be mitigated using Network Policy that can limit origin of network traffic. In this case, it is useful to allow ingress traffic to server from kube-system namespace only. The kube-system namespace hosts Ingress Nginx instance, therefore, connection from this and only this namespace is required.
Example of network policy can be downloaded here. This policy allows ingress traffic from kube-system to Pod named myapp
. This policy is applied to the namespace where the Pod myapp
is.
E-infra Single Sign On (BETA)
It is possible to utilize e-infra’s SSO service to secure your application. To enable this, some data must be added to the ingress. We will show how to edit an existing ingress to include SSO.
This example represents an existing ingress:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-name
annotations:
kubernetes.io/tls-acme: "true"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
ingressClassName: nginx
tls:
- hosts:
- "hostname.dyn.cloud.e-infra.cz"
secretName: hostname-dyn-cloud-e-infra-cz-tls
rules:
- host: "hostname.dyn.cloud.e-infra.cz"
http:
paths:
- path: /
backend:
service:
name: service-name
port:
number: port-number
pathType: Prefix
Firstly, we must add a few annotations to the ingress itself:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-name
annotations:
kubernetes.io/tls-acme: "true"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
+ nginx.ingress.kubernetes.io/auth-url: "https://$host/oauth2/auth?allowed_emails=email1@ics.muni.cz, email2@ics.muni.cz, email3@ics.muni.cz"
+ nginx.ingress.kubernetes.io/auth-signin: "https://$host/oauth2/start?rd=$scheme%3A%2F%2F$host$escaped_request_uri"
spec:
ingressClassName: nginx
tls:
- hosts:
- "hostname.dyn.cloud.e-infra.cz"
secretName: hostname-dyn-cloud-e-infra-cz-tls
rules:
- host: "hostname.dyn.cloud.e-infra.cz"
http:
paths:
- path: /
backend:
service:
name: service-name
port:
number: service-port-number
pathType: Prefix
The nginx.ingress.kubernetes.io/auth-url
annotation contains a query string
which specifies a list of users that should be able to access the website,
only change the list of emails in this field, do not change the URL in any
way.
The other annotation simply tells the ingress that it should redirect back to the webpage after the user authenticates.
Now that the ingress is configured to use an SSO enpoint, we must configure the SSO endpoint itself. To do this we must apply the following YAML file:
apiVersion: v1
kind: Service
metadata:
name: ingress-name-oauth
spec:
type: ExternalName
externalName: oauth2-proxy.kube-system.svc.cluster.local
ports:
- name: http
port: 4180
protocol: TCP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-name-oauth
annotations:
kubernetes.io/tls-acme: "true"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
kubernetes.io/ingress.class: "nginx"
tls:
- hosts:
- "hostname.dyn.cloud.e-infra.cz"
secretName: hostname-dyn-cloud-e-infra-cz-tls
rules:
- host: "hostname.dyn.cloud.e-infra.cz"
http:
paths:
- path: /oauth2
backend:
service:
name: ingress-name-oauth
port:
number: 4180
pathType: Prefix
Note that the hosts
and secretName
are the same as in the original ingress.
The only thing that needs to be changed in the file is all occurences of
ingress-name
and hostname
, replace them with the name of your ingress
and web page URL and apply the file.
With all the changes applied, your webiste is now secured with the e-infra’s SSO service.