How to secure my application?
To enable Dex authentication for your application, follow these steps:
-
Create a DexAuthenticator custom resource.
Creating
DexAuthenticator
in a cluster results in an oauth2-proxy instance being created. The latter is connected to Dex. Once theDexAuthenticator
custom resource becomes available, the necessary Deployment, Service, Ingress, Secret objects will be created in the specified namespace.An example of the
DexAuthenticator
custom resource:apiVersion: deckhouse.io/v1 kind: DexAuthenticator metadata: # Dex authenticator pod name prefix. # For example, if the name prefix is `app-name`, then Dex authenticator pods will look like `app-name-dex-authenticator-7f698684c8-c5cjg`. name: app-name # Namespace to deploy Dex authenticator to. namespace: app-ns spec: # Your application's domain. Requests to it will be redirected for Dex authentication. applicationDomain: "app-name.kube.my-domain.com" # A parameter that determines whether to send the `Authorization: Bearer` header to the application. # This one is useful in combination with auth_request in NGINX. sendAuthorizationHeader: false # The name of the Secret containing the SSL certificate. applicationIngressCertificateSecretName: "ingress-tls" # The name of the Ingress class to use in the Ingress resource created for the Dex authenticator. applicationIngressClassName: "nginx" # The duration of the active user session. keepUsersLoggedInFor: "720h" # The list of groups whose users are allowed to authenticate. allowedGroups: - everyone - admins # The list of addresses and networks for which authentication is allowed. whitelistSourceRanges: - 1.1.1.1/32 - 192.168.0.0/24
-
Connect your application to Dex.
For this, add the following annotations to the application’s Ingress resource:
nginx.ingress.kubernetes.io/auth-signin: https://$host/dex-authenticator/sign_in
nginx.ingress.kubernetes.io/auth-response-headers: X-Auth-Request-User,X-Auth-Request-Email
nginx.ingress.kubernetes.io/auth-url: https://<NAME>-dex-authenticator.<NS>.svc.{{ C_DOMAIN }}/dex-authenticator/auth
, where:NAME
— the value of themetadata.name
parameter of theDexAuthenticator
resource;NS
— the value of themetadata.namespace
parameter of theDexAuthenticator
resource;C_DOMAIN
— the cluster domain (the clusterDomain parameter of theClusterConfiguration
resource).
Below is an example of annotations added to an application’s Ingress resource so that it can be connected to Dex:
annotations: nginx.ingress.kubernetes.io/auth-signin: https://$host/dex-authenticator/sign_in nginx.ingress.kubernetes.io/auth-url: https://app-name-dex-authenticator.app-ns.svc.cluster.local/dex-authenticator/auth nginx.ingress.kubernetes.io/auth-response-headers: X-Auth-Request-User,X-Auth-Request-Email
Setting up CIDR-based restrictions
DexAuthenticator does not have a built-in system for allowing the user authentication based on its IP address. Instead, you can use annotations for Ingress resources:
-
If you want to restrict access by IP and use Dex for authentication, add the following annotation with a comma-separated list of allowed CIDRs:
nginx.ingress.kubernetes.io/whitelist-source-range: 192.168.0.0/32,1.1.1.1
-
Add the following annotation if you want to exclude users from specific networks from passing authentication via Dex and force users from all other networks to authenticate via Dex:
nginx.ingress.kubernetes.io/satisfy: "any"
Authentication flow with DexAuthenticator
-
Dex redirects the user to the provider’s login page in most cases and wait for the user to be redirected back to the
/callback
URL. However, some providers like LDAP or Atlassian Crowd do not support this flow. The user should write credentials to the Dex login form instead, and Dex will make a request to the provider’s API to validate them. -
DexAuthenticator sets the cookie with the whole refresh token (instead of storing it in Redis like an id token) because Redis does not persist data. If there is no id token by the id token ticket in Redis, the user will be able to get the new id token by providing the refresh token from the cookie.
-
DexAuthenticator sets the
Authorization
HTTP header to the ID token value from Redis. It is not required for services like Upmeter, because permissions to Upmeter entities are not highly grained. On the other hand, for the Kubernetes Dashboard, it is a crucial functionality because it sends the ID token further to access Kubernetes API.
How can I generate a kubeconfig and access Kubernetes API?
You can generate kubeconfig
for remote access to the cluster via kubectl
via the kubeconfigurator
web interface.
Configure the publishAPI parameter:
-
Open the
user-authn
module settings (create the moduleConfiguser-authn
resource if there is none):kubectl edit mc user-authn
-
Add the following section to the
settings
block and save the changes:publishAPI: enabled: true
The name kubeconfig
is reserved for accessing the web interface that allows generating kubeconfig
. The URL for access depends on the value of the parameter publicDomainTemplate (for example, for publicDomainTemplate: %s.kube.my
it will be kubeconfig.kube.my
, and for publicDomainTemplate: %s-kube.company.my
it will be kubeconfig-kube.company.my
).
Configuring kube-apiserver
With the functional of the control-plane-manager module, Deckhouse automatically configures kube-apiserver by providing the following flags, so that dashboard and kubeconfig-generator modules can work in the cluster.
The flow of accessing Kubernetes API with generated kubeconfig
-
Before the start, kube-apiserver needs to request the configuration endpoint of the OIDC provider (Dex in our case) to get the issuer and JWKS endpoint settings.
-
Kubeconfig generator stores id token and refresh token to the kubeconfig file.
-
After receiving request with an id token, kube-apiserver goes to validate, that the token is signed by the provider configured on the first step by getting keys from the JWKS endpoint. As the next step, it compares
iss
andaud
claims values of the token with the values from configuration.
How secure is Dex from brute-forcing my credentials?
Only 20 login attempts are allowed per user. If this limit is used up, one additional attempt will be added every 6 seconds.