credentials

package
v2.0.0-...-c472316 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 12, 2024 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Overview

Package credentials supports reading, saving, and removing credentials from Docker configuration files and external credential stores that follow the Docker credential helper protocol.

Reference: https://docs.docker.com/engine/reference/commandline/login/#credential-stores

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrPlaintextPutDisabled is returned by Put() when DisablePut is set
	// to true.
	ErrPlaintextPutDisabled = errors.New("putting plaintext credentials is disabled")
	// ErrBadCredentialFormat is returned by Put() when the credential format
	// is bad.
	ErrBadCredentialFormat = errors.New("bad credential format")
)
View Source
var ErrClientTypeUnsupported = errors.New("client type not supported")

ErrClientTypeUnsupported is thrown by Login() when the registry's client type is not supported.

Functions

func Credential

func Credential(store Store) auth.CredentialFunc

Credential returns a Credential() function that can be used by auth.Client.

Example
package main

import (
	"net/http"

	"oras.land/oras-go/v2/registry/remote/auth"

	credentials "oras.land/oras-go/v2/registry/remote/credentials"
)

func main() {
	store, err := credentials.NewStore("example/path/config.json", credentials.StoreOptions{})
	if err != nil {
		panic(err)
	}

	client := auth.DefaultClient
	client.Credential = credentials.Credential(store)

	request, err := http.NewRequest(http.MethodGet, "localhost:5000", nil)
	if err != nil {
		panic(err)
	}

	_, err = client.Do(request)
	if err != nil {
		panic(err)
	}
}
Output:

func Login

func Login(ctx context.Context, store Store, reg *remote.Registry, cred auth.Credential) error

Login provides the login functionality with the given credentials. The target registry's client should be nil or of type *auth.Client. Login uses a client local to the function and will not modify the original client of the registry.

Example
package main

import (
	"context"
	"fmt"

	"oras.land/oras-go/v2/registry/remote"
	"oras.land/oras-go/v2/registry/remote/auth"

	credentials "oras.land/oras-go/v2/registry/remote/credentials"
)

func main() {
	store, err := credentials.NewStore("example/path/config.json", credentials.StoreOptions{
		AllowPlaintextPut: true,
	})
	if err != nil {
		panic(err)
	}
	registry, err := remote.NewRegistry("localhost:5000")
	if err != nil {
		panic(err)
	}
	cred := auth.Credential{
		Username: "username-example",
		Password: "password-example",
	}
	err = credentials.Login(context.Background(), store, registry, cred)
	if err != nil {
		panic(err)
	}
	fmt.Println("Login succeeded")
}
Output:

func Logout

func Logout(ctx context.Context, store Store, registryName string) error

Logout provides the logout functionality given the registry name.

Example
package main

import (
	"context"
	"fmt"

	credentials "oras.land/oras-go/v2/registry/remote/credentials"
)

func main() {
	store, err := credentials.NewStore("example/path/config.json", credentials.StoreOptions{})
	if err != nil {
		panic(err)
	}
	err = credentials.Logout(context.Background(), store, "localhost:5000")
	if err != nil {
		panic(err)
	}
	fmt.Println("Logout succeeded")
}
Output:

func ServerAddressFromHostname

func ServerAddressFromHostname(hostname string) string

ServerAddressFromHostname maps a hostname to a server address, which is used as a key for credentials store. It is expected that the traffic targetting the host "registry-1.docker.io" will be redirected to "https://index.docker.io/v1/". See: https://github.com/moby/moby/blob/v24.0.2/registry/config.go#L25-L48

func ServerAddressFromRegistry

func ServerAddressFromRegistry(registry string) string

ServerAddressFromRegistry maps a registry to a server address, which is used as a key for credentials store. The Docker CLI expects that the credentials of the registry 'docker.io' will be added under the key "https://index.docker.io/v1/". See: https://github.com/moby/moby/blob/v24.0.2/registry/config.go#L25-L48

Types

type DynamicStore

type DynamicStore struct {
	// contains filtered or unexported fields
}

DynamicStore dynamically determines which store to use based on the settings in the config file.

func NewStore

func NewStore(configPath string, opts StoreOptions) (*DynamicStore, error)

NewStore returns a Store based on the given configuration file.

For Get(), Put() and Delete(), the returned Store will dynamically determine which underlying credentials store to use for the given server address. The underlying credentials store is determined in the following order:

  1. Native server-specific credential helper
  2. Native credentials store
  3. The plain-text config file itself

References:

Example
package main

import (
	"context"
	"fmt"

	"oras.land/oras-go/v2/registry/remote/auth"

	credentials "oras.land/oras-go/v2/registry/remote/credentials"
)

func main() {
	// NewStore returns a Store based on the given configuration file. It will
	// automatically determine which Store (file store or native store) to use.
	// If the native store is not available, you can save your credentials in
	// the configuration file by specifying AllowPlaintextPut: true, but keep
	// in mind that this is an unsafe workaround.
	// See the documentation for details.
	store, err := credentials.NewStore("example/path/config.json", credentials.StoreOptions{
		AllowPlaintextPut: true,
	})
	if err != nil {
		panic(err)
	}

	ctx := context.Background()
	// save credentials into the store
	err = store.Put(ctx, "localhost:5000", auth.Credential{
		Username: "username-example",
		Password: "password-example",
	})
	if err != nil {
		panic(err)
	}

	// get credentials from the store
	cred, err := store.Get(ctx, "localhost:5000")
	if err != nil {
		panic(err)
	}
	fmt.Println(cred)

	// delete the credentials from the store
	err = store.Delete(ctx, "localhost:5000")
	if err != nil {
		panic(err)
	}
}
Output:

func NewStoreFromDocker

func NewStoreFromDocker(opt StoreOptions) (*DynamicStore, error)

NewStoreFromDocker returns a Store based on the default docker config file.

  • If the $DOCKER_CONFIG environment variable is set, $DOCKER_CONFIG/config.json will be used.
  • Otherwise, the default location $HOME/.docker/config.json will be used.

NewStoreFromDocker internally calls NewStore.

References:

Example
package main

import (
	"context"
	"fmt"

	"oras.land/oras-go/v2/registry/remote/auth"

	credentials "oras.land/oras-go/v2/registry/remote/credentials"
)

func main() {
	ds, err := credentials.NewStoreFromDocker(credentials.StoreOptions{
		AllowPlaintextPut: true,
	})
	if err != nil {
		panic(err)
	}

	ctx := context.Background()
	// save credentials into the store
	err = ds.Put(ctx, "localhost:5000", auth.Credential{
		Username: "username-example",
		Password: "password-example",
	})
	if err != nil {
		panic(err)
	}

	// get credentials from the store
	cred, err := ds.Get(ctx, "localhost:5000")
	if err != nil {
		panic(err)
	}
	fmt.Println(cred)

	// delete the credentials from the store
	err = ds.Delete(ctx, "localhost:5000")
	if err != nil {
		panic(err)
	}
}
Output:

func (*DynamicStore) ConfigPath

func (ds *DynamicStore) ConfigPath() string

ConfigPath returns the path to the config file.

func (*DynamicStore) Delete

func (ds *DynamicStore) Delete(ctx context.Context, serverAddress string) error

Delete removes credentials from the store for the given server address.

func (*DynamicStore) Get

func (ds *DynamicStore) Get(ctx context.Context, serverAddress string) (auth.Credential, error)

Get retrieves credentials from the store for the given server address.

func (*DynamicStore) IsAuthConfigured

func (ds *DynamicStore) IsAuthConfigured() bool

IsAuthConfigured returns whether there is authentication configured in the config file or not.

IsAuthConfigured returns true when:

  • The "credsStore" field is not empty
  • Or the "credHelpers" field is not empty
  • Or there is any entry in the "auths" field

func (*DynamicStore) Put

func (ds *DynamicStore) Put(ctx context.Context, serverAddress string, cred auth.Credential) error

Put saves credentials into the store for the given server address. Put returns ErrPlaintextPutDisabled if native store is not available and StoreOptions.AllowPlaintextPut is set to false.

type FileStore

type FileStore struct {
	// DisablePut disables putting credentials in plaintext.
	// If DisablePut is set to true, Put() will return ErrPlaintextPutDisabled.
	DisablePut bool
	// contains filtered or unexported fields
}

FileStore implements a credentials store using the docker configuration file to keep the credentials in plain-text.

Reference: https://docs.docker.com/engine/reference/commandline/cli/#docker-cli-configuration-file-configjson-properties

func NewFileStore

func NewFileStore(configPath string) (*FileStore, error)

NewFileStore creates a new file credentials store.

Reference: https://docs.docker.com/engine/reference/commandline/cli/#docker-cli-configuration-file-configjson-properties

Example
package main

import (
	"context"
	"fmt"

	"oras.land/oras-go/v2/registry/remote/auth"

	credentials "oras.land/oras-go/v2/registry/remote/credentials"
)

func main() {
	fs, err := credentials.NewFileStore("example/path/config.json")
	if err != nil {
		panic(err)
	}

	ctx := context.Background()
	// save credentials into the store
	err = fs.Put(ctx, "localhost:5000", auth.Credential{
		Username: "username-example",
		Password: "password-example",
	})
	if err != nil {
		panic(err)
	}

	// get credentials from the store
	cred, err := fs.Get(ctx, "localhost:5000")
	if err != nil {
		panic(err)
	}
	fmt.Println(cred)

	// delete the credentials from the store
	err = fs.Delete(ctx, "localhost:5000")
	if err != nil {
		panic(err)
	}
}
Output:

func (*FileStore) Delete

func (fs *FileStore) Delete(_ context.Context, serverAddress string) error

Delete removes credentials from the store for the given server address.

func (*FileStore) Get

func (fs *FileStore) Get(_ context.Context, serverAddress string) (auth.Credential, error)

Get retrieves credentials from the store for the given server address.

func (*FileStore) Put

func (fs *FileStore) Put(_ context.Context, serverAddress string, cred auth.Credential) error

Put saves credentials into the store for the given server address. Returns ErrPlaintextPutDisabled if fs.DisablePut is set to true.

type Store

type Store interface {
	// Get retrieves credentials from the store for the given server address.
	Get(ctx context.Context, serverAddress string) (auth.Credential, error)
	// Put saves credentials into the store for the given server address.
	Put(ctx context.Context, serverAddress string, cred auth.Credential) error
	// Delete removes credentials from the store for the given server address.
	Delete(ctx context.Context, serverAddress string) error
}

Store is the interface that any credentials store must implement.

func NewDefaultNativeStore

func NewDefaultNativeStore() (Store, bool)

NewDefaultNativeStore returns a native store based on the platform-default docker credentials helper and a bool indicating if the native store is available.

  • Windows: "wincred"
  • Linux: "pass" or "secretservice"
  • macOS: "osxkeychain"

Reference:

func NewMemoryStore

func NewMemoryStore() Store

NewMemoryStore creates a new in-memory credentials store.

func NewNativeStore

func NewNativeStore(helperSuffix string) Store

NewNativeStore creates a new native store that uses a remote helper program to manage credentials.

The argument of NewNativeStore can be the native keychains ("wincred" for Windows, "pass" for linux and "osxkeychain" for macOS), or any program that follows the docker-credentials-helper protocol.

Reference:

Example
package main

import (
	"context"
	"fmt"

	"oras.land/oras-go/v2/registry/remote/auth"

	credentials "oras.land/oras-go/v2/registry/remote/credentials"
)

func main() {
	ns := credentials.NewNativeStore("pass")

	ctx := context.Background()
	// save credentials into the store
	err := ns.Put(ctx, "localhost:5000", auth.Credential{
		Username: "username-example",
		Password: "password-example",
	})
	if err != nil {
		panic(err)
	}

	// get credentials from the store
	cred, err := ns.Get(ctx, "localhost:5000")
	if err != nil {
		panic(err)
	}
	fmt.Println(cred)

	// delete the credentials from the store
	err = ns.Delete(ctx, "localhost:5000")
	if err != nil {
		panic(err)
	}
}
Output:

func NewStoreWithFallbacks

func NewStoreWithFallbacks(primary Store, fallbacks ...Store) Store

NewStoreWithFallbacks returns a new store based on the given stores.

  • Get() searches the primary and the fallback stores for the credentials and returns when it finds the credentials in any of the stores.
  • Put() saves the credentials into the primary store.
  • Delete() deletes the credentials from the primary store.
Example (ConfigAsPrimaryStoreDockerAsFallback)
package main

import (
	"context"
	"fmt"

	"oras.land/oras-go/v2/registry/remote/auth"

	credentials "oras.land/oras-go/v2/registry/remote/credentials"
)

func main() {
	primaryStore, err := credentials.NewStore("example/path/config.json", credentials.StoreOptions{
		AllowPlaintextPut: true,
	})
	if err != nil {
		panic(err)
	}
	fallbackStore, err := credentials.NewStoreFromDocker(credentials.StoreOptions{})
	sf := credentials.NewStoreWithFallbacks(primaryStore, fallbackStore)

	ctx := context.Background()
	// save credentials into the store
	err = sf.Put(ctx, "localhost:5000", auth.Credential{
		Username: "username-example",
		Password: "password-example",
	})
	if err != nil {
		panic(err)
	}

	// get credentials from the store
	cred, err := sf.Get(ctx, "localhost:5000")
	if err != nil {
		panic(err)
	}
	fmt.Println(cred)

	// delete the credentials from the store
	err = sf.Delete(ctx, "localhost:5000")
	if err != nil {
		panic(err)
	}
}
Output:

type StoreOptions

type StoreOptions struct {
	// AllowPlaintextPut allows saving credentials in plaintext in the config
	// file.
	//   - If AllowPlaintextPut is set to false (default value), Put() will
	//     return an error when native store is not available.
	//   - If AllowPlaintextPut is set to true, Put() will save credentials in
	//     plaintext in the config file when native store is not available.
	AllowPlaintextPut bool

	// DetectDefaultNativeStore enables detecting the platform-default native
	// credentials store when the config file has no authentication information.
	//
	// If DetectDefaultNativeStore is set to true, the store will detect and set
	// the default native credentials store in the "credsStore" field of the
	// config file.
	//   - Windows: "wincred"
	//   - Linux: "pass" or "secretservice"
	//   - macOS: "osxkeychain"
	//
	// References:
	//   - https://docs.docker.com/engine/reference/commandline/login/#credentials-store
	//   - https://docs.docker.com/engine/reference/commandline/cli/#docker-cli-configuration-file-configjson-properties
	DetectDefaultNativeStore bool
}

StoreOptions provides options for NewStore.

Directories

Path Synopsis
internal
executer
Package executer is an abstraction for the docker credential helper protocol binaries.
Package executer is an abstraction for the docker credential helper protocol binaries.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL