From 0783525b98a05a8d5ffed1cf5bed16bb7887d724 Mon Sep 17 00:00:00 2001 From: Micah Nagel Date: Fri, 10 Jan 2025 15:53:26 -0700 Subject: [PATCH] chore(docs): add doc on non-http ingress (#1166) ## Description Documents the resources/configuration necessary to allow non-http ingress into a UDS Cluster (with Istio). ## Related Issue Fixes https://github.com/defenseunicorns/uds-core/issues/748 ## Type of change - [ ] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [x] Other (security config, docs update, etc) ## Steps to Validate While the doc can be read and reviewed, I stepped through this on k3d with an example pod to validate my own docs. The steps I used are included below for convenience/reference. These should align with the doc 1:1, just subsituting real workloads/values where needed instead of the example ones.
Create a folder + file for a new bundle, `bundles/base-ssh/uds-bundle.yaml`. The file contents should be: ```yaml kind: UDSBundle metadata: name: base-ssh version: "dev" packages: - name: init repository: ghcr.io/zarf-dev/packages/init ref: v0.45.0 - name: core-base repository: ghcr.io/defenseunicorns/packages/private/uds/core-base ref: 0.33.1-unicorn overrides: istio-tenant-gateway: gateway: values: - path: "service.ports" value: - name: status-port port: 15021 protocol: TCP targetPort: 15021 - name: http2 port: 80 protocol: TCP targetPort: 80 - name: https port: 443 protocol: TCP targetPort: 443 - name: tcp-ssh port: 2022 protocol: TCP targetPort: 22 ``` Run the below commands to deploy core with a pod listening for SSH connections: ```console # The extra args here allow us to expose port 2022 on the host and map it into the ingress gateway uds zarf package deploy oci://defenseunicorns/uds-k3d:0.11.0 --set K3D_EXTRA_ARGS='-p 2022:2022@server:*' --set NGINX_EXTRA_PORTS='[2022]' --confirm # Create our bundle uds create bundles/base-ssh --confirm # Deploy our bundle (note that the architecture may be different for you) uds deploy bundles/base-ssh/uds-bundle-base-ssh-arm64-dev.tar.zst --confirm # Create our gateway kubectl apply -f - < ## Checklist before merging - [x] Test, docs, adr added or updated as needed - [x] [Contributor Guide](https://github.com/defenseunicorns/uds-template-capability/blob/main/CONTRIBUTING.md) followed --------- Co-authored-by: Noah <40781376+noahpb@users.noreply.github.com> --- docs/reference/configuration/ingress.md | 5 + .../configuration/non-http-ingress.md | 121 ++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 docs/reference/configuration/non-http-ingress.md diff --git a/docs/reference/configuration/ingress.md b/docs/reference/configuration/ingress.md index de5ac0c6d..fb059a382 100644 --- a/docs/reference/configuration/ingress.md +++ b/docs/reference/configuration/ingress.md @@ -14,6 +14,10 @@ UDS Core provides a few Istio [Gateway](https://istio.io/latest/docs/reference/c 2. **(Required)** Admin Gateway - This gateway provides ingress to admin-related applications that are not for use by the default end user. By default, UDS Core deploys a few services on this gateway, such as the Admin Keycloak interface. This gateway is typically accessible to admins of the applications deployed on top of UDS Core. *Since the Admin and Tenant Gateways are logically separated, it is possible to have different security controls on each gateway.* 3. **(Optional)** Passthrough Gateway - This gateway allows mesh ingress without TLS termination performed by Istio. This could be useful for applications that need to (or currently) handle their own TLS termination. This gateway used to be a default component of UDS Core but is no longer deployed by default. To deploy this gateway, you must specify `istio-passthrough-gateway` as an `optionalComponent` in your UDS Bundle configuration. +:::note +The default gateways provided with UDS Core only support HTTP/HTTPS ingress. If you need other TCP ingress for a service (ex: SSH ingress) this can be done by adding additional resources/configuration to UDS Core (see [this document](https://uds.defenseunicorns.com/reference/configuration/non-http-ingress/) for a guide). UDP Ingress is [not currently supported with Istio](https://github.com/istio/istio/issues/1430) and would need to be managed via a separate ingress path. +::: + ### Enable Passthrough Gateway In order to enable the Passthrough Gateway, you must specify `istio-passthrough-gateway` as an `optionalComponent` in your UDS Bundle configuration. Here is an example of how to do this: @@ -129,3 +133,4 @@ packages: values: - path: tls.credentialName value: tenant-gateway-tls-secret # Reference to the Kubernetes secret for the tenant gateway's TLS certificate +``` diff --git a/docs/reference/configuration/non-http-ingress.md b/docs/reference/configuration/non-http-ingress.md new file mode 100644 index 000000000..7ea71c3be --- /dev/null +++ b/docs/reference/configuration/non-http-ingress.md @@ -0,0 +1,121 @@ +--- +title: Non-HTTP(s) Istio Ingress +--- + +As noted in the [Istio Ingress document](https://uds.defenseunicorns.com/reference/configuration/ingress/), UDS Core by default provides gateway configuration to handle HTTP(s) ingress traffic only. This document provides example configuration and resources to setup ingress for a non-http service (using SSH for the example below). Note that while this example uses port 22 and the SSH protocol this same process should work for an TCP port/protocol that your service is listening on. + +## UDS Core Configuration + +In order to allow ingress for a non-HTTP service you first need to configure the UDS Core loadbalancers to accept traffic on a different port. This can be done via an override to the configuration for the admin or tenant loadbalancers, as shown in the example below for the tenant loadbalancer to add port 22: + +```yaml + - name: core + repository: ghcr.io/defenseunicorns/packages/uds/core + ref: x.x.x + overrides: + istio-tenant-gateway: + gateway: + values: + - path: "service.ports" + value: + # Default ports for status, http, and https + - name: status-port + port: 15021 + protocol: TCP + targetPort: 15021 + - name: http2 + port: 80 + protocol: TCP + targetPort: 80 + - name: https + port: 443 + protocol: TCP + targetPort: 443 + # Any additional ports required for ingress + - name: tcp-ssh + port: 2022 # The external port that is exposed + protocol: TCP + targetPort: 22 # The port to route to on the Gateway +``` + +Note that you _MUST_ include the default list of ports (as shown above) to ensure that HTTP traffic and liveness checks continue to function as expected. You can choose any `port` and `targetPort` for your additional configuration that you want. + +## Gateway Custom Resource + +In order to allow exposing services through the newly opened loadbalancer port you must also create an [Istio Gateway](https://istio.io/latest/docs/reference/config/networking/gateway/) custom resource that specifies the hosts and port that you want to configure the gateway to accept requests for. The below example shows how to do this for `example.uds.dev` on our SSH port of 22: + +```yaml +apiVersion: networking.istio.io/v1beta1 +kind: Gateway +metadata: + name: example-ssh-gateway + # This must be the namespace of the ingressgateway you configured the port for + namespace: istio-tenant-gateway +spec: + selector: + app: tenant-ingressgateway + servers: + - hosts: + # This should be the host you expect to hit with requests + - example.uds.dev + port: + name: tcp-ssh + # This must match the `targetPort` you added to the port list above + number: 22 + protocol: TCP +``` + +## VirtualService Custom Resource + +Now that the loadbalancer and Istio Gateway are configured for the right ports and host, you will just need to add a route (`VirtualService`) to ensure traffic is directed to the right cluster service when requests come to your host and port. The example below does this for our `example.uds.dev` host: + +```yaml +apiVersion: networking.istio.io/v1beta1 +kind: VirtualService +metadata: + name: example-ssh + # This must be in the namespace of your application + namespace: example +spec: + gateways: + # This must match the namespace/name of the Gateway you created + - istio-tenant-gateway/example-ssh-gateway + hosts: + - example.uds.dev + tcp: + - match: + # This must match the Gateway port number you added above + - port: 22 + route: + - destination: + # This should be the full cluster service address + host: example.example.svc.cluster.local + port: + # This is the port on the service you want to route to + number: 22 +``` + +Assuming you are running with strict network policies you will also need to add a network policy to allow ingress on this same port. You can do this in the Package CR like the example below: + +```yaml +spec: + network: + allow: + - direction: Ingress + selector: + app: example + # These must line up with the gateway you chose + remoteNamespace: istio-tenant-gateway + remoteSelector: + app: tenant-ingressgateway + # This must line up with the port exposed on the pod + port: 22 + description: "SSH Ingress" +... +``` + +With these steps complete you should be able to hit your application over the port you configured on the configured host, so in our case we should be able to run: + +```console +ssh -p 2022 user@example.uds.dev +```