UDS Core ----- # Distribution Support UDS Core is a versatile platform designed to operate across any [CNCF conformant](https://www.cncf.io/training/certification/software-conformance/) Kubernetes distribution. This documentation provides an overview of UDS Core's testing with different distributions as well as expectations and support provided for other distributions. ### Tested Distributions | Distribution | Status (latest pipeline) | Testing Schedule | |-------------|--------------|---------------------------------------------------------------------------------------------------------| | [K3s](https://k3s.io/) (run with [k3d](https://k3d.io/stable/)) | [![K3d HA Test](https://github.com/defenseunicorns/uds-core/actions/workflows/test-k3d-ha.yaml/badge.svg?branch=main&event=schedule)](https://github.com/defenseunicorns/uds-core/actions/workflows/test-k3d-ha.yaml?query=event%3Aschedule+branch%3Amain) | Nightly and before each release | | [Amazon EKS](https://aws.amazon.com/eks/) | [![EKS Test](https://github.com/defenseunicorns/uds-core/actions/workflows/test-eks.yaml/badge.svg?branch=main&event=schedule)](https://github.com/defenseunicorns/uds-core/actions/workflows/test-eks.yaml?query=event%3Aschedule+branch%3Amain) | Weekly and before each release | | [Azure AKS](https://azure.microsoft.com/en-us/products/kubernetes-service) | [![AKS Test](https://github.com/defenseunicorns/uds-core/actions/workflows/test-aks.yaml/badge.svg?branch=main&event=schedule)](https://github.com/defenseunicorns/uds-core/actions/workflows/test-aks.yaml?query=event%3Aschedule+branch%3Amain) | Weekly and before each release | | [RKE2](https://github.com/rancher/rke2) (run on [AWS](https://aws.amazon.com/)) | [![RKE2 Test](https://github.com/defenseunicorns/uds-core/actions/workflows/test-rke2.yaml/badge.svg?branch=main&event=schedule)](https://github.com/defenseunicorns/uds-core/actions/workflows/test-rke2.yaml?query=event%3Aschedule+branch%3Amain) | Weekly and before each release | :::note Unless otherwise indicated, the Kubernetes version used for testing is typically one minor version back from the [latest release](https://kubernetes.io/releases/) ("n-1"). If the latest Kubernetes version were 1.33, testing would be performed on 1.32, on the latest patch version where possible. ::: ### Other Distributions UDS Core is typically compatible with other CNCF-conformant Kubernetes distributions that have not reached their end of life. While these distributions are not part of our regular testing pipeline, we welcome and will review bug reports and contributions related to compatibility issues. When reporting issues, please include details about your environment and any relevant logs. ----- # DNS Configuration UDS Core deploys two Gateways by default - a Tenant Gateway for end-user applications and an Admin Gateway for administrative applications. You can read more about Istio configuration in UDS Core [here](https://uds.defenseunicorns.com/reference/configuration/ingress/). This section covers how to configure DNS for these Gateways. ### Domain Configuration Each Gateway requires a wildcard DNS entry corresponding with the chosen `DOMAIN` and `ADMIN_DOMAIN` [variables](https://github.com/defenseunicorns/uds-core/blob/f6b0b59060a14febd11b0cdc7480f853a57f8520/src/istio/zarf.yaml#L10-L16) (or `admin.` if not specifying a separate admin domain). When deploying UDS Core, you can expect two Gateways to be created that match the following domain names: - `*.` / Tenant Gateway - `*.` / Admin Gateway if setting `ADMIN_DOMAIN` - `*.admin.` / Admin Gateway if NOT setting `ADMIN_DOMAIN` :::note Wildcard records do not cover the root (apex) domain itself. If you need to serve applications directly on the root (for example, `uds.dev`), see [Istio Ingress docs](https://uds.defenseunicorns.com/reference/configuration/ingress/). ::: :::note The default value for `DOMAIN` is `uds.dev`, which is intended for development purposes only. For non-development purposes, you should override this value by specifying a value for `domain` in your `uds-config.yaml`. You can find instructions on how to do so [here](https://uds.defenseunicorns.com/reference/configuration/ingress/#configure-domain-name-and-tls-for-istio-gateways). ::: ### Bundle Configuration :::note UDS Core does not include any cloud provider specific configuration by default. Additional overrides are required to deploy UDS Core on a given provider. This section will refer to AWS, but values can be substituted as needed for other providers. ::: The Admin and Tenant Gateways will be each be bound to an external Load Balancer that is exposed on TCP ports 80 and 443 by default. The Admin Gateway should be configured to use an internal facing Load Balancer and the Tenant Gateway should be configured to use an external facing Load Balancer. Below is an example of overrides that would accomplish this: ```yaml kind: UDSBundle metadata: name: core-with-lb-config description: A UDS example bundle for deploying UDS Core with external Load Balancer configuration version: "0.0.1" packages: - name: core repository: oci://ghcr.io/defenseunicorns/packages/uds/core ref: 0.54.1-upstream overrides: istio-admin-gateway: gateway: values: - path: service.annotations.service\.beta\.kubernetes\.io/aws-load-balancer-type value: "external" - path: service.annotations.service\.beta\.kubernetes\.io/aws-load-balancer-scheme value: "internal" - path: service.annotations.service\.beta\.kubernetes\.io/aws-load-balancer-attributes value: "load_balancing.cross_zone.enabled=true" istio-tenant-gateway: gateway: values: - path: service.annotations.service\.beta\.kubernetes\.io/aws-load-balancer-type value: "external" - path: service.annotations.service\.beta\.kubernetes\.io/aws-load-balancer-scheme value: "internet-facing" - path: service.annotations.service\.beta\.kubernetes\.io/aws-load-balancer-attributes value: "load_balancing.cross_zone.enabled=true" ``` ### Istio Gateways Once UDS Core is deployed, there will be Istio Gateway resources in your cluster. You can find each Gateway in a dedicated namespace: ```console $ kubectl get gateway -A NAMESPACE NAME AGE istio-admin-gateway admin-gateway 1h istio-tenant-gateway tenant-gateway 1h ``` Each Gateway will have a Kubernetes Service of type Load Balancer: ```console $ kubectl get svc -A | grep LoadBalancer NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE istio-admin-gateway admin-ingressgateway LoadBalancer 10.43.82.84 k8s-istioadm-admin...elb.us-east-1.amazonaws.com 15021:30842/TCP,80:31304/TCP,443:31518/TCP 1h istio-tenant-gateway tenant-ingressgateway LoadBalancer 10.43.47.182 k8s-istioten-tenant...elb.us-east-1.amazonaws.com 15021:31222/TCP,80:30456/TCP,443:32508/TCP 1h ``` From here, you can register your domain and/or create DNS records for your environment that point to the appropriate Gateways/Load Balancers. Refer to your DNS provider's documentation. ----- # Flavor Specific Development Notes > This document describes various flavors of UDS Core. Specific flavors of UDS Core have access and architecture restrictions when used for development work. The `upstream` flavor is generally recommended for development as it does not have any restrictions or requirements. ### Registry1 The `registry1` flavor uses images from [Ironbank](https://p1.dso.mil/services/iron-bank) which can only be pulled with authentication. Developers can self-register on [P1 SSO](https://login.dso.mil/) and retrieve a pull token for auth from [registry1's Harbor](https://registry1.dso.mil/). (In upper right corner, click --> User Profile, then click the Copy icon next to CLI secret, and use this for `docker login`.) Images in `registry1` historically only supported `amd64` architectures. While some images do now support `arm64` architecture, uds-core only supports `amd64` for the `registry1` flavor. If developing on an `arm64` machine you will need to use a virtualization layer or an external dev box. ### Unicorn The `unicorn` flavor uses images primarily from a private repository. These images can be pulled by any developer in the Defense Unicorns organization. Developers outside the Defense Unicorns organization/company will be unable to pull these images directly and should rely on CI testing for validation of this flavor. [Contact us](https://www.defenseunicorns.com/contactus) if you have a need to pull these images and develop on this flavor in particular. ----- # Functional Layers ## Background Context on the inclusion of "functional layers" can be viewed in our [ADR](https://github.com/defenseunicorns/uds-core/blob/main/adrs/0002-uds-core-functional-layers.md). In short, UDS Core publishes smaller Zarf packages that contain subsets of core's capabilities, grouped by their function (such as monitoring, logging, backup/restore, etc) to allow more flexibility in deployment. This helps to support resource constrained environments (edge deployments) and other situations where an environment has different needs than the default core stack. Each layer is published as an individual OCI Zarf package. Package sources can be viewed under the [`packages` directory](https://github.com/defenseunicorns/uds-core/tree/main/packages), with each folder containing a readme detailing the contents and any dependencies. All layers (except CRDs) assume the requirement of the base layer which provides Istio, the UDS Operator, and UDS Policy Engine. :::caution By removing pieces of core from your deployment you may affect your security and compliance posture as well as reduce functionality of the stack. Deploying core using these layers should be the exception in most cases and only done after carefully weighing needs for your environment. ::: ## Example Usage Functional layers are designed to be combined into a UDS bundle for deployment. The example below shows all layers in the correct order. Keep in mind that 'base' must always be the first layer, and any other layers should follow based on their dependency order. When building your bundle, you can skip layers that don't fit your deployment needs and apply overrides to individual layers as needed. Ensure all layers are using the same version for compatibility. ```yaml kind: UDSBundle metadata: name: functional-layer-core-bundle description: An example bundle for deploying all of core using functional layers version: "0.1.0" packages: - name: core-crds repository: ghcr.io/defenseunicorns/packages/uds/core-crds ref: x.x.x-flavor - name: core-base repository: ghcr.io/defenseunicorns/packages/uds/core-base ref: x.x.x-flavor - name: core-identity-authorization repository: ghcr.io/defenseunicorns/packages/uds/core-identity-authorization ref: x.x.x-flavor - name: core-metrics-server repository: ghcr.io/defenseunicorns/packages/uds/core-metrics-server ref: x.x.x-flavor - name: core-runtime-security repository: ghcr.io/defenseunicorns/packages/uds/core-runtime-security ref: x.x.x-flavor - name: core-logging repository: ghcr.io/defenseunicorns/packages/uds/core-logging ref: x.x.x-flavor - name: core-monitoring repository: ghcr.io/defenseunicorns/packages/uds/core-monitoring ref: x.x.x-flavor - name: core-backup-restore repository: ghcr.io/defenseunicorns/packages/uds/core-backup-restore ref: x.x.x-flavor ``` ## Layer Selection Layer selection will always be deployment-specific but below are guidelines for what layers to consider for your deployment. The layers marked with a cross (†) are those needed to follow the [Big Bang Conformant Stack](https://repo1.dso.mil/big-bang/product/bbtoc/-/blob/master/policy/conformance.md?ref_type=heads) though if you are not bound by that document, UDS Core Base is the only *technical* layer required to install most UDS Packages. | UDS Core Layers | Selection Criteria | |----------------|--------------------| | Runtime Security†* | Provides more advanced security with runtime inspection
*(install if resources allow and more advanced security is desired)* | | Monitoring†* | Provides frontend log / metrics monitoring and alerting
*(install if resources allow and more advanced debugging is desired)* | | Backup and Restore | Allows volumes and k8s objects to be backed up and restored
*(install if deployment provides critical data or must maintain state)* | | Identity and Authorization† | Provides authentication and authorization functionality
*(install if deployment requires an auth mechanism (i.e. direct user login))* | | Logging† | Provides backend log storage and log shipping capabilities
*(install if the deployment requires log aggregation and shipping)* | | Metrics Server†** | Provides metrics collection capabilities (req of UDS Runtime)
*(install if the cluster does not provide its own metrics server)* | | Base† | Provides the base for all other functional layers
*(required for all "UDS" deployments and all other functional layers)* | | CRDs | Provides standalone UDS Core CRDs (Package, Exemption, ClusterConfig)
*(deploy before base if you need to create exemptions for pre-existing cluster components)* | :::note *The Monitoring and Runtime Security layers provide user login and therefore require the Identity and Authorization layer. ::: :::note **The Metrics Server layer provides a metrics server if your cluster does not deploy metrics server itself. If your cluster does provide its own metrics server deployment ensure that you do NOT enable this layer. ::: | UDS Add-ons* | Selection Criteria | |------------|--------------------| | UDS UI | Provides a common operating picture for a Kubernetes cluster and UDS deployments
*(install if you would like to have an easy-to-use window into your cluster/deployments)* | | UDS Registry | Provides a storage location for UDS components and mission applications
*(install if you would like to be able to easily store and view the software available in your environment)* | | UDS Remote Agent | Allows for more advanced remote cluster management / deployment
*(install if you would like to manage UDS deployments from more advanced clients than UDS CLI)* | :::note *UDS Add-ons are not part of the open-source platform but are also not required to maintain / operate a UDS deployment. They provide additional functionality to streamline the deployment, monitoring, and management of the deployment for the given organization. ::: | UDS Core Pre-Requisites* | Selection Criteria | |--------------------------|--------------------| | UDS Package Minio Operator | Provides storage for the Logging and Backup and Restore layers
*(install after core base but before logging/backup and restore if selected)* | | UDS Package MetalLB | Provides a simple LoadBalancer implementation
*(install after Zarf init and before UDS Core Base)* | :::note *You may need to deploy pre-requisite packages that are not a part of UDS Core's layers if you are on prem or in an edge scenario - usually cloud deployments will have their own offerings to provide these services which we recommend to use instead. ::: :::tip If you deploy pre-requisite packages (such as MetalLB or other storage/load balancer controllers) that need UDS policy exemptions, deploy the **CRDs layer** first. This lets you create `Exemption` custom resources alongside those packages, before UDS Core Base and its policy engine are active — preventing policy violations during upgrades or reconciliation. ::: ----- # Account Lockout ## Lockout Behavior Options UDS Core exposes one configurable option related to brute‑force protection: ### **Max Temporary Lockouts** This controls whether your realm uses: 1. Permanent lockout only: `MAX_TEMPORARY_LOCKOUTS = 0` (default) 1. Temporary lockout followed by permanent lockout: `MAX_TEMPORARY_LOCKOUTS > 0` Use the following bundle override to configure this functionality: ```yaml overrides: keycloak: keycloak: values: - path: realmInitEnv value: MAX_TEMPORARY_LOCKOUTS: 3 ``` ### Example flows #### 1. Default UDS Core behavior: **permanent lockout** (`MAX_TEMPORARY_LOCKOUTS = 0`) 1. User fails login **3 times** within a 12 hour window. 1. Keycloak applies a **permanent lockout** once the threshold is hit. 1. The account remains locked until an administrator manually unlocks it. #### 1. Optional: temporary then permanent mode (`MAX_TEMPORARY_LOCKOUTS > 0`) 1. Configure `MAX_TEMPORARY_LOCKOUTS` to a non‑zero value. 1. User fails login **3 times within the 12 hour window** → Keycloak applies a **temporary lockout** for 15 minutes. 1. After the temporary lockout expires, the account unlocks. 1. If the user triggers more temporary lockouts than allowed by the configured `MAX_TEMPORARY_LOCKOUTS` value, Keycloak escalates the account to a **permanent lockout**. The user has **up to 12 hours** during which additional lockouts count toward this limit. For example: * `MAX_TEMPORARY_LOCKOUTS = 1` → the **second** lockout results in permanent lock * `MAX_TEMPORARY_LOCKOUTS = 2` → the **third** lockout results in permanent lock ## Manually Configure Temporary Lockouts ### Admin Console (Keycloak 24+) 1. Sign into the Keycloak Admin Console and select your realm. 2. Navigate to **Realm Settings → Security Defenses → Brute Force Detection**. 3. Configure the following values: * Brute Force Protected: `Lockout permanently after temporary lockout` Enables Keycloak’s brute-force detection mechanism for the realm. * Failure Factor: `3` The number of failed login attempts within the counting window that triggers a lockout. * Quick Login Check (ms): `1000` If repeated failed attempts occur faster than this interval, Keycloak treats them as rapid-attack behavior and applies the minimum quick-login wait. * Max Delta Time (s): `43200` A rolling 12-hour window during which failed login attempts count toward the failure threshold. * Wait Increment (s): `900` The duration of a temporary lockout (15 minutes) after the failure threshold is reached. * Minimum Quick Login Wait (s): `60` The minimum delay applied when rapid successive failures occur. * Max Failure Wait (s): `86400` The maximum temporary lockout wait (24 hours). This sets the upper bound for how long Keycloak can delay a user before escalation. * Failure Reset Time (s): `43200` Controls when Keycloak resets the failure and lockout counters. Must exceed the rolling window to allow temporary lockouts to accumulate toward permanent lockout. * Permanent Lockout: `ON` Enables escalation to a permanent lockout once the configured number of temporary lockouts is exceeded. * Max Temporary Lockouts: `3` Allows one temporary lockout before escalating to a permanent lock. * Brute Force Strategy: `MULTIPLE` Defines how Keycloak handles the progression of lockout waits when repeated failures occur. 4. Save and test with a non-production account. ## Compliance :::caution There may be compliance impacts when modifying lockout behavior, be aware of any environment specific requirements (NIST controls or STIG requirements) for brute-force protection. ::: ----- # Authentication Flow Customization ## Authentication Flow Options UDS Core comes equipped with a robust authentication framework that supports multiple authentication methods to meet diverse security requirements and user preferences. Here’s a breakdown of the authentication options available: --- 1. Username and Password The most traditional form of authentication involves users providing a username and password that must match the credentials stored in the system. This method is widely used due to its simplicity and direct control over access credentials. --- 2. SSO (Single Sign-On) Single Sign-On (SSO) allows users to authenticate with one set of credentials to access multiple applications. UDS Core can be configured to integrate with various SSO providers, such as Google SSO, Microsoft Entra, and others, streamlining the login process and reducing the burden of managing multiple usernames and passwords. --- 3. x509 Certificate x509 certificates provide a way to authenticate using digital certificates. It is commonly used in environments that require higher security, such as corporate or governmental networks. This method uses public key infrastructure (PKI) to verify the user's identity through a trusted certificate authority. > **Air-Gapped Note**: In environments without reliable internet access, **OCSP revocation checks** may fail if the designated OCSP responder cannot be reached. As a short-term workaround, you can configure “fail-open” or disable OCSP checks entirely. However, these approaches carry **security risks** (e.g., potentially allowing revoked certificates). --- ![Authentication Flow Options](https://github.com/defenseunicorns/uds-identity-config/blob/main/docs/.images/diagrams/uds-core-auth-flows-options.svg?raw=true) ## MFA Authentication UDS Core comes with two different options for MFA requirements. One time password (OTP) and WebAuthn options can be configured. These options are available for both `Username and Password` and `x509` authentication flows. They are controlled individually, to provide the most amount of configurability. ```yaml - path: realmAuthFlows value: USERNAME_PASSWORD_AUTH_ENABLED: true X509_AUTH_ENABLED: true SOCIAL_AUTH_ENABLED: true OTP_ENABLED: true WEBAUTHN_ENABLED: false X509_MFA_ENABLED: false ``` Above is the complete list of authentication configurations from a bundle override. Below is the description of what each of those do: | Name | Description | Default Value | | - | - | - | | `USERNAME_PASSWORD_AUTH_ENABLED` | Controls whether the `Username and Password` authentication flow is allowed and present on the login page. | `true`(default), `false` | | `X509_AUTH_ENABLED` | Controls whether the `X509` authentication is allowed and present (when a proper certificate is present) on the login page. | `true`(default), `false` | | `SOCIAL_AUTH_ENABLED` | Controls whether the `Social` authentication is allowed and present on the login page. This requires that an Identity Provider be configured as well. | `true`(default), `false` | | `OTP_ENABLED` | Control whether `OTP` MFA is enabled, making it required for `Username and Password` authentication. | `true`(default), `false` | | `WEBAUTHN_ENABLED` | Control whether `WebAuthn` MFA is enabled, making it required for `Username and Password` authentication. | `true`, `false`(default) | | `X509_MFA_ENABLED` | Control whether `X509` authentication flow should also include MFA. Enabling this requires `OTP_ENABLED` or `WEBAUTHN_ENABLED` as well. | `true`, `false`(default) | :::caution We shift all authn and authz responsibilies to the Identity Provider if choosing to use SSO, this means that MFA is not configurable for SSO options. ::: ## Authentication Flows in UDS Core UDS Core is shipped with a basic authentication flow that includes all three options out of the box. The following diagram shows the basic authentication flows that are deployed with standard UDS Core: ![UDS Core Authentication Flow](https://github.com/defenseunicorns/uds-identity-config/blob/main/docs/.images/diagrams/uds-core-auth-flows-basic.svg?raw=true) ### Customizing Authentication Flows Different operational environments may necessitate distinct authentication flows to comply with specific security policies, regulatory demands, or demographic requirements. UDS Core facilitates the customization of these flows, allowing for tailored security measures and user interfaces. The diagram below illustrates various combinations of the three authentication methods that can be adapted to meet unique operational needs: ![Complex Authentication Flows](https://github.com/defenseunicorns/uds-identity-config/blob/main/docs/.images/diagrams/uds-core-auth-flows-complex.svg?raw=true) These customizations not only ensure appropriate security configurations by enabling or disabling specific flows but also maintain a seamless user experience by adjusting the Keycloak theme accordingly. The following sections provide a step-by-step guide on how to customize UDS Core to deploy specific authentication flows, catering to the particular needs and guidelines of your environment. ## Authentication Flow Customization :::note Environment variables configured in the [uds-core Keycloak values.yaml file](https://github.com/defenseunicorns/uds-core/blob/main/src/keycloak/chart/values.yaml#L30-32) have `REALM_` appended to them during creation. See [Customization docs](/reference/uds-core/idam/customization/) for more information. ::: :::caution If upgrading uds-core, be aware that Keycloak Admin manual configuration will probably be required to set new Realm values. See the manual configuration section below for how to do this. ::: ### Bundle Overrides To simplify the configuration of the available authentication flows, the following three environment variables have been exposed. These variables default to `true` in UDS Core, override their values in a bundle to disable. :::note These settings allow for enabling/disabling one or more of the Auth flows. Be aware that disabling `USERNAME_PASSWORD_AUTH_ENABLED`, `X509_AUTH_ENABLED` and `SOCIAL_AUTH_ENABLED` will result in no options for registration and authentication (login). At the same time disabling both `USERNAME_PASSWORD_AUTH_ENABLED` and `X509_AUTH_ENABLED` also disables the User Registration feature. ::: | Setting | Description | Options | | - | - | - | | [USERNAME_PASSWORD_AUTH_ENABLED](https://github.com/defenseunicorns/uds-core/blob/main/src/keycloak/chart/values.yaml#L30) | Toggle on/off the Username and Password Authentication flow. When disabled there will be no username password login, password / password confirm registration fields, no credential reset, and no update password options available. | `true`(default), `false` | | [X509_AUTH_ENABLED](https://github.com/defenseunicorns/uds-core/blob/main/src/keycloak/chart/values.yaml#L31) | Toggle on/off X509 (CAC) Authentication flow. | `true`(default), `false` | | [SOCIAL_AUTH_ENABLED](https://github.com/defenseunicorns/uds-core/blob/main/src/keycloak/chart/values.yaml#L32) | Toggle on/off Social (Google SSO, Azure AD, etc. ) Authentication flows.| `true`(default), `false` | | [X509_MFA_ENABLED](https://github.com/defenseunicorns/uds-core/blob/main/src/keycloak/chart/values.yaml#L32) | Toggle on/off X509 to require additional MFA options (OTP, WebAuthn, etc).| `true`, `false`(default) | These three variables handle the complexities of configuring the following environment variables, which are responsible for both visual (theme) and security (realm). The following variables are not exposed for overriding. ### Manual Configuration #### Theme Configurations Theme's cannot be clickops'ed, for these changes to take affect an upgrade or fresh deployment will be required. Another option is exec-ing into the the keycloak pod and copying in the new themes to the `/opt/keycloak/theme/themes/login/` directory. After copying in the theme changes, the theme changes depend on environment variables being defined in the [theme.properties file](https://github.com/defenseunicorns/uds-identity-config/blob/main/src/theme/login/theme.properties). The above table demonstrates the different environment variables for the `theme.properties` file. #### Realm Configurations All Realm Configurations require access to the Keycloak admin portal. | Configuration | How to Configure | | - | - | | `DENY_USERNAME_PASSWORD_ENABLED` | 1. Realm Authentication tab
2. Select the `UDS Authentication` Authentication Flow
3. `DISABLE` the `Deny Access` step that is below the `Username Password Form` | | `RESET_CREDENTIAL_FLOW_ENABLED` | 1. Realm Authentication tab
2. Select the `UDS Reset Credentials` Authentication Flow
3. `DISABLE` the `Reset Password` step | | `REGISTRATION_FORM_ENABLED` | 1. Realm Authentication tab
2. Select the `UDS Registration` Authentication Flow
3. `DISABLE` the `UDS Registration form` step | | `OTP_ENABLED` | 1. Realm Authentication tab
2. Select the `Required Action` tab at the top of the Authentication view
3. Toggle off the `Configure OTP` | | `WEBAUTHN_ENABLED` | 1. Realm Authentication tab
2. Select the `Required Action` tab at the top of the Authentication view
3. Toggle on the `Webauthn Register Passwordless` `Enabled` column
4. Select the `Flows` tab at the top of the Authentication view
5. Select the `UDS Authentication` flow
6. Set the `MFA` sub-flow to `Required`
7. Set the `WebAuthn Passwordless Authenticator` in the `MFA` sub-flow to `Required` | ----- # Image Customizations ## Add additional jars Adding additional jars to Keycloak's deployment is as simple as adding that jar to the [src/extra-jars directory](https://github.com/defenseunicorns/uds-identity-config/tree/main/src/extra-jars). Adding new jars will require building a new identity-config image for [uds-core](https://github.com/defenseunicorns/uds-core). See [Testing custom image in UDS Core](/reference/uds-core/idam/testing-deployment-customizations/) for building, publishing, and using the new image with `uds-core`. Once `uds-core` has sucessfully deployed with your new image, viewing the Keycloak pod can provide insight into a successful deployment or not. Also describing the Keycloak pod, should display your new image being pulled instead of the default image defined [here](https://github.com/defenseunicorns/uds-core/blob/main/src/keycloak/chart/values.yaml#L10) in the events section. ## Customizing Theme **Official Theming Docs** * [Official Keycloak Theme Docs](https://www.keycloak.org/docs/latest/server_development/#_themes) * [Official Keycloak Theme Github](https://github.com/keycloak/keycloak/tree/b066c59a83c99d757d501d8f5e6061372706d24d/themes/src/main/resources/theme) For other changes beyond these images you will need to build a custom theme and identity-config image. Changes can be made to the [src/theme](https://github.com/defenseunicorns/uds-identity-config/tree/main/src/theme) directory. At this time only Account and Login themes are included, but email, admin, and welcome themes could be added as well. ### Branding Customizations The UDS Identity Config supports a limited and opinionated set of branding customizations. This includes: * Changing the logo * Changing the footer image * Changing the favicon * Changing the background image These customizations require overriding the Keycloak Helm Chart provided by the UDS Core. Here's an example: ```yaml packages: - name: core repository: oci://ghcr.io/defenseunicorns/packages/uds/core ref: x.x.x overrides: keycloak: keycloak: values: - path: themeCustomizations value: resources: images: - name: background.png configmap: name: keycloak-theme-overrides - name: logo.png configmap: name: keycloak-theme-overrides - name: footer.png configmap: name: keycloak-theme-overrides - name: favicon.png configmap: name: keycloak-theme-overrides ``` The configuration supports four keys for different images: `background.png`, `logo.png`, `footer.png`, and `favicon.png`. You can set any or all of these images (you do not have to override all of them), and the corresponding key(s) must exist in your designated ConfigMap(s). Note that you must pre-create this ConfigMap in the `keycloak` namespace before deploying/upgrading Core with these overrides. In the above example all images are in the same ConfigMap named `keycloak-theme-overrides`. An easy way to generate the ConfigMap manifest is using the following command (including whichever images you need and specifying the correct paths to your local images): ```bash kubectl create configmap keycloak-theme-overrides \ --from-file=background.png=path/to/local/directory/background.png \ --from-file=logo.png=path/to/local/directory/logo.png \ --from-file=footer.png=path/to/local/directory/footer.png \ --from-file=favicon.png=path/to/local/directory/favicon.png \ -n keycloak --dry-run=client -o=yaml > theme-image-cm.yaml ``` To deploy this it is easiest to make a small zarf package referencing the manifest you just created: ```yaml kind: ZarfPackageConfig metadata: name: keycloak-theme-overrides version: 0.1.0 components: - name: keycloak-theme-overrides required: true manifests: - name: configmap namespace: keycloak # Ensure this is in the Keycloak namespace files: - theme-image-cm.yaml # Update to the manifest you have locally ``` Then create and deploy this zarf package _prior_ to deploying/upgrading UDS Core/Keycloak. ### Terms and Conditions Customizations In a similar theme to Branding customizations, the UDS Identity Config supports adjusting the Terms and Conditions (if enabled). These customizations similarly require overriding the Keycloak Helm Chart provided by the UDS Core. Here's an example: ```yaml packages: - name: core repository: oci://ghcr.io/defenseunicorns/packages/uds/core ref: x.x.x overrides: keycloak: keycloak: values: - path: themeCustomizations value: termsAndConditions: text: configmap: key: text name: keycloak-theme-overrides ``` The configuration supports a single key (named however you want) which must exist in the corresponding ConfigMap(s). Note that you must pre-create this ConfigMap in the `keycloak` namespace before deploying/upgrading Core with these overrides. The contents of this key must be your custom Terms and Conditions content, formatted as a single line HTML string. As a basic example you might want some terms and conditions like the following HTML: ```html

By logging in you agree to the following:

  • Terms
  • And
  • Conditions
``` In order to properly format this you will need to replace any newlines with the literal newline character (`\n`), converting your HTML to a single line. Using the above example that would look like this (again note the use of `\n` in place of the newlines): ```

By logging in you agree to the following:

\n
    \n
  • Terms
  • \n
  • And
  • \n
  • Conditions
  • \n
``` :::tip This replacement process can easily be done with a tool like `sed`: ```bash # This will require GNU sed cat terms.html | sed ':a;N;$!ba;s/\n/\\n/g' > single-line.html ``` ::: Your new single-line HTML file can be used to generate a properly formatted ConfigMap with the following command: ```bash kubectl create configmap keycloak-theme-overrides \ --from-file=text=path/to/local/directory/single-line.html \ -n keycloak --dry-run=client -o=yaml > terms-and-confitions-cm.yaml ``` To deploy this it is easiest to make a small zarf package referencing the manifest you just created: ```yaml kind: ZarfPackageConfig metadata: name: keycloak-terms-and-conditions version: 0.1.0 components: - name: keycloak-terms-and-conditions required: true manifests: - name: configmap namespace: keycloak # Ensure this is in the Keycloak namespace files: - terms-and-confitions-cm.yaml # Update to the manifest you have locally ``` Then create and deploy this zarf package _prior_ to deploying/upgrading UDS Core/Keycloak. :::tip In order to speed up the development process of the Customized Terms and Conditions, you can edit the ConfigMap in your cluster and then cycle the Keycloak pod to reload your updated Terms and Conditions. This will allow you to see the changes quicker without needing to rebuild/redeploy each time. ::: :::note The default terms and conditions provided are based on the standard DoD Notice and Consent Banner. The source HTML for these terms is in the identity-config repository [here](hhttps://github.com/defenseunicorns/uds-identity-config/blob/v0.15.0/src/theme/login/terms.ftl#L25-L79) and could be used as a starting point for customizing. Note that you will need to follow the above steps to properly format this as single-line HTML and create a ConfigMap with its contents. There are some limitations and you won't be able to dynamically lookup resources (i.e. `${url.resourcesPath}`) due to the way this input is dynamically injected into the terms template so keep this in mind if trying to reference external images. ::: ### Registration Form Fields Registration Form Fields, which by default are enabled, can be disabled to minimize the steps to register a new user. See [this section](/reference/uds-core/idam/customization/#templated-realm-values) for the example of disabling the registration form fields with the `themeCustomizations.settings.enableRegistrationFields` environment variable. When disabled, the following fields will not be present during registration: - Affiliation - Pay Grade - Unit, Organization or Company Name ### Testing Changes To test the `identity-config` theme changes, a local running Keycloak instance is required. Don't have a local Keycloak instance? The simplest testing path is utilizing [uds-core](https://github.com/defenseunicorns/uds-core), specifically the `dev-identity` task. This will create a k3d cluster with Istio, Pepr, Keycloak, and Authservice. Once that cluster is up and healthy and after making theme changes, utilize this task to : 1. Execute this command: ```bash uds run dev-theme ``` 2. View the changes in the browser ## Customizing Realm The `UDS Identity` realm is defined in the realm.json found in [src/realm.json](https://github.com/defenseunicorns/uds-identity-config/blob/main/src/realm.json5). This can be modified and will require a new `uds-identity-config` image for `uds-core`. :::note Be aware that changing values in the realm may also need to be updated throughout the configuration of Keycloak and Authservice in `uds-core`. For example, changing the realm name will break a few different things within Keycloak unless those values are changed in `uds-core` as well. ::: See the [Testing custom image in UDS Core](/reference/uds-core/idam/testing-deployment-customizations/) for building, publishing, and using the new image with `uds-core`. ### Templated Realm Values Keycloak supports using environment variables within the realm configuration, see [docs](https://www.keycloak.org/server/importExport). These environment variables have default values set in the realm.json that uses the following syntax: ```yaml ${REALM_GOOGLE_IDP_ENABLED:false} ``` In the uds-core keycloak [values.yaml](https://github.com/defenseunicorns/uds-core/blob/main/src/keycloak/chart/values.yaml), the `realmInitEnv` defines set of environment variables that can be used to configure the realm different from default values. These environment variables will be created with a prefix `REALM_` to avoid collisions with keycloak environment variables. If necessary to add additional template variables within the realm.json must be prefixed with `REALM_`. For example, this bundle override contains all the available overrides: ```yaml overrides: keycloak: keycloak: values: - path: realmInitEnv value: GOOGLE_IDP_ENABLED: true GOOGLE_IDP_ID: GOOGLE_IDP_SIGNING_CERT: GOOGLE_IDP_NAME_ID_FORMAT: GOOGLE_IDP_CORE_ENTITY_ID: GOOGLE_IDP_ADMIN_GROUP: GOOGLE_IDP_AUDITOR_GROUP: EMAIL_AS_USERNAME: true EMAIL_VERIFICATION_ENABLED: true TERMS_AND_CONDITIONS_ENABLED: true PASSWORD_POLICY: X509_OCSP_FAIL_OPEN: true ACCESS_TOKEN_LIFESPAN: 600 SSO_SESSION_LIFESPAN_TIMEOUT: 1200 SSO_SESSION_MAX_LIFESPAN: 36000 SSO_SESSION_MAX_PER_USER: 10 MAX_TEMPORARY_LOCKOUTS: 3 - path: realmAuthFlows value: USERNAME_PASSWORD_AUTH_ENABLED: true X509_AUTH_ENABLED: true SOCIAL_AUTH_ENABLED: true OTP_ENABLED: true WEBAUTHN_ENABLED: true X509_MFA_ENABLED: true - path: themeCustomizations.settings value: enableRegistrationFields: true - path: realmConfig.maxInFlightLoginsPerUser value: 10 ``` > These environment variables can be found in the [realm.json](https://github.com/defenseunicorns/uds-identity-config/blob/main/src/realm.json5) and the table below summarizes their purpose: | Option | Default value | Purpose | |------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------| | GOOGLE_IDP_* | false, unset | Google SAML Identity Provider configuration settings. | | EMAIL_AS_USERNAME | false | Treat the user's email as their username in the realm. | | EMAIL_VERIFICATION_ENABLED | false | Require users to verify their email address before using the account. | | TERMS_AND_CONDITIONS_ENABLED | false | Enable the Terms and Conditions screen that users must accept. | | PASSWORD_POLICY | hashAlgorithm(pbkdf2-sha256) and forceExpiredPasswordChange(60) and specialChars(2) and digits(1) and lowerCase(1) and upperCase(1) and passwordHistory(5) and length(15) and notUsername(undefined) | Define the Keycloak password policy applied to users in the realm. | | X509_OCSP_FAIL_OPEN | false | Control OCSP fail behavior for X.509 certificate authentication | | ACCESS_TOKEN_LIFESPAN | 60 | Access token validity period in seconds. | | SSO_SESSION_LIFESPAN_TIMEOUT | 600 | Session idle timeout in seconds. | | SSO_SESSION_MAX_LIFESPAN | 36000 | Maximum absolute session lifespan in seconds, regardless of activity. | | SSO_SESSION_MAX_PER_USER | 0 | Maximum number of concurrent active sessions per user. | | MAX_TEMPORARY_LOCKOUTS | 0 | Number of temporary lockouts that occur before a permanent lockout. | | SECURITY_HARDENING_ADDITIONAL_PROTOCOL_MAPPERS | unset | Additional Protocol Mappers added to the allow list for UDS hardening. | | SECURITY_HARDENING_ADDITIONAL_CLIENT_SCOPES | unset | Additional Client Scopes added to the allow list for UDS hardening. | :::note **Important**: By allowing certificates to pass when no revocation check is performed, you accept the **risk** of potentially allowing revoked certificates to authenticate. This can pose a significant security threat depending on your organization’s compliance requirements and threat model. - **Fail-Closed (`X509_OCSP_FAIL_OPEN:false`)**: More secure (no unchecked certificates) but can disrupt logins if the OCSP responder is unreachable. - **Fail-Open (`X509_OCSP_FAIL_OPEN:true`)**: More forgiving (users still log in if checks fail) but can allow revoked certificates if the OCSP server is down. ::: Values set in both `realmInitEnv` and `realmAuthFlows` are applied only during the initial import of the `uds` Keycloak Realm. Updating these values at runtime will not affect the running Keycloak instance; to apply changes, you must redeploy the Keycloak package. In contrast, values provided in `themeCustomizations.settings` and `realmConfig` are designed to be updated at runtime and do not require redeployment of the Keycloak package. ### Customizing Session and Access Token Timeouts and limits The `SSO_SESSION_IDLE_TIMEOUT` specifies how long a session remains active without user activity, while the `ACCESS_TOKEN_LIFESPAN` defines the validity duration of an access token before it requires refreshing. The `SSO_SESSION_MAX_LIFESPAN` determines the maximum duration a session can remain active, regardless of user activity. To ensure smooth session management, configure the idle timeout to be longer than the access token lifespan (e.g., 10 minutes idle, 5 minutes lifespan) so tokens can be refreshed before the session expires, and ensure the max lifespan is set appropriately (e.g., 8 hours) to enforce session limits. Misalignment, such as setting a longer token lifespan than the idle timeout or not aligning the max lifespan with session requirements, can result in sessions ending unexpectedly or persisting longer than intended. The `SSO_SESSION_MAX_PER_USER` provides a limit on the number of active sessions a user can use. You can specify 0 to allow unlimited sessions per user, or set a specific number to limit concurrent sessions. This is useful for controlling resource usage and ensuring that users do not have an excessive number of active sessions at once. ### OpenTofu Keycloak Client Configuration The UDS Identity Config includes a Keycloak client that can be used by OpenTofu to manage Keycloak resources programmatically. This client is disabled by default for security reasons. :::caution **Critical Security Requirements** 1. **Pre-Deployment Configuration** - **You must configure authentication flows before deploying UDS Core** - UDS Core will apply default authentication flows if not configured first - This is a critical security step to prevent unauthorized access 2. **Deployment Options**: **Option 1: Disable All Flows (Recommended)** This approach starts with maximum security by disabling all authentication methods: ```yaml overrides: keycloak: keycloak: values: - path: realmInitEnv value: OPENTOFU_CLIENT_ENABLED: true - path: realmAuthFlows value: USERNAME_PASSWORD_AUTH_ENABLED: false X509_AUTH_ENABLED: false SOCIAL_AUTH_ENABLED: false OTP_ENABLED: false WEBAUTHN_ENABLED: false X509_MFA_ENABLED: false ``` This is the most secure approach but requires OpenTofu to enable specific authentication methods after deployment. **Option 2: Configure Final Flows Upfront** If you know your exact authentication requirements, you can configure them directly. For example, to enable Username/Password + OTP authentication only: ```yaml overrides: keycloak: keycloak: values: - path: realmInitEnv value: OPENTOFU_CLIENT_ENABLED: true - path: realmAuthFlows value: USERNAME_PASSWORD_AUTH_ENABLED: true X509_AUTH_ENABLED: false SOCIAL_AUTH_ENABLED: false OTP_ENABLED: true WEBAUTHN_ENABLED: false X509_MFA_ENABLED: false ``` This approach is simpler initially but may require manual steps if your requirements change. 3. **Security Considerations** - The `uds-opentofu-client` has elevated permissions - protect its credentials - Never modify or delete the `uds-operator` clients as they are critical for system operation - Monitor authentication logs after deployment for any unexpected access attempts 4. **Verification** - Test authentication in a non-production environment first - For detailed information on available authentication flows, see [Authentication Flow Documentation](/reference/uds-core/idam/authentication-flows) ::: #### OpenTofu Provider Configuration To use the OpenTofu Keycloak client, you'll need to configure the [Keycloak provider](https://registry.terraform.io/providers/keycloak/keycloak/latest/docs) to use the OpenTofu client's `Client Secret`. The OpenTofu Keycloak client's secret can be retrieved via the Admin UI, navigate to the `UDS` Realm and select the `Clients` tab from the left sidebar, select the `uds-opentofu-client`, and click the `Credentials` tab to copy the secret value. Here's an example configuration that would create a new client called `example-client`: ```hcl terraform { required_providers { keycloak = { source = "keycloak/keycloak" version = "5.5.0" } } required_version = ">= 1.0.0" } variable "keycloak_client_secret" { type = string description = "Client secret for the Keycloak provider" sensitive = true } provider "keycloak" { client_id = "uds-opentofu-client" client_secret = var.keycloak_client_secret url = "https://keycloak.admin.uds.dev" realm = "uds" } # Create a new group in Keycloak resource "keycloak_group" "example_group" { realm_id = "uds" name = "example-group" # Optional attributes attributes = { description = "Example group created via Terraform" created_by = "terraform" } } # Create a nested group under example-group resource "keycloak_group" "nested_group" { realm_id = "uds" name = "nested-example-group" parent_id = keycloak_group.example_group.id # This makes it a child of example-group attributes = { description = "Nested group under example-group" created_by = "terraform" } lifecycle { prevent_destroy = false # Set to true in production after testing } } # Output the group IDs for reference output "example_group_id" { value = keycloak_group.example_group.id description = "The ID of the example group" } output "nested_group_id" { value = keycloak_group.nested_group.id description = "The ID of the nested group" } ``` :::note **Security Note:** Passing sensitive values (such as `keycloak_client_secret`) via command line arguments can expose secrets in shell history and process lists. Instead, use a `.tfvars` file (e.g., `secrets.auto.tfvars`) to securely provide sensitive variables to Tofu. ::: Create a file named `secrets.auto.tfvars` with the following content: ```hcl keycloak_client_secret = "your-actual-client-secret-here" ``` Then run Tofu without passing the secret on the command line: ```bash # Use this tofu command to plan the Tofu tofu plan # Use this tofu command to apply the Tofu tofu apply -auto-approve ``` #### Enabling the OpenTofu Client via Keycloak Admin UI If you need to enable the OpenTofu client after deployment or verify its configuration, follow these steps in the Keycloak Admin Console: 1. **Log in to Keycloak Admin Console** - Navigate to your Keycloak admin URL (typically `https:///admin/`) - Log in with administrative credentials - **Important**: Ensure you're in the `UDS` realm (not the `master` realm) - In the left sidecar, select `Manage Realms` - Select `uds` from the `Manage Realms` page 2. **Enable the Tofu Client** - In the left sidebar, click on "Clients" - Find the `uds-opentofu-client` client - Click on the client to open its settings - Toggle the "Enabled" switch to ON in the top right of the page - Click "Save" at the bottom of the page #### Configure OpenTofu Client via Keycloak Admin UI If you need to setup the OpenTofu client manually, the following steps will provide the steps to do this: 1. **Log in to Keycloak Admin Console** - Navigate to your Keycloak admin URL (typically `https:///admin/`) - Log in with administrative credentials - **Important**: Ensure you're in the `UDS` realm (not the `master` realm) - In the left sidecar, select `Manage Realms` - Select `uds` from the `Manage Realms` page 2. **Create new Client** - In the left sidebar, click on "Clients" - Click `Create client` - `Client ID` = `uds-opentofu-client` - `Name` = `uds-opentofu-client` - `Description` = `A client used for managing Keycloak via Tofu` - Click `Next` - Enable `Client authentication` - Disable `Standard flow` - Enable `Service account roles` - Click `Next` - Click `Save` - Click `Service account roles` - Click `Assign role` - Select `Client Roles` - Seach for `realm-admin` and check the box - `Assign` - Click `Credentials` - Copy the `Client Secret` and start applying Tofu ----- # Integration Testing ## Integration Testing For UDS Identity Config + UDS Core [Cypress Web Flow/Integration Testing Docs](https://docs.cypress.io/guides/overview/why-cypress) ## Implemented Tests | Test Name (link) | Test Description | |------------------|------------------| | [Login Existing User](https://github.com/defenseunicorns/uds-identity-config/blob/main/src/test/cypress/e2e/login.cy.ts) | Login in existing user that is created in the testing [realm.json](https://github.com/defenseunicorns/uds-identity-config/blob/main/src/test/cypress/realm.json5) | | [Login Nonexistant User / Incorrect creds](https://github.com/defenseunicorns/uds-identity-config/blob/main/src/test/cypress/e2e/login.cy.ts) | User cannot login / authenticate with incorrect creds or without account | | [Successfuly CAC Registration](https://github.com/defenseunicorns/uds-identity-config/blob/main/src/test/cypress/e2e/registration.cy.ts) | New user can successfully register with CAC | | [CAC User Login](https://github.com/defenseunicorns/uds-identity-config/blob/main/src/test/cypress/e2e/registration.cy.ts) | New user can successfully login with CAC | | [Duplicate User Registration](https://github.com/defenseunicorns/uds-identity-config/blob/main/src/test/cypress/e2e/registration.cy.ts) | User cannot register more than once | | [Password check for special characters](https://github.com/defenseunicorns/uds-identity-config/blob/main/src/test/cypress/e2e/registration.cy.ts) | User registration requires password special characters | | [Password check for length](https://github.com/defenseunicorns/uds-identity-config/blob/main/src/test/cypress/e2e/registration.cy.ts) | User registration requires password length check | | [Group Authorization](https://github.com/defenseunicorns/uds-identity-config/blob/main/src/test/cypress/e2e/group-authz.cy.ts) | Grafana is deployed to required admin group to authorize | ## Cypress Testing Using uds-cli task [`uds-core-integration-tests`](https://github.com/defenseunicorns/uds-identity-config/blob/main/tasks.yaml). Task explanation: - Cleanup an existing uds-core directory ( mainly for local testing ) - Create docker image that uses the new certs - Clone [`uds-core`](https://github.com/defenseunicorns/uds-core) necessary for setting up k3d cluster to test against - Use that cacert in deploying `uds-core` [istio gateways](https://github.com/defenseunicorns/uds-core/tree/main/src/istio/values) - Create zarf package that combines uds-core and identity-config - Setup k3d cluster by utilizing `uds-core` (istio, keycloak, pepr, zarf) - Deploy zarf package that was created earlier - Run cypress tests against deployed cluster ## Updating Cypress Certs Cypress testing requires that a ca.cer be created and put into an authorized_certs.zip, done by using the `regenerate-test-pki` uds task, which is then utilized by the [Dockerfile](https://github.com/defenseunicorns/uds-identity-config/blob/main/src/Dockerfile). Once a docker image has been created another command is used for pulling that cacert, uds task `cacert`, from the image using it's value to configure uds-core's gateways, `uds-core-gateway-cacert` uds task . Eventually cypress will require a [pfx cert](https://github.com/defenseunicorns/uds-identity-config/blob/main/src/test/cypress/cypress.config.ts) for its CAC testing. Our cypress testing utilizes [static certs](https://github.com/defenseunicorns/uds-identity-config/tree/main/src/test/cypress/certs) that are created and saved to limit the need for constantly rebuilding and importing those certs. Follow these steps to update the certs for cypress: 1. Run `uds run regenerate-test-pki` to regenerate the necessary certs and authorized_certs.zip 2. Run `docker build --build-arg CA_ZIP_URL="authorized_certs.zip" -t uds-core-config:keycloak --no-cache src` to create docker image 3. Run `uds run dev-cacert` to extract cacert from docker image for the tls_cacert.yaml file 4. Copy the authorized_certs.zip, test.pfx, and tls_cacert.yaml into the [certs directory](https://github.com/defenseunicorns/uds-identity-config/tree/main/src/test/cypress/certs) - `mv test.pfx tls_cacert.yaml src/authorized_certs.zip src/test/cypress/certs` 5. Will need to add license headers to generated `tls_cacert.yaml` to pass linting ----- # Custom Keycloak Plugins > This documentation discusses the Keycloak plugin and the additional logic it provides. A Keycloak plugin provides additional custom logic to our Keycloak deployment. Below is a table of the current implemented Custom Keycloak Implementations and how to interact with them. ## Current Custom Implementations | Name | Type | Description | |------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | [Group Authentication](https://github.com/defenseunicorns/uds-identity-config/blob/main/src/plugin/src/main/java/com/defenseunicorns/uds/keycloak/plugin/authentication/RequireGroupAuthenticator.java) | [Authenticator](https://www.keycloak.org/docs-api/latest/javadocs/org/keycloak/authentication/Authenticator.html) | Requires Keycloak group membership to access an application. Controls when Terms and Conditions are displayed. [More info](https://github.com/defenseunicorns/uds-core/blob/v0.23.0/docs/configuration/uds-operator.md?plain=1#L23-L26) and [E2E test](https://github.com/defenseunicorns/uds-identity-config/blob/v0.5.2/src/test/cypress/e2e/group-authz.cy.ts). | | [Register Event Listener](https://github.com/defenseunicorns/uds-identity-config/blob/main/src/plugin/src/main/java/com/defenseunicorns/uds/keycloak/plugin/eventListeners/RegisterEventListenerProvider.java) | [EventListener](https://www.keycloak.org/docs-api/latest/javadocs/org/keycloak/events/EventListenerProvider.html) | Generates a unique `mattermostId` for each user during registration. [E2E test](https://github.com/defenseunicorns/uds-identity-config/blob/v0.5.2/src/test/cypress/e2e/registration.cy.ts#L49-L61). | | [JSON Log Event Listener](https://github.com/defenseunicorns/uds-identity-config/blob/main/src/plugin/src/main/java/com/defenseunicorns/uds/keycloak/plugin/eventListeners/JSONLogEventListenerProvider.java) | [EventListener](https://www.keycloak.org/docs-api/latest/javadocs/org/keycloak/events/EventListenerProvider.html) | Converts Keycloak event logs into JSON strings for logging applications like Grafana. | | [User Group Path Mapper](https://github.com/defenseunicorns/uds-identity-config/blob/main/src/plugin/src/main/java/com/defenseunicorns/uds/keycloak/plugin/CustomGroupPathMapper.java) | [OpenID Mapper](https://www.keycloak.org/docs-api/latest/javadocs/org/keycloak/protocol/oidc/mappers/AbstractOIDCProtocolMapper.html) | Removes leading slash from group names and creates a new `bare-groups` claim. | | [User AWS SAML Group Mapper](https://github.com/defenseunicorns/uds-identity-config/blob/main/src/plugin/src/main/java/com/defenseunicorns/uds/keycloak/plugin/CustomAWSSAMLGroupMapper.java) | [SAML Mapper](https://www.keycloak.org/docs-api/latest/javadocs/org/keycloak/protocol/saml/mappers/AbstractSAMLProtocolMapper.html) | Filters user groups to include only those with `-aws-` and concatenates them into a colon-separated string for SAML attribute. | | [Custom AWS SAML Attribute Mapper](https://github.com/defenseunicorns/uds-identity-config/blob/main/src/plugin/src/main/java/com/defenseunicorns/uds/keycloak/plugin/CustomAWSSAMLAttributeMapper.java) | [SAML Mapper](https://www.keycloak.org/docs-api/latest/javadocs/org/keycloak/protocol/saml/mappers/AbstractSAMLProtocolMapper.html) | Maps user and group attributes to AWS SAML PrincipalTag attributes with colon-separated values when multiple attribute values exist. Aggregates attributes from user profile and all user's groups (including parent groups). | [ClientIdAndKubernetesSecretAuthenticator](https://github.com/defenseunicorns/uds-identity-config/blob/main/src/plugin/src/main/java/com/defenseunicorns/uds/keycloak/plugin/authentication/authenticators/client/ClientIdAndKubernetesSecretAuthenticator.java) | [ClientAuthenticator](https://www.keycloak.org/docs-api/latest/javadocs/org/keycloak/authentication/ClientAuthenticator.html) | Authenticates a client using a Kubernetes secret. Used in the `ClientIdAndKubernetesSecret` authentication flow. | | [UDSClientPolicyPermissionsExecutor](https://github.com/defenseunicorns/uds-identity-config/blob/main/src/plugin/src/main/java/com/defenseunicorns/uds/keycloak/plugin/clientpolicy/executor/UDSClientPolicyPermissionsExecutor.java) | [ClientPolicyExecutorProvider](https://www.keycloak.org/docs-api/latest/javadocs/org/keycloak/clientpolicy/executor/ClientPolicyExecutorProvider.html) | Checks if a client has the necessary permissions to access a resource. Used in the `UDSClientPolicyPermissions` client policy. | ### Security hardening The UDS Keycloak Plugin leverages [Keycloak Client Policies](https://www.keycloak.org/docs/latest/server_admin/index.html#_client_policies) to enforce security hardening for clients created by the UDS Operator. The configuration can be accessed under "Realm Settings" > "Client Policies" > "UDS Client Profile" > "uds-operator-permissions" and includes the following options: * `Additional Allowed Protocol Mappers` - Specifies additional Protocol Mappers permitted for use by the packages. * `Use UDS Default Allowed Protocol Mappers` - When enabled, applies a predefined list of Protocol Mappers. Additional Protocol Mappers can be added using the `Additional Allowed Protocol Mappers` option. * `Additional Allowed Client Scopes` - Specifies additional Client Scopes permitted for use by the packages. * `Use UDS Default Client Scopes` - When enabled, applies a predefined list of Client Scopes. Additional Client Scopes can be added using the `Additional Allowed Client Scopes` option. Additional Protocol Mappers and Client Scopes can be specified declaratively using the following overrides: ```yaml overrides: keycloak: keycloak: values: - path: realmInitEnv value: SECURITY_HARDENING_ADDITIONAL_PROTOCOL_MAPPERS: "oidc-hardcoded-claim-mapper, saml-hardcode-attribute-mapper" SECURITY_HARDENING_ADDITIONAL_CLIENT_SCOPES: "role_list" ``` ### Terms and Conditions behavior The [Group Authentication](https://github.com/defenseunicorns/uds-identity-config/blob/main/src/plugin/src/main/java/com/defenseunicorns/uds/keycloak/plugin/authentication/RequireGroupAuthenticator.java) plugin controls when the Terms and Conditions are displayed to the user. By default, users are required to accept the Terms and Conditions once per session, meaning that if a user logs in with multiple Keycloak Clients, the Terms and Conditions are displayed only once. This behavior can be modified by adjusting the Authentication Flows in the Keycloak Admin Console and changing the "UDS Operator Group Authentication Validation" step settings. The plugin allows UDS Administrators to change the "Display Terms and Conditions only per user session" setting. Setting it to "false" will force users to accept the Terms and Conditions every time they log in. ### Warnings :::note When creating a user via ADMIN API or ADMIN UI, the `REGISTER` event is not triggered, resulting in no Mattermost ID attribute generation. This will need to be done manually via click ops or the api. An example of how the attribute can be set via api can be seen [here](https://github.com/defenseunicorns/uds-common/blob/b2e8b25930c953ef893e7c787fe350f0d8679ee2/tasks/setup.yaml#L46). ::: :::caution Please use this scope only if you understand the implications of excluding full path information from group data. It is highly important to not use the `bare-groups` claim for protecting an application due to security vulnerabilities. ::: ## Requirements Working on the plugin requires JDK17+ and Maven 3.5+. ```bash # local java version java -version # loval maven version mvn -version ``` ## Plugin Testing with Keycloak After making changes to the plugin code and verifying that unit tests are passing ( and hopefully writing some more ), test against Keycloak. See the `New uds-identity-config Image` [section](/reference/uds-core/idam/testing-deployment-customizations/#build-a-new-image) for building, publishing, and using the new image with `uds-core`. ## Plugin Unit Testing / Code Coverage The maven surefire and jacoco plugins are configured in the [pom.xml](https://github.com/defenseunicorns/uds-identity-config/blob/main/src/plugin/pom.xml). :::note `mvn` commands will need to be executed from inside of the `src/plugin` directory ::: :::note There is a uds-cli task for running the `mvn clean verify` command: `uds run dev-plugin`. ::: Some important commands that can be used when developing/testing on the plugin: |Command|Description| |-------|-----------| | `mvn clean install` | Cleans up build artifacts and then builds and installs project into local maven repository. | | `mvn clean test` | Cleans up build artifacts and then compiles the source code and runs all tests in the project. | | `mvn clean test -Dtest=com.defenseunicorns.uds.keycloak.plugin.X509ToolsTest` | Same as `mvn clean test` but instead of running all tests in project, only runs the tests in designated file. | | `mvn surefire-report:report` | This command will run the `mvn clean test` and then generate the surefire-report.html file in `target/site` | | `mvn clean verify` | Clean project, run tests, and generate both surefire and jacoco reports | ### Viewing the Test Reports ```bash # maven command from src/plugin directory mvn clean verify ``` Open the `src/plugin/target/site/surefire-report.html` file in your browser to view the surefire test report. Open the `src/plugin/target/site/jacoco/index.html` file in your browser to view the unit test coverage report generated by jacoco. Both reports will hot reload each time they are regenerated, no need to open each time. ## New Custom Plugin Development :::caution This isn't recommended, however can be achieved if necessary ::: :::note Making these changes iteratively and importing into Keycloak to create a new realm can help to alleviate typo's and mis-configurations. This is also the quickest solution for testing without having to create,build,deploy with new images each time. ::: The plugin provides the auth flows that keycloak uses for x509 (CAC) authentication as well as some of the surrounding registration flows. One nuanced auth flow is the creation of a Mattermost ID attribute for users. [CustomEventListener](https://github.com/defenseunicorns/uds-identity-config/blob/main/src/plugin/src/main/java/com/defenseunicorns/uds/keycloak/plugin/eventListeners/RegisterEventListenerProvider.java) is responsible for generating the unique ID. :::note When creating a user via ADMIN API or ADMIN UI, the 'REGISTER' event is not triggered, resulting in no Mattermost ID attribute generation. This will need to be done manually via click ops or the api. An example of how the attribute can be set via api can be seen [here](https://github.com/defenseunicorns/uds-common/blob/b2e8b25930c953ef893e7c787fe350f0d8679ee2/tasks/setup.yaml#L46). ::: ### Configuration In addition, modify the realm for keycloak, otherwise the realm will require plugin capabilities for registering and authenticating users. In the current [realm.json](https://github.com/defenseunicorns/uds-identity-config/blob/main/src/realm.json) there is a few sections specifically using the plugin capabilities. Here is the following changes necessary: * Remove all of the `UDS ...` authenticationFlows: * `UDS Authentication` * `UDS Authentication Browser - Conditional OTP` * `UDS Registration` * `UDS Reset Credentials` * `UDS registration form` * `UDS Client Credentials` * Make changes to authenticationExecutions from the `browser` authenticationFlow: * Remove `auth-cookie` * Remove `auth-spnego` * Remove `identity-provider-redirector` * Update the remaining authenticationFlow * `"requirement": "REQUIRED"` * `"flowAlias": "Authentication"` * Remove `registration-profile-action` authenticationExecution from the `registration form` authenticationFlow * Update the realm flows: * `"browserFlow": "browser"` * `"registrationFlow": "registration"` * `"resetCredentialsFlow": "reset credentials"` * `"clientAuthenticationFlow": "clients"` ### Disabling If desired the Plugin can be removed from the identity-config image by commenting out these lines in the [Dockerfile](https://github.com/defenseunicorns/uds-identity-config/blob/main/src/Dockerfile): ```bash COPY plugin/pom.xml . COPY plugin/src ../src RUN mvn clean package ``` ----- # Testing and Deployment Customizations ## Image Management This document provides comprehensive guidelines for managing custom images within the UDS Core system, from creation and testing to deployment and transportation, particularly in restricted environments like air-gapped systems. ### Building and Testing Custom Images #### Build a new image Build a custom development image for UDS Core using the following commands: ```bash # create a dev image uds-core-config:keycloak uds run dev-build # optionally, retag and publish to temporary registry for testing docker tag uds-core-config:keycloak ttl.sh/uds-core-config:keycloak docker push ttl.sh/uds-core-config:keycloak ``` #### Update UDS Core references Update the custom image references in the `uds-core` repository: * Update zarf.yaml to include updated image. * Specify configImage in Keycloak values.yaml. * For truststore updates, see gateway configuration instructions. Alternatively, to override the existing Identity-Config image found in the Keycloak [values.yaml](https://github.com/defenseunicorns/uds-core/blob/main/src/keycloak/chart/values.yaml), use the following: ```yaml overrides: keycloak: keycloak: values: - path: configImage value: ttl.sh/uds-core-config:keycloak ``` #### Deploy UDS Core Deploy UDS Core with the new custom image: ```bash # build and deploy uds-core uds run test-uds-core ``` See [UDS Core](https://github.com/defenseunicorns/uds-core/blob/main/README.md) for further details ## Building New Image with Updates For convenience, a Zarf package definition has been included to simplify custom image transport and install in air-gapped systems. Use the included UDS task to build the custom image and package it with Zarf: ```bash uds run build-zarf-pkg ``` ----- # Truststore Customization ## Customizing Truststore The default truststore is configured in a [script](https://github.com/defenseunicorns/uds-identity-config/blob/main/src/truststore/ca-to-jks.sh) and excuted in the [Dockerfile](https://github.com/defenseunicorns/uds-identity-config/blob/main/src/Dockerfile). There is a few different ways the script could be customized. * [Change where the DoD CA zip file are pulled from.](https://github.com/defenseunicorns/uds-identity-config/blob/main/src/Dockerfile#L31), defualting to DOD UNCLASS certs but could be updated for local or another source. * [Change the Regex Exclusion Filter](https://github.com/defenseunicorns/uds-identity-config/blob/main/src/Dockerfile#30), used by the ca-to-jks script to exclude certain certs from being added to the final truststore. * [Change the truststore password](https://github.com/defenseunicorns/uds-identity-config/blob/main/src/truststore/ca-to-jks.sh#L29) ### Build test `authorized_certs.zip` Utilizing the [`regenerate-test-pki` task](https://github.com/defenseunicorns/uds-identity-config/blob/main/tasks.yaml), you can create a test `authorized_certs.zip` to use for the truststore. To use the `regenerate-test-pki` task: * Create `csr.conf` ```bash [req] default_bits = 2048 default_keyfile = key.pem distinguished_name = req_distinguished_name req_extensions = req_ext x509_extensions = v3_ext [req_distinguished_name] countryName = Country Name (2 letter code) countryName_default = US stateOrProvinceName = State or Province Name (full name) stateOrProvinceName_default = Colorado localityName = Locality Name (eg, city) localityName_default = Colorado Springs organizationName = Organization Name (eg, company) organizationName_default = Defense Unicorns commonName = Common Name (e.g. server FQDN or YOUR name) commonName_default = uds.dev [req_ext] subjectAltName = @alt_names [v3_ext] subjectAltName = @alt_names [alt_names] DNS.0 = *.uds.dev ``` * ```bash # Generates new authorized_certs.zip uds run regenerate-test-pki ``` ### Update Dockerfile and build image Update `CA_ZIP_URL` in [Dockerfile](https://github.com/defenseunicorns/uds-identity-config/blob/main/src/Dockerfile) to refer to the generated `authorized_certs.zip` ```bash ARG CA_ZIP_URL=authorized_certs.zip ``` Build config image ```bash # build image uds run dev-build ``` :::note If you're getting errors from the ca-to-jks.sh script, verify your zip folder is in the correct directory. ::: ### Configure Istio Gateways CACERT in UDS Core In order to ensure your client certs are requested when deploying UDS Core you will need to override the `tls.cacert` value for the gateway(s) where you expect client certs to be provided. A values file can be generated from your local image build using the `dev-cacert` task: ```bash uds run dev-cacert ``` This task can also be modified locally to point to a different image if you have published a custom build somewhere else. The output of this task will be a values file locally, `tls_cacert.yaml`, that can be used in your bundle or copied out as needed. ### Deploy UDS Core with new uds-identity-config See [Testing custom image in UDS Core](/reference/uds-core/idam/testing-deployment-customizations/) ### Verify Istio Gateway configuration ```bash # Verify the "Acceptable client certificate CA names" openssl s_client -connect sso.uds.dev:443 ``` ----- # Overview ## What is IdAM? Identity and Access Management (IdAM) refers to a framework of policies and technologies that ensure the proper people in an enterprise have the appropriate access to technology resources. IdAM systems provide tools and technologies for controlling user access to critical information within an organization through a set of business processes and by managing identities and access rights. The technology typically helps IT managers control user access to critical information within an organization by using a digital identity—which is considered unique in the system—and setting up roles, permissions, and policies. IdAM solutions ensure that users are who they claim to be (authentication) and that they can access the applications and resources they are allowed to use (authorization). ## What is UDS Identity Config? UDS Identity Config is a component of the UDS Core that supplies the necessary configuration for Keycloak, an open-source Identity and Access Management solution. This configuration includes setting up realms, clients, roles, and other Keycloak settings tailored specifically for the UDS environment. By managing these configurations, UDS Identity Config facilitates the seamless integration of authentication and authorization functionalities into various services within the UDS ecosystem, ensuring that security protocols are consistently applied across platforms. ### Main Responsibilities UDS Identity Config is responsible for managing several key aspects of Keycloak’s configuration within the UDS ecosystem, including: 1. Realm Configuration – Defines realms, clients, roles, and authentication flows. 2. Theme Configuration – Manages custom branding and UI elements for authentication pages. 3. Truststore Management – Ensures secure communication by handling trusted certificates and keys. 4. Custom Plugins – Supports additional functionality through custom Keycloak extensions and providers. ### Air-Gapped Limitations When Keycloak is configured for X.509 certificate authentication and OCSP checking (x509-cert-auth.ocsp-checking-enabled) is enabled, it attempts to contact the OCSP responder specified in the certificate or a manually configured URL. In air-gapped or otherwise restricted environments, this external endpoint may be unreachable. See this [bundle override](/reference/uds-core/idam/customization/#templated-realm-values) for an example of disabling OCSP checking but note the risks of doing so. By allowing certificates to pass when the revocation check fails, the door is open to revoked certificates being considered valid, which can pose a serious security threat depending on your organization’s compliance requirements and threat model. ### FIPS Mode UDS Core supports running Keycloak in [FIPS 140-2 Strict Mode](https://www.keycloak.org/server/fips) by enabling the `fips` Helm Chart override. When set to `true`, the UDS Identity Config Init Container automatically copies the required Bouncy Castle JAR files into the Keycloak Providers directory. To verify that FIPS mode is active, set the `debugMode` Helm Chart override to `true` and review the Keycloak bootstrap logs. Look for the following line: ```bash KC(BCFIPS version 2.0 Approved Mode, FIPS-JVM: disabled) ``` The `BCFIPS version 2.0 Approved Mode` confirms that Keycloak is operating in FIPS Strict Mode. The `FIPS-JVM` setting indicates whether the underlying JVM is also running in FIPS mode. If this setting is disabled, it likely means the Keycloak container is not hosted on a system with a FIPS-enabled kernel. :::caution If you're planning on migrating to FIPS mode, please ensure you followed [Upgrading Identity Config Versions](/reference/uds-core/idam/upgrading-versions/) guide. Otherwise, you might lock yourself out of the Keycloak admin console. ::: ### Upgrading UDS Identity Config When upgrading UDS Identity Config, changes to the realm configuration do not propagate automatically. This is because Keycloak persists its realm settings across upgrades to prevent breaking existing functionality. To apply updates to the realm configuration, follow the manual steps outlined in [Upgrading Identity Config Versions](/reference/uds-core/idam/upgrading-versions/) . However, updates to the following components are automatically applied upon upgrade, as they are not persisted between versions: - Themes (branding and UI customizations) - Truststore (certificate and key management) - Custom Plugins (additional Keycloak extensions) This ensures that realm configurations remain unchanged during upgrades, while other non-persistent settings are automatically refreshed. ## IdAM Contents 1. [Custom Image Testing and Deployment](/reference/uds-core/idam/testing-deployment-customizations/) 2. [Image Customizations](/reference/uds-core/idam/customization/) 3. [Image Truststore Customization](/reference/uds-core/idam/truststore-customization/) 4. [Authentication Flows Customization](/reference/uds-core/idam/authentication-flows/) 5. [UDS Core Integration Testing](/reference/uds-core/idam/integration/) 6. [Custom Keycloak Plugins](/reference/uds-core/idam/plugin/) 7. [Upgrading Identity Config Versions](/reference/uds-core/idam/upgrading-versions/) ----- # Upgrading Versions This doc contains important information for upgrading uds-identity-config versions. It is not meant to be an exhaustive list of changes between versions, rather information and steps required to manually upgrade versions without a full redeploy of keycloak. ## v0.23.0+
Upgrade Details Keycloak 26.5.0 introduced a logout confirmation capability (see [Keycloak #44463](https://github.com/keycloak/keycloak/pull/44463)) that is enabled by default in UDS Core. To update the default Keycloak clients to add this option, follow these steps: - Navigate to the `UDS` realm - Go to `Clients` > `account` - Find the `Logout confirmation` option and set it to `On` - Click `Save` - Repeat these steps for the `account-console` and `security-admin-console` clients
## v0.19.0+
Upgrade Details Keycloak 26.4.0 introduced a breaking change to the ServerInfo endpoint and does not render SystemInfo without additional permissions. This change will cause OpenTofu to fail with a "Malformed version" (see [Keycloak Terraform Provider #1342](https://github.com/keycloak/terraform-provider-keycloak/issues/1342#issuecomment-3398650912)). In order to resolve the issue, you need to perform the following steps: - Navigate to the `UDS` realm - Go to `Clients` > `realm-management` > `Client Roles` > `Roles` and click `Create Role` - Use `view-system` as the Role Name and `Enables displaying SystemInfo through the ServerInfo endpoint` for the Description and click `Save` - Go back to the `realm-management` Roles by clicking the `Client details` breadcrumb and find the `realm-admin` Role. Click on it - Go to `Associated roles` tab and click `Assign role` > `Client Roles` - Find the `view-system` role you created earlier, select it and click `Assign`
## v0.17.0
Upgrade Details UDS Identity Config introduced the OpenTofu client that can be used for managing Keycloak with OpenTofu. This new client is included in the realm.json, however if unable to re-initialize Keycloak in UDS Core you can find steps [here to manually configure the OpenTofu client](/reference/uds-core/idam/customization#configure-opentofu-client-via-keycloak-admin-ui). UDS Core v0.51.0 introduced a mechanism to limit the number of concurrent SSO sessions per user in the UDS Realm. To manually configure this: - Navigate to the `UDS` realm - Go to `Authentication` > `Flows` > `UDS Authentication` - Click `Add execution` - Select `User Session Count Limiter` : - Select the gear icon next to the new `User Session Count Limiter` to configure the following: - `Maximum concurrent sessions for each user within this realm`: Set to the desired maximum number of concurrent sessions per user. The value should be the same as the `SSO_SESSION_MAX_PER_USER` value in the `realmInitEnv`.
## v0.14.1+
Upgrade Details UDS Core v0.42.0 switched Keycloak to run in Ambient Mode. In some cases, specifically in AWS environment that uses “Shared Address Space” (see RFC6598), this may result in HTTP 403 errors. In order to resolve this, uds-identity-config v0.14.1 requires setting "Require SSL" option to "None". To manually configure this: - Navigate to the `UDS` realm - Go to `Realm Settings` > `General` tab - Switch `Require SSL` to `None`
## v0.14.0+
Upgrade Details In uds-identity-config versions v0.14.0+, the UDS Identity Config has removed `Dynamic Client Registration`. Part of this means that we need to remove a couple of the `Trusted Hosts` configured in uds-identity-config. To manually configure this: - Navigate to the `UDS` realm (be aware that in KC v26.2 the UI/UX of navigating realms has changed) - Go to `Clients` > `Client Registration` > `Trusted Hosts` - Remove the following Trusted Hosts: - `*.keycloak.svc.cluster.local` - `*.pepr-uds-core-watcher.pepr-system.svc.cluster.local` - `127.0.0.6` - Click the `Save` button - Go to `Clients` > `Client Registration` - Click `Create client policy` - Click the `max-clients` option - Name the `max-clients` policy `max number of clients` - Set `Max Clients Per Realm` to `0` - Click the `Save` button UDS Core v0.41.0+ resolves a critical issue with enabling FIPS mode in Keycloak. Previously, due to missing Bouncy Castle FIPS libraries, Keycloak would start in normal mode without FIPS restrictions. Enabling FIPS mode introduces two significant changes: * Passwords must be at least 14 characters long. Keycloak will reject shorter passwords, including database credentials and user passwords. * The `argon2` hashing algorithm is unavailable in FIPS mode. Existing systems must first migrate to the `pbkdf2-sha512` algorithm for hashing user credentials before enabling FIPS mode in the `master` realm. Failing to do so will lock the administrator password. To prevent locking the administrator password, follow these steps: - Log in to Keycloak with the administrator account (you may need to use `uds zarf connect keycloak`). - In the `master` Realm, navigate to `Authentication` > `Policies` > `Password Policy` and click `Add Policy`. - Select `Hashing Algorithm` and enter `pbkdf2-sha512`. - Click `Save`. - Go to `Users` and select your administrator account. - Open the `Credentials` tab and click `Reset Password`. - Enter a new password of at least 14 characters. You can reuse your existing password if desired. - Set `Temporary` to `Off` and click `Save`. - Return to your user's details, open the `Credentials` tab, and click `Show data`. Ensure the `algorithm` is set to `pbkdf2-sha512`. - You are now ready to enable FIPS mode in Keycloak. For more details on FIPS limitations, refer to the [Keycloak FIPS 140-2 support](https://www.keycloak.org/server/fips) page.
## v0.11.0+
Upgrade Details In uds-identity-config versions v0.11.0+, the UDS Operator can automatically switch to Client Credentials Grant from using the Dynamic Client Registration. The new method works faster, is more reliable and doesn't require storing Registration Tokens in the Pepr Store. It is highly recommended to switch to it, which requires the following steps: - Create the `uds-operator` Client: - Go to `Clients` > `Create` - Client type: `openid-connect` - Client ID: `uds-operator` - Client Name: `uds-operator` - Click `Next` - Client authentication: on - Uncheck all Authentications flows except from `Service account roles` - Click `Next` - Click `Save` - Go to `Clients` > `uds-operator` > `Credentials` tab - Set `Client Authenticator` to `Client Id and Kubernetes Secret` - Click `Save` - Go to `Clients` > `uds-operator` > `Service accounts roles` tab - Should see the Role `default-roles-uds` > click the three dots on the right and `unassign` > `Remove` - Click `Assign role` - Make sure the filter is on `Filter by clients` - Check the box next to `realm-management: manage-clients` - Click `Assign` - Configure the UDS Client Policy - Go to `Realm Settings` > `Client Policies` > `Profiles` - Click `Create Client Profile` - Name: `uds-client-profile` - Description: `UDS Client Profile` - Click `Save` - Click `Add Executor` - Select `uds-operator-permissions` - Click `Add` - Go to `Realm Settings` > `Client Policies` > `Policies` - Click `Create client policy` - Name: `uds-client-policy` - Description: `UDS Client Policy` - Click `Save` - Click `Add condition` - Select `any-client` - Click `Add` - Click `Add client profile` - Select `uds-client-profile` - Click `Add` (there is a glitch in the UI where it seems all the profiles are selected, but only the selected one is actually chosen) - Configure the Client Credentials Authentication Flow - Go to `Authentication` > `Flows` - Click `clients` - Click `Actions` > `Duplicate` - Name: `UDS Client Credentials` - Description `UDS Client Credentials` - Click `Duplicate` - Go to `Authentication` > `UDS Client Credentials` - Click `Add Step` (pre uds-core v0.40.0) or `Add Execution` (uds-core v0.40.0+) - Select `Client Id and Kubernetes Secret` - Click `Add` - Select `Requirement` and set it to `Alternative` - Go to `Authentication`, select three dots on the right side of the panel for `UDS Client Credentials` and select `Bind flows` - Select `Client authentication flow` - Click `Save` - Verify that everything is configured correctly - Deploy a new uds package or update the existing ones - Check UDS Operator logs and verify if there are no errors - Use `uds zarf tools kubectl logs deploy/pepr-uds-core-watcher -n pepr-system | grep "Client Credentials Keycloak Client is available"` command to verify if the UDS Operator uses the Client Credentials flow. After introducing the changes above, ensure that all packages reconcile correctly and that no errors appear. If the UDS Operator displays the error `The client doesn’t have the created-by=uds-operator attribute. Rejecting request`, disable `UDS Client Policy` and give the system a bit more time to process every package. Some users have reported that they needed to disable `UDS Client Policy`, cycle the Pepr Watcher pod (this will force reconciliation of **all** Packages), wait for all Package CRs to be ready, and finally enable the `UDS Client Policy`. [Additional information if you need to add protocol mappers that UDS Core does not include out of the box.](/reference/uds-core/idam/plugin/#security-hardening) --- In uds-identity-config version 0.11.0 we incorporated some big changes around MFA. - Previous versions didn't allow for MFA on the X509 Authentication flow. Now that can be configured to required additional factors of authentication. By default this is disabled and will need to be enabled. - Additionally, we've added support of WebAuthn MFA. This can assume many different forms such as biometrics, passkeys, etc. This also is disabled by default and is only used as an MFA option. If wanting to configure the MFA everywhere with both OTP and WebAuthn options, the following steps will help to manually configure these options on an upgrade: 1. There is a [new theme for webauthn-authentication](https://github.com/defenseunicorns/uds-identity-config/blob/main/src/theme/login/webauthn-authenticate.ftl) that conditionally removes the register button. This is removed because we assume that since you are doing MFA you have already provided enough details to be identified by Keycloak and don't need to register. 2. The Authentication `Required Actions` have a few changes as well: - Click `Authentication` tab from left side menu - Click `Required Actions` tab from Authentication page menu - Enable the following `Required Actions`, only toggle the `Enabled` **DO NOT TOGGLE** `Set as default action`: - `Configure OTP` - `Webauthn Register` - `Delete Credential` - Disable the `WebAuthn Register Passwordless`, make sure this is **not** the `WebAuthn Register` option ( this one should be enabled ) 3. The `UDS Authentication` authentication flow has undergone significant changes. - Click `Authentication` tab from left side menu - Click `UDS Authentication` flow option - **This can be very dangerous to modify so make sure you know what you're doing before making changes here** - In the `Authentication` top level sub-flow of the `UDS Authentication` flow - Click the `+` icon and add a `sub-flow` - Name that sub-flow `X509 Authentication` - Drag that new sub-flow up and drop below the `Cookie` and the `IDP Redirector` step - Set the flow to `Alternative` - in the new `X509 Authentication` sub-flow select the `+` icon and add a sub-flow called `X509 Conditional OTP` - Set the `X509 Conditional OTP` to `Required` - Click the `+` and add the `Condition` called `Condition - user configured` - set this to be `Required` - Click the `+` and add the step called `OTP Form` - set this to be `Required` - Click the `+` and add the step called `WebAuthn Authenticator` - Drag the existing `X509/Validate Username Form` step into the `X509 Authentication` sub-flow, should be above the `X509 Conditional OTP` - May have to drag this twice, make sure this is `Required` --- To add an `IDP Redirector` option to the `UDS Authentication`, which enables bypassing the login page and jumping directly to the IDP login when using the `kc_idp_hint` URL parameter, do the following steps: - Click `Authentication` from the left sidebar under `Configure` - Select the `UDS Authentication` auth flow - Under the `Authentication` sub-flow in `UDS Authentication`, click the `+` and add a new `sub-flow` - Name that sub-flow `idp redirector` - click `Add` - Drag that new `idp redirector` sub-flow from the bottom of the `Authentication` sub-flow to be directly below the `Cookie` step - Set the `idp redirector` sub-flow to be `Alternative` - Click the `+` on the `idp redirector` sub-flow and add a new step - Select the `Identity Provider Redirector` - Click `Add` - Set that `Identity Provider Redirector` step to `Required`
## v0.10.0+
Upgrade Details In uds-identity-config versions 0.10.0+, the version of Keycloak was upgraded to Keycloak 26.1.0. In this release of Keycloak an unmentioned breaking change that added case sensitivity to the Client SAML Mappers. This resulted in breaking SAML Auth flows due to users IDP data not being correctly mapped into applications ( ex. Sonarqube, Gitlab, etc ). Manual steps to fix this issue: - Click `Client scopes` - For each of the following mappers: - `mapper-saml-email-email` - `mapper-saml-firstname-first_name` - `mapper-saml-lastname-last_name` - `mapper-saml-username-login` - `mapper-saml-username-name` - Select the mapper, should now be on the `Client scope details` page - Select the `Mappers` tab - Select the available mapper - Manually change the `Property` field dropdown to match the designated mapper property - `mapper-saml-email-email` had a value of `Email`, that needs to be changed to select the `email` option from the drop down. - `mapper-saml-firstname-first_name` had a value of `FirstName`, that needs to be changed to select the `firstName` option from the drop down. - `mapper-saml-lastname-last_name` had a value of `LastName`, that needs to be changed to select the `lastName` option from the drop down. - `mapper-saml-username-login` had a value of `Username`, that needs to be changed to select the `username` option from the drop down. - `mapper-saml-username-name` had a value of `Username`, that needs to be changed to select the `username` option from the drop down. - Make sure and click `Save` after updating the property field
## v0.9.1 to v0.10.0
Upgrade Details * For running Istio with Ambient Mesh, it is required to add two new entries to the trusted hosts list: `*.pepr-uds-core-watcher.pepr-system.svc.cluster.local` and `*.keycloak.svc.cluster.local`. This is done automatically for new deployments but when upgrading it is required to perform these extra steps: - Click `Clients` > `Client registration` > `Client details` - Add `*.pepr-uds-core-watcher.pepr-system.svc.cluster.local` and `*.keycloak.svc.cluster.local` to the `Trusted Hosts` list - Click `Save` * Keycloak 26.1.1 introduces a new option to force re-login after resetting credentials ([Keycloak Release Notes](https://www.keycloak.org/docs/latest/release_notes/index.html#new-option-in-send-reset-email-to-force-a-login-after-reset-credentials)). This option has been enabled for new deployments but the existing ones, it needs to be turned on manually: - Click `Authentication` > `UDS Reset Credentials` and find `Send Reset Email` Step of the Authentication Flow. - Click `Settings`, enter a new alias name, for example `reset-credentials-email` and turn the `Force login after reset` option on. - Click `Save`
## v0.5.1 to v0.5.2
Upgrade Details * An custom Keycloak event logger that replaces the default event logger is [included in this release](https://github.com/defenseunicorns/uds-identity-config/blob/v0.5.2/src/realm.json#L1669), if you wish to enable manually as part of an upgrade do the following (in the `Unicorn Delivery Service` realm): - Click on the `Realm Settings` > `Events` and add `jsonlog-event-listener`. - Remove the built in `jboss-logging` event listener. - Click `Save` * The custom registration event listener was [renamed](https://github.com/defenseunicorns/uds-identity-config/blob/v0.5.2/src/realm.json#L1670) from `custom-registration-listener` to `registration-event-listener`. To manually update this event listener (in the `Unicorn Delivery Service` realm): - Click on the `Realm Settings` > `Events` and add `registration-event-listener`. - Remove `custom-registration-listener`. - Click `Save` * An additional scope (`bare-groups`) was included in the uds [realm.json](https://github.com/defenseunicorns/uds-identity-config/blob/v0.5.2/src/realm.json#L1608-L1636). To add this scope manually do the following (in the `Unicorn Delivery Service` realm): - Click on `Client Scopes` > `Create client scope`. - Name the scope `bare-groups`, and configure it to be - Type: `Optional` - Include in token scope: `On` - Click `Save` - Click `Mappers` > `Create a new mapper` - Select `Custom Group Path Mapper` and name it `bare groups` - To enable this scope to be added as a `defaultClientScope` for your clients, navigate to the top level `Clients` > `Client registration` tab. - Click `Allowed Client Scopes` - Add `bare-groups` to the list of `Allowed Client Scopes` - Click `Save`
## v0.5.0 to v0.5.1
Upgrade Details This version upgrade utilizes built in Keycloak functionality for User Managed Attributes. :::note User managed attributes are only available in Keycloak 24+ ::: If upgrading without a full redeploy of keycloak the following changes will be needed: 1. The `realm.json` will need to be updated to contain the correct User Managed Attributes definition, [User Managed Attributes Configuration](https://github.com/defenseunicorns/uds-identity-config/blob/v0.5.1/src/realm.json#L1884-L1895). The following steps can be used to do this with clickops: 1. In `Realm Settings` tab and on the `General` page 1. toggle off `User-managed access` 2. `Unmanaged Attributes` set to `Only administrators can write` 2. On `User profile` page 1. select the `JSON Editor` tab 2. Copy and Paste the value of [the User Attribute Definition from the realm.json](https://github.com/defenseunicorns/uds-identity-config/blob/v0.5.1/src/realm.json#L1891) 3. `Save` 2. Incorporate STIG password rules, in accordance with these two hardening guides: * [Elasticsearch 8.0 Application Server](https://github.com/user-attachments/files/16178987/Elasticsearch.8.0.Hardening.Guide.Application.Server.SRG.V3R1.pdf) * [Elasticsearch 8.0 Central Log Server](https://github.com/user-attachments/files/16178988/Elasticsearch.8.0.Hardening.Guide.Central.Log.Server.SRG.V2R1.pdf) * Changes: 1. Passwords expire in 60 days 2. Passwords complexity: 2 special characters, 1 digit, 1 lowercase, 1 uppercase, and 15 character minimum length 3. IDP session idle timeout is now 10 minutes 4. Maximum login attempts is now 3
## v0.4.5 to v0.5.0
Upgrade Details This version upgrade brings in a new Authentication Flow for group authorization. If upgrading without a full redeploy of keycloak the following steps will be necessary to create and use group authorization: 1. In keycloak admin portal, in `UDS` realm, navigate to `Authentication` sidebar tab 2. In `Authentication` tab add the `Authorization` flow to `UDS Authentication`, `UDS Registration`, `UDS Reset Credentials` 1. In each `Authentication` flow 1. `Add step` -> `UDS Operator Group Authentication Validation` * Make sure that the step is at the base level and bottom of the Authentication flow 3. Finally if using `SAML` IDP 1. In the `Authentication` tab 1. `Create Flow` 2. `Name` -> `Authorization` 3. `Description` -> `UDS Operator Group Authentication Validation` 4. `Basic Flow` 5. `Create` 6. `Add execution` 7. `Add` the `UDS Operator Group Authentication Validation` 2. In the `Identity Providers` tab, select the `SAML` Provider 1. Add the `Authorization` flow to the `Post login flow` in the `Advanced settings` section
----- # Istio Transition and Support Policy This policy outlines the transition of **UDS Core services** from the traditional **Istio sidecar model** to **Istio Ambient Mode**. **Purpose of the transition:** * Lower resource requirements * Simplified operations * Improved latency These benefits are particularly important as UDS expands its **edge capabilities**. --- ## Scope **Applies to:** * All UDS Core services (e.g., logging, monitoring, SSO) * All users deploying apps within UDS-managed environments **Does NOT apply to:** * Applications not managed by UDS Core * Third-party infrastructure not provisioned through UDS tooling --- ## Transition Details | Component | Transition Path | | ------------------------ | ---------------------------------------------------------------------------------------------------------- | | **UDS Core Services** | All Core services use Istio Ambient Mode starting **0.43.0** (sidecar is not an option for Core services). | | **Mission Applications** | Ambient is the **default** mode starting **0.60.0**. Sidecar remains as a supported **opt-in** option. | :::note Mission Application = Any application outside of UDS Core ::: :::note **Existing Deployments** When upgrading to **0.43.0+** UDS Core will auto-transition Core services to Ambient Mode. No opt-out is available. ::: --- ## Support Policy | Deployment Type | Istio Ambient | Istio Sidecar | | ------------------------ | ----------------------- | ---------------------------- | | **UDS Core Services** | Fully supported | Not supported | | **Mission Applications** | Supported & recommended | Supported | | **New Features** | Prioritized for ambient | Evaluated case-by-case | | **Security & Patching** | Provided | Provided (shared components) | | **Deprecation Plan** | Active development | No planned deprecation | --- ## Technical Guidance See this [doc for additional Technical Guidance](https://uds.defenseunicorns.com/reference/configuration/service-mesh/istio-sidecar-vs-ambient/). --- ## Frequently Asked Questions **Q: Do I need to switch my app to Ambient Mode?** **A:** No. Sidecar mode is still supported, but Ambient is recommended. **Q: Will sidecar mode be deprecated for mission apps?** **A:** No. It remains supported. Hybrid mesh (ambient + sidecar) is low-maintenance and will remain supported. **Q: What happens when I update UDS Core?** **A:** UDS Core services will automatically use Ambient Mode. Mission apps are unaffected unless they explicitly opt in. **Q: Will Istio updates still apply to sidecar mode?** **A:** Yes. Istio components are shared and continue to serve both Ambient and Sidecar modes with updates and patches. **Q: Does switching to ambient require replacing Istio?** **A:** No. Ambient is an alternate data plane within Istio. The core control plane remains unchanged. **Q: How can I test or migrate to Ambient Mode?** **A:** By upgrading to 0.43.0+ UDS Core services will automatically migrate to ambient mode. Mission apps can be switched to ambient by opting-in. ----- # Overview import LikeC4View from '@components/LikeC4View.astro'; ## What is UDS Core? {/* @lulaStart babb60a4-d745-426c-ab8e-9527fda629d6 */} UDS Core is a collection of several individual applications combined into a single Zarf Package, that establishes a secure baseline for secure cloud-native systems. It comes equipped with comprehensive compliance documentation and prioritizes seamless support for highly regulated and egress-limited environments. Building upon the achievements of Platform One, UDS Core enhances the security stance introduced by Big Bang. It introduces advanced automation through the UDS Operator and UDS Policy Engine. {/* @lulaEnd babb60a4-d745-426c-ab8e-9527fda629d6 */} UDS Core enables your team to: - Deploy full mission environments and applications efficiently and securely. - Leverage specific functional applications to deliver a versatile platform that caters to diverse mission objectives. - Enhance the efficiency, security, and success of software delivery and operations process. :::note The above diagram captures an overview of the UDS Core architecture, primarily focusing on Kubernetes pod communications and namespace separation. In some cases this diagram omits some more complex connections for the sake of simplicity, for example: - Prometheus scraping is occurring with all available metrics endpoints in the cluster. - All pod communications in Istio ambient mode involve its CNI plugin and the node level Ztunnel proxy (additional information and diagrams of this architecture can be found [upstream](https://istio.io/latest/docs/ambient/architecture/)). ::: ### Accomplishing Mission Objectives with Functional Applications UDS leverages functional applications that are well-suited to perform the specific tasks required. These tools are carefully selected to ensure optimal performance and compatibility within the UDS landscape. By integrating functional tools into the platform, UDS ensures that Mission Heroes have access to cutting-edge technologies and best-in-class solutions for their missions. ### Leveraging UDS Applications Mission Heroes can leverage UDS Core Applications to tailor their mission environment and meet their unique requirements. By selecting and integrating specific tools into their deployments, your team can achieve a streamlined and secure software delivery process. Ranging from setting up a DevSecOps pipeline, enforcing security policies, or managing user identities, UDS Applications provide the necessary tools to accomplish mission objectives effectively. ### UDS Core Dependency A UDS Core dependency refers to the specific prerequisites and external elements required for the smooth operation of bundled tools. While UDS Applications are designed to offer distinct functionalities, some may necessitate external resources, services, or configurations to seamlessly integrate within a particular environment. These dependencies can include a wide range of components such as databases, security services, and networking tools. ----- # Prerequisites `UDS Core` can run in any [CNCF conformant Kubernetes distribution](https://www.cncf.io/training/certification/software-conformance/) that has not reached [End-of-Life (EOL)](https://kubernetes.io/releases/#release-history). This documentation aims to provide guidance and links to relevant information to help configure your Kubernetes environment and hosts for a successful installation of `UDS Core`. Note that customizations may be required depending on the specific environment. ### Cluster Requirements When running Kubernetes on any type of host it is important to ensure you are following the upstream documentation from the Kubernetes distribution regarding prerequisites. A few links to upstream documentation are provided below for convenience. #### RKE2 - [General installation requirements](https://docs.rke2.io/install/requirements) - [Disabling Firewalld to prevent networking conflicts](https://docs.rke2.io/known_issues#firewalld-conflicts-with-default-networking) - [Modifying NetworkManager to prevent CNI conflicts](https://docs.rke2.io/known_issues#networkmanager) - [Known Issues](https://docs.rke2.io/known_issues) ##### Control Plane Metrics Configuration In hardened RKE2 setups (using the CIS profile), control plane components (etcd, kube-scheduler, kube-controller-manager) bind to 127.0.0.1 by default, which prevents Prometheus from scraping them. To fix this, add the following settings to your control plane node’s config file (`/etc/rancher/rke2/config.yaml`): ```yaml kube-controller-manager-arg: - bind-address=0.0.0.0 kube-scheduler-arg: - bind-address=0.0.0.0 etcd-arg: - listen-metrics-urls=http://0.0.0.0:2381 ``` These changes require restarting RKE2 to take effect. ##### CoreDNS Metrics Configuration In hardened RKE2 setups (using the CIS profile), RKE2 applies some default network policies that [block ingress to the kube-system namespace](https://docs.rke2.io/security/hardening_guide#network-policies). In order to enable CoreDNS metrics scraping you will need to enable an additional network policy. UDS Core includes an option to deploy a network policy for CoreDNS metrics scraping. To enable this policy, set the value `rke2CorednsNetpol.enabled` to `true` in the `uds-prometheus-config` helm chart with the following override: ```yaml - name: uds-core ... overrides: kube-prometheus-stack: uds-prometheus-config: values: - path: rke2CorednsNetpol.enabled value: true ``` #### K3S - [General installation requirements](https://docs.k3s.io/installation/requirements) - [Known Issues](https://docs.k3s.io/known-issues) #### EKS - [General installation requirements](https://docs.aws.amazon.com/eks/latest/userguide/create-cluster.html) - [Troubleshooting Guide](https://docs.aws.amazon.com/eks/latest/userguide/troubleshooting.html) #### AKS - [General installation requirements](https://learn.microsoft.com/en-us/azure/well-architected/service-guides/azure-kubernetes-service) - [Troubleshooting Guide](https://learn.microsoft.com/en-us/troubleshoot/azure/azure-kubernetes/welcome-azure-kubernetes) ### UDS Core Requirements The below are specific requirements for running UDS Core. Some of them are tied to the entire stack of UDS Core and some are more specific to certain components. If you encounter issues with a particular component of core, this can be a good list to check to validate you met all the prerequisite requirements for that specific application. #### Default Storage Class Several UDS Core components require persistent volumes that will be provisioned using the default storage class via dynamic volume provisioning. Ensure that your cluster includes a default storage class prior to deploying. You can validate by running the below command (see example output which includes `(default)` next to the `local-path` storage class): ```console ❯ kubectl get storageclass NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE local-path (default) rancher.io/local-path Delete WaitForFirstConsumer true 55s ``` It’s generally beneficial if your storage class supports volume expansion (set `allowVolumeExpansion: true`, provided your provisioner allows it). This enables you to resize volumes when needed. Additionally, be mindful of any size restrictions imposed by your provisioner. For instance, EBS volumes have a minimum size of 1Gi, which could lead to unexpected behavior, especially during Velero’s CSI backup and restore process. These constraints may also necessitate adjustments to default PVC sizes, such as Keycloak’s PVCs, which default to 512Mi in `devMode`. :::caution If you are deploying stateful applications, including but not limited to critical UDS Core services such as [Velero](#velero) or [Loki](#loki), ensure you understand where their data is stored and that the underlying volumes are properly backed up and stored safely. Cluster or deployment issues may result in data loss, particularly when these services rely on in-cluster storage such as the [Minio Operator UDS Package](https://github.com/uds-packages/minio-operator). ::: #### Network Policy Support The UDS Operator will dynamically provision network policies to secure traffic between components in UDS Core. To ensure these are effective, validate that your CNI supports enforcing network policies. In addition, UDS Core makes use of some CIDR based policies for communication with the KubeAPI server. If you are using Cilium, support for node addressability with CIDR based policies must be enabled with a [feature flag](https://docs.cilium.io/en/stable/security/policy/language/#selecting-nodes-with-cidr-ipblock). #### Istio Istio requires a number of kernel modules to be loaded for full functionality. The below is a script that will ensure these modules are loaded and persisted across reboots (see also Istio's [upstream requirements list](https://istio.io/latest/docs/ops/deployment/platform-requirements/)). Ideally this script is used as part of an image build or cloud-init process on each node. ```console modules=("br_netfilter" "xt_REDIRECT" "xt_owner" "xt_statistic" "iptable_mangle" "iptable_nat" "xt_conntrack" "xt_tcpudp" "xt_connmark" "xt_mark" "ip_set") for module in "${modules[@]}"; do modprobe "$module" echo "$module" >> "/etc/modules-load.d/istio-modules.conf" done ``` In addition, to run Istio ingress gateways (part of Core) you will need to ensure your cluster supports dynamic load balancer provisioning when services of type LoadBalancer are created. Typically in cloud environments this is handled using a cloud provider's controller (example: [AWS LB Controller](https://github.com/kubernetes-sigs/aws-load-balancer-controller)). When deploying on-prem, this is commonly done by using a "bare metal" load balancer provisioner like [MetalLB](https://metallb.universe.tf/) or [kube-vip](https://kube-vip.io/). Certain distributions may also include ingress controllers that you will want to disable as they may conflict with Istio (example: RKE2 includes ingress-nginx). :::note If you would like to use MetalLB as your load balancer provisioner there is a UDS Package available for MetalLB from the [UDS Package MetalLB GitHub repository](https://github.com/uds-packages/metallb) ::: ##### Ambient Mode [Ambient Mode](https://istio.io/latest/docs/ambient/overview/) in Istio is now integrated directly into the `istio-controlplane` component and enabled by default. Also note that only the `unicorn` and `registry1` flavors of core contain `FIPS` compliant images. When using ambient mode with UDS Packages, you can benefit from: - Reduced resource overhead compared to sidecar mode, as workloads don't require an injected sidecar container - Simplified deployment and operations for service mesh capabilities - Faster pod startup times since there's no need to wait for sidecar initialization The `istio-controlplane` component installs the Istio CNI plugin which requires specifying the `CNI_CONF_DIR` and `CNI_BIN_DIR` variables. These values can change based on the environment Istio is being deployed into. By default the package will attempt to auto-detect these values and will use the following values if not specified: ```yaml # K3d cluster cniConfDir: /var/lib/rancher/k3s/agent/etc/cni/net.d cniBinDir: /opt/cni/bin/ # Historically this was `/bin/` # K3s cluster cniConfDir: /var/lib/rancher/k3s/agent/etc/cni/net.d cniBinDir: /opt/cni/bin/ # All other clusters cniConfDir: /etc/cni/net.d cniBinDir: /opt/cni/bin/ ``` These values can be overwritten when installing core by setting the `cniConfDir` and `cniBinDir` values in the `istio-controlplane` component. To set these values add the following to the `uds-config.yaml` file: ```yaml variables: core-base: cni_conf_dir: "foo" cni_bin_dir: "bar" ``` or via `--set` if deploying the package via `zarf`: ```console uds zarf package deploy uds-core --set CNI_CONF_DIR=/etc/cni/net.d --set CNI_BIN_DIR=/opt/cni/bin ``` If you are using Cilium you will also need to make some additional configuration changes and add a cluster wide network policy to prevent Cilium's CNI from interfering with the Istio CNI plugin (part of the ambient stack). See the [upstream documentation](https://istio.io/latest/docs/ambient/install/platform-prerequisites/#cilium) for these required changes. #### Falco The UDS Core deployment of Falco utilizes the [Modern eBPF Probe](https://falco.org/docs/concepts/event-sources/kernel/#modern-ebpf-probe). The main advantage it brings to the table is that it is embedded into Falco, which means that you don't have to download or build anything, if your kernel is recent enough Falco will automatically inject it! At bare minimum this setup requires: - Kernel version ≥5.8 (typically) - [BPF ring buffer](https://www.kernel.org/doc/html/next/bpf/ringbuf.html) support - [BTF](https://docs.kernel.org/bpf/btf.html) (BPF Type Format) exposure Most modern OS distributions meet these requirements out of the box. See the [upstream kernel requirements documentation](https://falco.org/docs/concepts/event-sources/kernel/#requirements) for full compatibility details. #### Vector In order to ensure that Vector is able to scrape the necessary logs concurrently you may need to adjust some kernel parameters for your hosts. The below is a script that can be used to adjust these parameters to suitable values and ensure they are persisted across reboots. Ideally this script is used as part of an image build or cloud-init process on each node. ```console declare -A sysctl_settings sysctl_settings["fs.nr_open"]=13181250 sysctl_settings["fs.inotify.max_user_instances"]=1024 sysctl_settings["fs.inotify.max_user_watches"]=1048576 sysctl_settings["fs.file-max"]=13181250 for key in "${!sysctl_settings[@]}"; do value="${sysctl_settings[$key]}" sysctl -w "$key=$value" echo "$key=$value" > "/etc/sysctl.d/$key.conf" done sysctl -p ``` #### Metrics Server Metrics server is provided as an optional component in UDS Core and can be enabled if needed. For distros where metrics-server is already provided, ensure that you do NOT enable metrics-server. See the below as an example for enabling metrics-server if your cluster does not include it. ```yaml - name: uds-core repository: ghcr.io/defenseunicorns/packages/private/uds/core ref: 0.54.1-unicorn optionalComponents: - metrics-server ``` #### Loki The Loki deployment is (by default) backed by an object storage provider for log retention. For cloud environments you can wire this into the environment's storage provider with the following overrides: ```yaml - name: uds-core ... overrides: loki: loki: values: - path: loki.storage.s3.endpoint value: "" - path: loki.storage.s3.secretAccessKey value: "" - path: loki.storage.s3.accessKeyId value: "" - path: loki.storage.bucketNames.chunks value: "" - path: loki.storage.bucketNames.ruler value: "" - path: loki.storage.bucketNames.admin value: "" - path: loki.storage.bucketNames.region value: "" ``` You can also use the [Minio Operator UDS Package](https://github.com/uds-packages/minio-operator) to back Loki with the following overrides: ```yaml - name: minio-operator ... overrides: minio-operator: uds-minio-config: values: - path: apps value: - name: loki namespace: loki remoteSelector: app.kubernetes.io/name: loki bucketNames: - uds-loki-chunks - uds-loki-ruler - uds-loki-admin copyPassword: enabled: true - name: core-logging ... overrides: loki: uds-loki-config: values: - path: storage.internal value: enabled: true remoteSelector: v1.min.io/tenant: loki remoteNamespace: minio loki: values: - path: loki.storage.bucketNames.chunks value: "uds-loki-chunks" - path: loki.storage.bucketNames.ruler value: "uds-loki-ruler" - path: loki.storage.bucketNames.admin value: "uds-loki-admin" - path: loki.storage.s3.endpoint value: http://uds-minio-hl.minio.svc.cluster.local:9000/ - path: loki.storage.s3.region value: "" - path: loki.storage.s3.accessKeyId value: ${LOKI_ACCESS_KEY_ID} - path: loki.storage.s3.secretAccessKey value: ${LOKI_SECRET_ACCESS_KEY} - path: loki.storage.s3.s3ForcePathStyle value: true - path: loki.storage.s3.signatureVersion value: "v4" - path: write.extraArgs value: - "-config.expand-env=true" - path: write.extraEnv value: - name: LOKI_ACCESS_KEY_ID valueFrom: secretKeyRef: name: minio-loki key: accessKey - name: LOKI_SECRET_ACCESS_KEY valueFrom: secretKeyRef: name: minio-loki key: secretKey - path: read.extraArgs value: - "-config.expand-env=true" - path: read.extraEnv value: - name: LOKI_ACCESS_KEY_ID valueFrom: secretKeyRef: name: minio-loki key: accessKey - name: LOKI_SECRET_ACCESS_KEY valueFrom: secretKeyRef: name: minio-loki key: secretKey ``` #### Velero The Velero deployment is (by default) backed by an object storage provider for backup retention. For cloud environments you can wire this into the environment's storage provider with the following overrides: ```yaml - name: uds-core ... overrides: velero: velero: values: - path: credentials.secretContents.cloud value: | [default] aws_access_key_id= aws_secret_access_key= - path: "configuration.backupStorageLocation" value: - name: default provider: aws bucket: "" config: region: "" s3ForcePathStyle: true s3Url: "" credential: name: "velero-bucket-credentials" key: "cloud" ``` You can also use the [Minio Operator UDS Package](https://github.com/uds-packages/minio-operator) to back Velero with the following overrides: ```yaml - name: minio-operator ... overrides: minio-operator: uds-minio-config: values: - path: apps value: - name: velero namespace: velero remoteSelector: app.kubernetes.io/name: velero bucketNames: - uds-velero copyPassword: enabled: true secretIDKey: AWS_ACCESS_KEY_ID secretPasswordKey: AWS_SECRET_ACCESS_KEY - name: core-backup-restore ... overrides: velero: uds-velero-config: values: - path: storage.internal value: enabled: true remoteSelector: v1.min.io/tenant: velero remoteNamespace: minio velero: values: - path: "credentials" value: useSecret: true existingSecret: "minio-velero" extraEnvVars: AWS_ACCESS_KEY_ID: dummy AWS_SECRET_ACCESS_KEY: dummy - path: "configuration.backupStorageLocation" value: - name: default provider: aws bucket: "uds-velero" config: region: "" s3ForcePathStyle: true s3Url: "http://uds-minio-hl.minio.svc.cluster.local:9000/" ``` ----- # Release Overview This document outlines how UDS Core is versioned, released, tested, and maintained. ## Release Cadence UDS Core follows a predictable release schedule to provide regular updates and improvements: - **Regular Releases** (minor or major): New versions are published every 2 weeks (typically on Tuesdays) - **Patch Releases**: Critical bug fixes are released as patches outside the regular cycle when necessary ### Patch Policy Patch releases are created for critical issues that cannot wait for the next regular release cycle. We typically cut patch releases for: - Bugs preventing installation or upgrade (even if only affecting specific configurations) - Issues limiting access to core services (UIs/APIs) or ability to configure/communicate with external dependencies - Significant regressions in functionality or behavior - Security vulnerabilities requiring immediate attention We reserve the right to cut releases outside the normal schedule whenever we deem necessary to address important issues. ## Versioning Strategy UDS Core follows [Semantic Versioning 2.0.0](https://semver.org/). For a more detailed review of how UDS Core applies Semantic Versioning, see the [versioning](https://github.com/defenseunicorns/uds-core/blob/main/VERSIONING.md) document in our repository. ### Breaking Changes Breaking changes are clearly documented in the [CHANGELOG.md](https://github.com/defenseunicorns/uds-core/blob/main/CHANGELOG.md) with the `⚠ BREAKING CHANGES` header (and in the [GitHub release notes](https://github.com/defenseunicorns/uds-core/releases)). Each breaking change includes specific upgrade steps required when applicable. #### Security Exception As a security-first platform, UDS Core reserves the right to release security-related breaking changes in minor versions when the security benefit to users outweighs the disruption of waiting for a major release. These changes will still be clearly advertised as breaking changes. We will always strive to minimize the impact on users and will only exercise this exception when the security improvement is necessary and urgent. ### Current Stability Status While UDS Core has not yet reached version 1.0, it is considered production-ready and stable. The pre-1.0 versioning reflects our commitment to maintaining flexibility as we continue to enhance our security posture. ### Version Support UDS Core provides patch support for the latest three minor versions (the current minor and the two previous minors), where applicable. Minor and major releases are cut from `main`, while patch releases are published from dedicated `release/X.Y` branches for each supported minor stream. Patch releases follow the [patch policy](#patch-policy) and are not present in the main repository changelog (but are documented in GitHub releases). ### Deprecation Policy UDS Core uses a deprecation process to evolve the platform safely while providing clear, predictable upgrade paths for users. Deprecations signal upcoming breaking changes and allow sufficient time for migration before removal in a major release. #### Scope This policy applies to all elements of the UDS Core public API, as defined in the [Versioning](https://github.com/defenseunicorns/uds-core/blob/main/VERSIONING.md) document, including: - Custom Resource Definitions (CRDs), CRD versions, fields, and behaviors - UDS Core configuration values and defaults - Exposed Zarf variables - Default-enabled components or integrations - Default behaviors that are planned to change or be removed Internal implementation details are not subject to this policy. #### How Deprecations Are Announced Deprecations are introduced via commits using the `feat(deprecation)` conventional commit format and are included in GitHub release notes. Each deprecation includes: - What is being deprecated - Why it is being deprecated - The recommended replacement or migration path - The projected major version in which it will be removed All active deprecations are tracked in the [DEPRECATIONS.md](https://github.com/defenseunicorns/uds-core/blob/main/DEPRECATIONS.md) file, which serves as a single source of truth for deprecated features, their deprecation version, and projected removal version. #### Support Period Deprecated features remain supported for **at least three subsequent minor releases** following their deprecation announcement and **may only be removed in a major release**. They continue to function without behavioral changes during this period and may receive bug fixes and security fixes when feasible. For example, if a feature is deprecated in version `0.30.0`, it must remain supported through at least the three subsequent minor releases: `0.31.0`, `0.32.0`, and `0.33.0`. It becomes eligible for removal starting in `1.0.0` (assuming `1.0.0` is released after `0.33.0`). If a major release were planned before the three-minor window elapsed, the deprecated feature would remain and could not be removed until the following major release. Removal of deprecated functionality is considered a breaking change and will only occur in major releases. Patch releases never introduce deprecations or remove deprecated functionality. :::caution Users are expected to resolve all deprecation warnings before upgrading to the next major version to avoid encountering breaking changes. ::: #### CRD-Specific Guarantees Because CRDs represent a primary API boundary for UDS Core, they receive the same deprecation guarantees: - Deprecated CRD fields and versions remain accepted for at least three minor releases after deprecation - New CRD versions may be introduced without removing older versions - CRD version or field removal follows the standard deprecation lifecycle and only occurs in major releases ## Release Process ### Official Releases The release process is automated using [release-please](https://github.com/googleapis/release-please) and GitHub workflows: 1. Changes are merged to the `main` branch through pull requests 1. Release-please automatically determines the next version based on conventional commits 1. A release PR is created with updated version numbers and CHANGELOG entries 1. Once merged, a new version tag is created and the release workflow is triggered 1. Release artifacts are built, tested, and published 1. CVE scans are performed on the released artifacts 1. Release notes are automatically generated from the CHANGELOG ### Release Artifacts Each release includes: - Zarf packages for all UDS Core components - Pre-configured UDS bundles for demos and development (with [`uds-k3d`](https://github.com/defenseunicorns/uds-k3d)) - Documentation updates as necessary ## Testing Strategy UDS Core undergoes rigorous testing before each release. ### Functionality Testing - **Operator Logic Tests**: Validate UDS Operator functionality and reconciliation logic - **UI Journey Tests**: End-to-end testing of user workflows across application interfaces - **API Validation Tests**: Verify API endpoints and responses function correctly - **Cross-Distribution Tests**: Validate compatibility with [supported Kubernetes distributions](/reference/uds-core/distribution-support) - **Upgrade Tests**: Verify smooth upgrades from previous versions ### Security Testing - **Static Analysis**: CodeQL scans for code vulnerabilities - **Dependency Scanning**: Checks for vulnerabilities in dependencies - **Container Scanning**: Analyzes container images for security issues - **Policy Compliance**: Validates adherence to security policies ### Production Validation Defense Unicorns maintains several environments running UDS Core that are updated shortly after each release, providing additional real-world validation. ## Development Builds ### Nightly Snapshots Automated builds from the latest `main` branch are created daily at 10:00 UTC: - Tagged as `snapshot-latest` on GitHub - Available as Zarf packages and UDS bundles in the [GitHub Packages repository](https://github.com/orgs/defenseunicorns/packages?tab=packages&q=uds%2Fsnapshots+repo%3Adefenseunicorns%2Fuds-core) - Each snapshot is tagged with a unique identifier combining date string + commit hash (for immutable, pinned references), while the most recent snapshots are also tagged with `latest` (a mutable tag that always points to the newest snapshot) - Useful for testing new features before official releases - **Not recommended for production use** ### Feature Previews For significant new features or architectural changes, special snapshot builds may be created: - Available from feature branches or `main` - Provided for early feedback and validation ## Upgrade Recommendations When upgrading UDS Core: 1. Always review the [CHANGELOG](https://github.com/defenseunicorns/uds-core/blob/main/CHANGELOG.md) for breaking changes and new features. 1. Ensure you have reviewed and performed any [Keycloak / Identity Config upgrade steps](/reference/uds-core/idam/upgrading-versions). 1. Test upgrades in a staging environment before upgrading production 1. Follow the detailed [upgrade documentation](/reference/deployment/upgrades) 1. Consider the impact on any mission applications running on UDS Core For mission-critical deployments, we recommend maintaining a staging environment that mirrors production for validating upgrades before deployment.