> For the complete documentation index, see [llms.txt](https://developer.harness.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.harness.io/harness-platform/use-harness-platform/delegates/delegate/manage-delegates/proxy/configure-delegate-kerberos-proxy.md).

# Kerberos proxy authentication

Configure Harness Delegate to authenticate to a Kerberos-enabled proxy using SPNEGO/Negotiate authentication.

If your outbound HTTP proxy requires Kerberos/SPNEGO (Negotiate) authentication instead of Basic authentication, the delegate can authenticate to it using a Kerberos keytab you provide. No `PROXY_USER` or `PROXY_PASSWORD` is needed.

For standard proxy configuration with Basic authentication, go to [Proxy configuration guide](/harness-platform/use-harness-platform/delegates/delegate/manage-delegates/proxy/configure-delegate-proxy-settings.md).

## What you will learn from this topic

* How to understand the [scope of Kerberos proxy authentication](#scope) in this release
* How to configure [environment variables](#environment-variables) for Kerberos authentication
* How to author a [JAAS login configuration](#jaas-login-configuration) file
* How to configure [Kerberos settings](#kerberos-configuration) in `krb5.conf`
* How to deploy a delegate with [Kerberos proxy authentication](#example-manifest) using a complete Kubernetes manifest
* How to [rotate keytabs](#rotate-keytabs) without restarting the delegate
* How to [troubleshoot](#troubleshooting) common authentication failures

## Before you begin

Before you configure Kerberos proxy authentication, ensure you have the following:

* **Kubernetes cluster**: You need kubectl access to deploy and configure the delegate. For more information, go to [Delegate installation options](/harness-platform/use-harness-platform/delegates/delegate/install-delegates/overview.md).
* **Delegate installed**: A Harness Delegate must be installed in your Kubernetes cluster. For more information, go to [Delegate overview](/harness-platform/use-harness-platform/delegates/delegate/delegate-concepts/delegate-overview.md) and [Delegate system requirements](/harness-platform/use-harness-platform/delegates/delegate/delegate-concepts/delegate-requirements.md).
* **Kerberos keytab**: Obtain a keytab file for the delegate principal from your Kerberos administrator.
* **Kerberos configuration**: Your organization's `krb5.conf` configuration file with realm and KDC (Key Distribution Center) details.
* **Network access**: The delegate pod must be able to reach your KDC over the network.
* **Proxy configuration**: A proxy server configured to accept Kerberos/Negotiate authentication (not just Basic auth). For Basic authentication proxy setup, go to [Proxy configuration guide](/harness-platform/use-harness-platform/delegates/delegate/manage-delegates/proxy/configure-delegate-proxy-settings.md).

## Scope

Kerberos proxy authentication in this release covers delegate-to-Harness Manager traffic only:

* REST API calls (heartbeat, task polling, task acknowledgement)
* WebSocket tunnel connections

Everything else continues to use Basic authentication (`PROXY_USER`/`PROXY_PASSWORD`), for example:

* Shell script tasks that run locally on the delegate or over SSH/WinRM
* Outbound calls to third-party systems (Terraform Cloud, Jira, Jenkins, HTTP pipeline steps)

{% hint style="warning" %}
**Third-party integration limitation**

If your corporate proxy requires Kerberos authentication for all outbound traffic, calls to third-party systems will fail with HTTP 407 until Kerberos support is extended to those integrations in a future release.
{% endhint %}

## Set up Kerberos proxy authentication

Setting up Kerberos proxy authentication requires no UI configuration, no API toggle, and no additional volumes rendered by Harness. You configure everything directly in the delegate manifest yourself.

Perform the following steps to set up Kerberos proxy authentication:

1. Set the standard proxy environment variables in your delegate manifest (these are the same as for Basic auth): `PROXY_HOST`, `PROXY_PORT`, and `PROXY_SCHEME`.
2. Set `PROXY_AUTH_TYPE=KERBEROS` on the delegate container to enable Kerberos authentication.
3. Provide your own `krb5.conf` file and point `KRB5_CONFIG` to its path.
4. Author a JAAS login config file (defining a `HarnessKrb5` entry) and point `KRB5_JAAS_CONFIG` to its path.
5. Ensure the delegate pod can reach your KDC, and that your proxy is configured to accept Kerberos/Negotiate authentication (not just Basic).

The following sections provide detailed configuration instructions for each component.

### Environment variables

Configure the following environment variables in your delegate manifest:

| Variable           | Required | Description                                                                                                              |
| ------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------ |
| `PROXY_HOST`       | Yes      | Proxy hostname or IP address. Go to [Select PROXY\_HOST value](#select-proxy_host-value) for Kerberos-specific guidance. |
| `PROXY_PORT`       | Yes      | Proxy port number (for example, 3128).                                                                                   |
| `PROXY_SCHEME`     | Yes      | Proxy scheme (`http` or `https`).                                                                                        |
| `PROXY_AUTH_TYPE`  | Yes      | Set to `KERBEROS` to enable Kerberos authentication.                                                                     |
| `PROXY_MANAGER`    | Yes      | Set to `true` to route Manager traffic through the proxy.                                                                |
| `KRB5_CONFIG`      | Yes      | Path to your `krb5.conf` file (for example, `/etc/harness/kerberos/krb5.conf`).                                          |
| `KRB5_JAAS_CONFIG` | Yes      | Path to your JAAS login config file (for example, `/etc/harness/kerberos/jaas/jaas.conf`).                               |
| `NO_PROXY`         | No       | Comma-separated list of hosts or domains to bypass the proxy.                                                            |

{% hint style="danger" %}
**Boot failure on missing configuration**

The delegate fails to start if `PROXY_AUTH_TYPE=KERBEROS` is set but `KRB5_CONFIG` or `KRB5_JAAS_CONFIG` is unset or points to an unreadable file. For more information on delegate environment variables, go to [Delegate environment variables](/harness-platform/use-harness-platform/delegates/delegate/delegate-reference/delegate-environment-variables.md).
{% endhint %}

### JAAS login configuration

Create a JAAS login config file that defines a `HarnessKrb5` entry. This file specifies the keytab location and principal to use for authentication.

The entry **must** be named `HarnessKrb5` exactly:

```java
HarnessKrb5 {
  com.sun.security.auth.module.Krb5LoginModule required
  useKeyTab=true
  keyTab="/etc/harness/kerberos/keytab/proxy.keytab"
  principal="delegate@EXAMPLE.COM"
  storeKey=true
  refreshKrb5Config=true
  doNotPrompt=true;
};
```

Replace the following values with your actual configuration:

* **keyTab**: Path where your keytab is mounted in the container.
* **principal**: Your delegate's Kerberos principal (must match an entry in the keytab).

### Kerberos configuration

Your `krb5.conf` file defines the Kerberos realm, KDC location, and domain mappings. Here is a recommended configuration:

```ini
[libdefaults]
  default_realm = EXAMPLE.COM
  dns_lookup_realm = false
  dns_lookup_kdc = false
  dns_canonicalize_hostname = false
  rdns = false
  forwardable = true

[realms]
  EXAMPLE.COM = {
    kdc = kdc.example.com
    admin_server = kdc.example.com
  }

[domain_realm]
  .example.com = EXAMPLE.COM
  example.com = EXAMPLE.COM
```

The following are key settings to understand:

* `dns_canonicalize_hostname = false` and `rdns = false` prevent hostname rewriting before deriving the service principal.
* `dns_lookup_realm = false` and `dns_lookup_kdc = false` disable DNS-based KDC discovery.
* Do **not** set `default_keytab_name`. The keytab path is specified in your JAAS config.

### Select PROXY\_HOST value

The Service Principal Name (SPN) sent to the KDC is `HTTP/<X>@<realm>`, where `<X>` depends on your `PROXY_HOST` value and `krb5.conf` DNS settings.

The following table shows how different `PROXY_HOST` values and DNS settings affect the SPN hostname:

| PROXY\_HOST         | rdns    | dns\_canonicalize\_hostname | SPN hostname                             |
| ------------------- | ------- | --------------------------- | ---------------------------------------- |
| `proxy.example.com` | `false` | `false`                     | `proxy.example.com` (verbatim)           |
| `proxy.example.com` | `false` | `true`                      | Forward DNS canonical name               |
| `proxy.example.com` | `true`  | any                         | PTR record of resolved IP                |
| `10.2.204.25`       | `false` | any                         | `10.2.204.25` (rarely registered at KDC) |
| `10.2.204.25`       | `true`  | any                         | PTR record of that IP                    |

Recommendation: Use the proxy hostname in `PROXY_HOST` and set `rdns = false` and `dns_canonicalize_hostname = false` in your `krb5.conf`. This ensures the SPN matches what your KDC administrator registered.

## Example manifest

The following is a complete Kubernetes manifest example that demonstrates how to configure a delegate with Kerberos proxy authentication.

This example uses the standard Harness Delegate image. If you need to customize the delegate image with additional tools or configurations, go to [Build custom delegate images using Dockerfile](/harness-platform/use-harness-platform/delegates/delegate/manage-delegates/build-custom-images-delegate-dockerfile.md).

{% code overflow="wrap" %}

```yaml
apiVersion: v1
kind: Namespace
metadata:
  name: harness-delegate-ng

---

apiVersion: v1
kind: ConfigMap
metadata:
  name: kerberos-config
  namespace: harness-delegate-ng
data:
  krb5.conf: |
    [libdefaults]
    default_realm = EXAMPLE.COM
    dns_lookup_realm = false
    dns_lookup_kdc = false
    rdns = false
    dns_canonicalize_hostname = false
    forwardable = true

    [realms]
        EXAMPLE.COM = {
            kdc = kdc.example.com
            admin_server = kdc.example.com
        }

    [domain_realm]
        .example.com = EXAMPLE.COM
        example.com = EXAMPLE.COM

---

apiVersion: v1
kind: ConfigMap
metadata:
  name: kerberos-jaas-config
  namespace: harness-delegate-ng
data:
  jaas.conf: |
    HarnessKrb5 {
      com.sun.security.auth.module.Krb5LoginModule required
      useKeyTab=true
      keyTab="/etc/harness/kerberos/keytab/proxy.keytab"
      principal="delegate@EXAMPLE.COM"
      storeKey=true
      refreshKrb5Config=true
      doNotPrompt=true;
    };

---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: harness-delegate
  namespace: harness-delegate-ng
spec:
  replicas: 1
  selector:
    matchLabels:
      harness.io/name: harness-delegate
  template:
    metadata:
      labels:
        harness.io/name: harness-delegate
    spec:
      securityContext:
        fsGroup: 100
        fsGroupChangePolicy: OnRootMismatch
      containers:
      - name: delegate
        image: harness/delegate:latest
        securityContext:
          allowPrivilegeEscalation: false
          runAsUser: 0
        env:
        - name: ACCOUNT_ID
          value: "YOUR_ACCOUNT_ID"
        - name: DELEGATE_TOKEN
          valueFrom:
            secretKeyRef:
              name: delegate-token
              key: token
        - name: MANAGER_HOST_AND_PORT
          value: https://app.harness.io
        - name: PROXY_HOST
          value: "proxy.example.com"
        - name: PROXY_PORT
          value: "3128"
        - name: PROXY_SCHEME
          value: "http"
        - name: PROXY_MANAGER
          value: "true"
        - name: PROXY_AUTH_TYPE
          value: "KERBEROS"
        - name: KRB5_CONFIG
          value: "/etc/harness/kerberos/krb5.conf"
        - name: KRB5_JAAS_CONFIG
          value: "/etc/harness/kerberos/jaas/jaas.conf"
        volumeMounts:
        - name: kerberos-config
          mountPath: /etc/harness/kerberos/krb5.conf
          subPath: krb5.conf
          readOnly: true
        - name: kerberos-jaas
          mountPath: /etc/harness/kerberos/jaas/jaas.conf
          subPath: jaas.conf
          readOnly: true
        - name: kerberos-keytab
          mountPath: /etc/harness/kerberos/keytab
          readOnly: true

      # Keytab sidecar - fetches keytab from KDC and writes to shared volume
      - name: keytab-sidecar
        image: your-keytab-sidecar-image:latest
        volumeMounts:
        - name: kerberos-keytab
          mountPath: /shared
        securityContext:
          runAsNonRoot: true
          runAsUser: 10001
          runAsGroup: 10001
        resources:
          requests:
            memory: "32Mi"
            cpu: "10m"
          limits:
            memory: "64Mi"
            cpu: "50m"

      volumes:
      - name: kerberos-config
        configMap:
          name: kerberos-config
      - name: kerberos-jaas
        configMap:
          name: kerberos-jaas-config
      - name: kerberos-keytab
        emptyDir:
          medium: Memory
```

{% endcode %}

{% hint style="info" %}
**Keytab sidecar container**

This example includes a `keytab-sidecar` container that automatically fetches the keytab from the KDC and writes it to the shared `emptyDir` volume. The delegate container reads the keytab from this shared volume.

The sidecar runs continuously and can refresh the keytab, enabling rotation without restarting the delegate. For more information on keytab rotation, go to [Use a sidecar for rotation](#use-a-sidecar-for-rotation).

**Important:** Mount the keytab volume as a **directory** (no `subPath`), not as a file. If you use `subPath` and the keytab does not exist when the pod starts, Kubernetes creates an empty directory that permanently masks the file.
{% endhint %}

## Rotate keytabs

If you rotate keytabs periodically (for example, using a sidecar container), the delegate picks up the new keytab automatically on the next proxy challenge. No restart is required.

### Use a sidecar for rotation

You can share the keytab between containers using an `emptyDir` volume. The following example shows how to configure a keytab rotation sidecar:

```yaml
spec:
  containers:
  - name: delegate
    volumeMounts:
    - name: kerberos-keytab
      mountPath: /etc/harness/kerberos/keytab
      readOnly: true
  
  - name: keytab-sidecar
    image: your-keytab-rotation-image:latest
    volumeMounts:
    - name: kerberos-keytab
      mountPath: /etc/harness/kerberos/keytab
      readOnly: false
  
  volumes:
  - name: kerberos-keytab
    emptyDir:
      medium: Memory
```

In this configuration:

* The sidecar writes the keytab to the shared volume.
* The delegate reads the keytab from the shared volume.
* If the keytab is not yet present when the delegate starts, authentication attempts fail and log a warning, but subsequent attempts succeed once the sidecar has written the keytab.

## Troubleshooting

<details>

<summary>Delegate fails to start with PROXY_AUTH_TYPE=KERBEROS requires KRB5_CONFIG</summary>

Verify that both `KRB5_CONFIG` and `KRB5_JAAS_CONFIG` environment variables are set and point to readable files. The delegate boot process fails fast if either variable is unset or points to an unreadable file.

</details>

<details>

<summary>Authentication fails with HTTP 407 responses</summary>

This can occur due to several configuration or connectivity issues:

* Keytab not readable at the path specified in your JAAS config.
* Principal in JAAS config does not match any entry in the keytab.
* Delegate pod cannot reach the KDC.
* Proxy is not configured for Negotiate/SPNEGO authentication.
* DNS or hostname mismatch breaks the `HTTP/<proxy-host>` service ticket.

Perform the following steps to diagnose and resolve the issue:

1. Verify keytab is mounted and readable.
2. Confirm principal matches keytab entries exactly.
3. Test KDC connectivity from the pod.
4. Confirm proxy advertises `Negotiate` in 407 responses.
5. Set `dns_canonicalize_hostname=false` and `rdns=false` in `krb5.conf`.

</details>

<details>

<summary>Authentication works briefly then fails before recovering</summary>

A proxy challenge triggered re-authentication while the KDC was briefly unreachable or the keytab was mid-rotation. Check delegate logs for `Kerberos: JAAS login failed for entry HarnessKrb5`. If the issue self-recovers, no action is needed.

</details>

<details>

<summary>Need to enable detailed Kerberos debugging</summary>

Enable detailed Kerberos debugging by adding the following to your delegate's `JAVA_OPTS`:

```yaml
env:
- name: JAVA_OPTS
  value: "-Xms64M -Dsun.security.krb5.debug=true"
```

Look for the following log messages to confirm successful authentication:

* `Kerberos: cached Subject initialized via JAAS entry HarnessKrb5`
* `Kerberos: refreshed cached Subject via JAAS entry HarnessKrb5`

</details>

<details>

<summary>Want to test keytab and proxy connectivity independently</summary>

Run the following commands from a pod that has access to the same keytab and network configuration:

```bash
# Test keytab with kinit
kinit -kt /path/to/proxy.keytab delegate@EXAMPLE.COM

# Test proxy with curl
curl -x http://proxy.example.com:3128 \
     --proxy-negotiate -U : \
     https://app.harness.io
```

These commands help isolate configuration issues by testing keytab and proxy authentication separately from the delegate.

</details>

## Additional considerations

### In-cluster Kubernetes delegate

If the delegate runs in-cluster and needs to access Kubernetes APIs, add the cluster master IP to `NO_PROXY` to bypass the proxy for in-cluster connections.

The following example shows how to configure `NO_PROXY`:

```yaml
env:
- name: NO_PROXY
  value: "kubernetes.default.svc,10.0.0.1"
```

### mTLS support

Harness supports mTLS authentication on a case-by-case basis. Contact [Harness Support](mailto:support@harness.io) to enable it.

## Next steps

* Go to [Proxy configuration guide](/harness-platform/use-harness-platform/delegates/delegate/manage-delegates/proxy/configure-delegate-proxy-settings.md) to learn how to configure proxy settings with Basic authentication.
* Go to [Delegate overview](/harness-platform/use-harness-platform/delegates/delegate/delegate-concepts/delegate-overview.md) to understand delegate architecture, lifecycle, and operational capabilities.

{% @harness-feedback/feedback module="harness-ai" pagePath="harness-ai/use-harness-platform/delegates/delegate/manage-delegates/proxy/configure-delegate-kerberos-proxy" %}
