Class CredentialsProviderService

java.lang.Object
com.maybeitssquid.rotatingsecrets.CredentialsProviderService

public class CredentialsProviderService extends Object
Service that reads database credentials from Kubernetes-mounted secret files and notifies registered UpdatableCredential components when credentials change.

This service implements the credential rotation pattern for Kubernetes environments. It watches the secrets directory for changes using WatchService (typically mounted by a secrets manager like HashiCorp Vault, OpenBao, or the External Secrets Operator). When credentials change, all registered connection pools are notified to update their credentials.

File Structure

The service expects the following files in the secrets directory:

  • username - Contains the database username
  • password - Contains the database password

Kubernetes Secret Mounting

Kubernetes mounts secrets via atomic symlink swaps on the ..data directory. Because individual credential files are symlinks, the watch is registered on the parent directory rather than the files themselves, so that the directory-level events fired during the symlink swap are captured.

Configuration Properties

  • k8s.secrets.path - Base directory for secret files (default: /var/run/secrets/database)
  • k8s.secrets.refresh-interval - Fallback poll timeout as a Duration, such as 30s, read by the application's configuration; a credential re-check is forced after this interval even if no watch event fires (default: 30000)

Thread Safety

This service is thread-safe. Credential reads and updates are performed atomically, and the list of updatable components is safely managed.

See Also:
  • Field Details

    • usernamePath

      protected final Path usernamePath
      Path to the file containing the database username.
    • passwordPath

      protected final Path passwordPath
      Path to the file containing the database password.
  • Constructor Details

    • CredentialsProviderService

      public CredentialsProviderService(String secretsPath, long refreshIntervalMs)
      Creates a new credentials provider reading from the specified secrets path.

      The provider will look for username and password files within the specified directory.

      Parameters:
      secretsPath - base path where Kubernetes mounts the secret files; defaults to /var/run/secrets/database
      refreshIntervalMs - fallback poll timeout in milliseconds; a credential re-check is forced after this interval even if no watch event fires; defaults to 30000
  • Method Details

    • start

      public void start() throws IOException
      Validates file permissions on startup and starts the directory watch thread.

      Checks if secret files are world-readable and logs a security warning if they are. On non-POSIX filesystems, the permission check is skipped.

      Throws:
      IOException - if the WatchService cannot be created or the directory cannot be registered
    • stop

      public void stop()
      Stops the directory watch thread and closes the WatchService.
    • refreshCredentials

      public void refreshCredentials()
      Reads the current credentials from the mounted secret files and notifies registered UpdatableCredential components if they have changed.
    • register

      public void register(UpdatableCredential<String> updatable)
      Registers a component to receive credential change notifications.

      Register components before calling start(), so that the first credential read reaches them.

      Parameters:
      updatable - the component to notify when credentials change