Skip to content

feature: support alternative Linux token cache backend for containers #762

Description

@whitehat101

Summary

kubelogin on Linux appears to rely on Azure Identity's persistent token cache backend for interactive user flows (devicecode, interactive, ropc). In containerized environments using Docker's default seccomp profile, the required kernel keyring syscalls (keyctl, add_key) are blocked, so token persistence fails and users are prompted to re-authenticate on every kubectl command.

This works fine on macOS, but fails in a VS Code dev container / Docker container unless seccomp is loosened.

Environment

  • kubelogin: v0.2.18
  • host/container OS: Ubuntu Linux in VS Code dev container
  • container runtime behavior: Docker seccomp active (Seccomp: 2)
  • login mode: devicecode

Reproduction

Inside the container:

kubelogin -v=5 get-token \
  --login devicecode \
  --server-id <server-id> \
  --client-id <client-id> \
  --tenant-id <tenant-id> \
  --environment AzurePublicCloud

Observed log:

failed to create cache: persistent storage isn't available due to error "couldn't get the user keyring due to error \"operation not permitted\""

Then every subsequent kubelogin get-token / kubectl invocation prompts for device login again.

Additional evidence

Inside the container:

grep '^Seccomp:' /proc/self/status

Output:

Seccomp:  2

keyctl also fails directly:

keyctl show
keyctl get_persistent @u

Output:

Operation not permitted

Using Docker/devcontainer with:

{
  "runArgs": ["--security-opt", "seccomp=unconfined"]
}

makes token persistence work again, which strongly suggests the failure is due to blocked kernel keyring syscalls.

What appears to be happening

From the current implementation:

  • get-token enables persistent cache
  • interactive credential paths call newPersistentCache()
  • that calls Azure Identity persistent cache creation
  • on Linux, Azure Identity uses the kernel key retention service

--cache-dir appears to control the authentication record (auth.json), not the actual persistent token cache backend.

So in default container environments:

  • auth.json is still created
  • persistent token cache is not
  • authentication still works
  • but the user gets prompted every command

Why this is a problem

This is a poor fit for common container/devcontainer workflows because Docker's default seccomp profile blocks keyctl by design.

At the moment, users appear to have only these options:

  1. run with seccomp=unconfined or a custom seccomp profile that allows kernel keyring syscalls
  2. switch login mode entirely (e.g. azurecli) if tenant access permits it (mine does not)

For users who need devicecode in containers, there doesn't appear to be a container-friendly fallback.


Here's how to make a custom seccomp profile based on the Docker default profile that allows the required syscalls.

However, this may be a security concern because these syscalls are not namespaced.

mkdir -p .devcontainer

curl -fsSL https://raw.githubusercontent.com/moby/moby/v28.2.2/profiles/seccomp/default.json \
  -o .devcontainer/seccomp-kubelogin.json

jq '
  .syscalls += [
    {
      "names": ["keyctl", "add_key"],
      "action": "SCMP_ACT_ALLOW"
    }
  ]
' .devcontainer/seccomp-kubelogin.json \
  > .devcontainer/seccomp-kubelogin.tmp

mv .devcontainer/seccomp-kubelogin.tmp .devcontainer/seccomp-kubelogin.json

devcontainer.json

{
  "securityOpt": [
    "seccomp=${localWorkspaceFolder}/.devcontainer/seccomp-kubelogin.json"
  ]
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions