# Container Registry Authentication and Credential Management Methods in Apple Container

> Learn secure OCI registry operations with Apple Container. Discover how it uses macOS Keychain for container registry authentication and credential management, avoiding plain text.

- Repository: [Apple/container](https://github.com/apple/container)
- Tags: how-to-guide
- Published: 2026-06-29

---

**The Apple Container tool stores all registry credentials in the macOS Keychain under the security domain `com.apple.container.registry`, eliminating plain-text storage while enabling secure OCI registry operations.**

The `apple/container` project implements a robust credential management system that leverages native macOS security primitives for container registry authentication. By delegating credential storage to the system Keychain rather than configuration files, the tool ensures that registry passwords remain encrypted at rest yet accessible for image pull and push workflows.

## How Credential Storage Works

All credential operations in the codebase route through the `KeychainHelper` class, which abstracts macOS Keychain interactions. The helper initializes with a repository-wide **security domain** defined in [`Sources/Services/ContainerAPIService/Client/Constants.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Client/Constants.swift) (line 20) as `Constants.keychainID`, set to the string `"com.apple.container.registry"`.

This design centralizes authentication state within the operating system's protected storage, preventing credential leakage through filesystem access or version control while maintaining availability across application launches.

## Authentication Commands

The tool provides three primary CLI commands for credential lifecycle management, each implemented as a separate Swift command structure.

### Logging In to a Registry

The `container registry login` command, implemented in [`Sources/ContainerCommands/Registry/RegistryLogin.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Registry/RegistryLogin.swift) (lines 63-97), handles credential acquisition and validation.

The process follows this sequence:

1. **Input Collection** – The command accepts `--username` and optionally `--password-stdin` to read sensitive values from standard input rather than command-line arguments.
2. **Validation** – The tool constructs a `BasicAuthentication` object and performs a ping against the target registry to verify connectivity and credential validity.
3. **Persistence** – Upon successful validation, the credentials are stored via `KeychainHelper.save(hostname:username:password:)`, associating the username/password pair with the specific registry hostname.

### Listing Stored Credentials

The `container registry list` command, found in [`Sources/ContainerCommands/Registry/RegistryList.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Registry/RegistryList.swift) (lines 41-50), enumerates all stored registry entries.

The command retrieves all credentials using `KeychainHelper.list()`, then maps each stored `RegistryInfo` object to a `RegistryResource` as defined in [`Sources/ContainerResource/Registry/RegistryResource.swift`](https://github.com/apple/container/blob/main/Sources/ContainerResource/Registry/RegistryResource.swift) (lines 20-52). The output supports both table formatting and quiet mode (`-q`), which returns only hostnames for scripting purposes.

### Removing Credentials

The `container registry logout` command, located in [`Sources/ContainerCommands/Registry/RegistryLogout.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Registry/RegistryLogout.swift) (lines 36-40), removes stored entries for a specific hostname.

The implementation calls `KeychainHelper.delete(hostname:)`, which purges the credential record from the Keychain without affecting other stored registries.

## Using Credentials for Image Operations

When pulling or pushing images, the system retrieves stored credentials to authenticate against OCI registries. In [`Sources/ContainerAPIService/Client/ClientImage.swift`](https://github.com/apple/container/blob/main/Sources/ContainerAPIService/Client/ClientImage.swift) (lines 62-71), the code resolves the appropriate scheme (`http` or `https`) based on command-line flags and internal DNS domain configuration.

The workflow proceeds as follows:

- **Credential Retrieval** – The client queries `KeychainHelper.list()` to find matching credentials for the target hostname.
- **Client Construction** – It instantiates a `RegistryClient` with the retrieved `BasicAuthentication` object, configuring the scheme, host, and port parameters.
- **Transport Security** – The scheme resolution ensures that insecure registries use HTTP while standard registries default to HTTPS, preventing man-in-the-middle attacks on credential transmission.

## Code Examples

Authenticate with a registry using command-line flags or stdin:

```bash

# Log in to a registry (prompts for username/password or reads password from stdin)

container registry login myregistry.example.com \
    --username alice \
    --password-stdin < password.txt

```

View stored credentials in different output formats:

```bash

# Show stored registry credentials in table view

container registry list

# Show only hostnames (quiet mode)

container registry list -q

```

Remove credentials for a specific registry:

```bash

# Log out and remove stored credentials

container registry logout myregistry.example.com

```

Programmatically interact with the credential store:

```swift
import ContainerAPIService

// Initialize the keychain helper with the security domain
let keychain = KeychainHelper(securityDomain: Constants.keychainID)

// Save credentials after validation
try keychain.save(
    hostname: "myregistry.example.com",
    username: "alice",
    password: "secret-token"
)

// Retrieve credentials for image operations
let stored = try keychain.list().first { $0.hostname == "myregistry.example.com" }
let auth = BasicAuthentication(
    username: stored?.username ?? "",
    password: stored?.password ?? ""
)

// Construct the registry client
let client = RegistryClient(
    host: "myregistry.example.com",
    scheme: "https",
    port: nil,
    authentication: auth
)

```

## Summary

- **Secure Storage** – Credentials persist in the macOS Keychain under the identifier `com.apple.container.registry`, never touching unencrypted filesystem storage.
- **Command Interface** – Three primary commands (`login`, `list`, `logout`) provide complete credential lifecycle management through `KeychainHelper` methods.
- **Validation** – The `registry login` command validates credentials against the target registry via ping before storing them.
- **Runtime Integration** – Image pull and push operations automatically retrieve credentials to construct authenticated `RegistryClient` instances with appropriate transport schemes.

## Frequently Asked Questions

### Where does apple/container store registry credentials?

The tool stores credentials exclusively in the macOS Keychain under the security domain `"com.apple.container.registry"`, defined as `Constants.keychainID` in [`Sources/Services/ContainerAPIService/Client/Constants.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Client/Constants.swift). This ensures operating-system-level encryption and access control rather than relying on file-based storage.

### How does the tool validate credentials before storing them?

During the `registry login` command execution, the tool creates a `BasicAuthentication` object and performs a ping operation against the target registry. Only after receiving a successful response does it call `KeychainHelper.save()` to persist the credentials, preventing invalid or mistyped credentials from entering the keychain.

### Can I use credential management features programmatically?

Yes. The `KeychainHelper` class provides a Swift API for programmatic credential operations including `save(hostname:username:password:)`, `delete(hostname:)`, and `list()`. You can construct `BasicAuthentication` objects from retrieved credentials and pass them to `RegistryClient` for OCI operations.

### How does the tool handle insecure registries?

The scheme selection logic in [`Sources/ContainerAPIService/Client/ClientImage.swift`](https://github.com/apple/container/blob/main/Sources/ContainerAPIService/Client/ClientImage.swift) (lines 62-71) determines whether to use HTTP or HTTPS based on the `--scheme` command-line flag and internal DNS domain resolution. This allows the credential system to authenticate against insecure HTTP registries when explicitly configured, while defaulting to HTTPS for security.