auth

package
v2.0.0-rc.3 Latest Latest
Warning

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

Go to latest
Published: Sep 7, 2022 License: Apache-2.0 Imports: 15 Imported by: 71

Documentation

Overview

Package auth provides authentication for a client to a remote registry.

Index

Examples

Constants

View Source
const (
	// ActionPull represents generic read access for resources of the repository
	// type.
	ActionPull = "pull"

	// ActionPush represents generic write access for resources of the
	// repository type.
	ActionPush = "push"

	// ActionDelete represents the delete permission for resources of the
	// repository type.
	ActionDelete = "delete"
)

Actions used in scopes. Reference: https://docs.docker.com/registry/spec/auth/scope/

View Source
const ScopeRegistryCatalog = "registry:catalog:*"

ScopeRegistryCatalog is the scope for registry catalog access.

Variables

View Source
var DefaultClient = &Client{
	Header: http.Header{
		"User-Agent": {"oras-go"},
	},
	Cache: DefaultCache,
}

DefaultClient is the default auth-decorated client.

Functions

func AppendScopes

func AppendScopes(ctx context.Context, scopes ...string) context.Context

AppendScopes appends additional scopes to the existing scopes in the context and returns a new context. The resulted scopes are de-duplicated. The append operation does modify the existing scope in the context passed in.

func CleanScopes

func CleanScopes(scopes []string) []string

CleanScopes merges and sort the actions in ascending order if the scopes have the same resource type and name. The final scopes are sorted in ascending order. In other words, the scopes passed in are de-duplicated and sorted. Therefore, the output of this function is deterministic. If there is a wildcard `*` in the action, other actions in the same resource type and name are ignored.

func GetScopes

func GetScopes(ctx context.Context) []string

GetScopes returns the scopes in the context.

func ScopeRepository

func ScopeRepository(repository string, actions ...string) string

ScopeRepository returns a repository scope with given actions. Reference: https://docs.docker.com/registry/spec/auth/scope/

func StaticCredential

func StaticCredential(registry string, cred Credential) func(context.Context, string) (Credential, error)

StaticCredential specifies static credentials for the given host.

func WithScopes

func WithScopes(ctx context.Context, scopes ...string) context.Context

WithScopes returns a context with scopes added. Scopes are de-duplicated. Scopes are used as hints for the auth client to fetch bearer tokens with larger scopes. For example, uploading blob to the repository "hello-world" does HEAD request first then POST and PUT. The HEAD request will return a challenge for scope `repository:hello-world:pull`, and the auth client will fetch a token for that challenge. Later, the POST request will return a challenge for scope `repository:hello-world:push`, and the auth client will fetch a token for that challenge again. By invoking `WithScopes()` with the scope `repository:hello-world:pull,push`, the auth client with cache is hinted to fetch a token via a single token fetch request for all the HEAD, POST, PUT requests. Passing an empty list of scopes will virtually remove the scope hints in the context. Reference: https://docs.docker.com/registry/spec/auth/scope/

Types

type Cache

type Cache interface {
	// GetScheme returns the auth-scheme part cached for the given registry.
	// A single registry is assumed to have a consistent scheme.
	// If a registry has different schemes per path, the auth client is still
	// workable. However, the cache may not be effective as the cache cannot
	// correctly guess the scheme.
	GetScheme(ctx context.Context, registry string) (Scheme, error)

	// GetToken returns the auth-token part cached for the given registry of a
	// given scheme.
	// The underlying implementation MAY cache the token for all schemes for the
	// given registry.
	GetToken(ctx context.Context, registry string, scheme Scheme, key string) (string, error)

	// Set fetches the token using the given fetch function and caches the token
	// for the given scheme with the given key for the given registry.
	// The return values of the fetch function is returned by this function.
	// The underlying implementation MAY combine the fetch operation if the Set
	// function is invoked multiple times at the same time.
	Set(ctx context.Context, registry string, scheme Scheme, key string, fetch func(context.Context) (string, error)) (string, error)
}

Cache caches the auth-scheme and auth-token for the "Authorization" header in accessing the remote registry. Precisely, the header is `Authorization: auth-scheme auth-token`. The `auth-token` is a generic term as `token68` in RFC 7235 section 2.1.

var DefaultCache Cache = NewCache()

DefaultCache is the sharable cache used by DefaultClient.

func NewCache

func NewCache() Cache

NewCache creates a new go-routine safe cache instance.

type Client

type Client struct {
	// Client is the underlying HTTP client used to access the remote
	// server.
	// If nil, http.DefaultClient is used.
	Client *http.Client

	// Header contains the custom headers to be added to each request.
	Header http.Header

	// Credential specifies the function for resolving the credential for the
	// given registry (i.e. host:port).
	// `EmptyCredential` is a valid return value and should not be considered as
	// an error.
	// If nil, the credential is always resolved to `EmptyCredential`.
	Credential func(context.Context, string) (Credential, error)

	// Cache caches credentials for direct accessing the remote registry.
	// If nil, no cache is used.
	Cache Cache

	// ClientID used in fetching OAuth2 token as a required field.
	// If empty, a default client ID is used.
	// Reference: https://docs.docker.com/registry/spec/auth/oauth/#getting-a-token
	ClientID string

	// ForceAttemptOAuth2 controls whether to follow OAuth2 with password grant
	// instead the distribution spec when authenticating using username and
	// password.
	// References:
	// - https://docs.docker.com/registry/spec/auth/jwt/
	// - https://docs.docker.com/registry/spec/auth/oauth/
	ForceAttemptOAuth2 bool
}

Client is an auth-decorated HTTP client. Its zero value is a usable client that uses http.DefaultClient with no cache.

func (*Client) Do

func (c *Client) Do(originalReq *http.Request) (*http.Response, error)

Do sends the request to the remote server, attempting to resolve authentication if 'Authorization' header is not set. On authentication failure due to bad credential, - Do returns error if it fails to fetch token for bearer auth. - Do returns the registry response without error for basic auth.

Example (BasicAuth)

ExampleClient_Do_basicAuth gives an example of using client with credentials.

client := &auth.Client{
	// expectedHostAddress is of form ipaddr:port
	Credential: auth.StaticCredential(expectedHostAddress, auth.Credential{
		Username: username,
		Password: password,
	}),
}
// basicAuthTargetURL can be any URL. For example, https://registry.wabbit-networks.io/v2/
req, err := http.NewRequest(http.MethodGet, basicAuthTargetURL, nil)
if err != nil {
	panic(err)
}
resp, err := client.Do(req)
if err != nil {
	panic(err)
}

fmt.Println(resp.StatusCode)
Output:

200
Example (ClientConfigurations)

ExampleClient_Do_clientConfigurations shows the client configurations available, including using cache, setting user agent and configuring OAuth2.

client := &auth.Client{
	// expectedHostAddress is of form ipaddr:port
	Credential: auth.StaticCredential(expectedHostAddress, auth.Credential{
		Username: username,
		Password: password,
	}),
	// ForceAttemptOAuth2 controls whether to follow OAuth2 with password grant.
	ForceAttemptOAuth2: true,
	// Cache caches credentials for accessing the remote registry.
	Cache: auth.NewCache(),
}
// SetUserAgent sets the user agent for all out-going requests.
client.SetUserAgent("example user agent")
// Tokens carry restrictions about what resources they can access and how.
// Such restrictions are represented and enforced as Scopes.
// Reference: https://docs.docker.com/registry/spec/auth/scope/
scopes := []string{
	"repository:dst:pull,push",
	"repository:src:pull",
}
// WithScopes returns a context with scopes added.
ctx := auth.WithScopes(context.Background(), scopes...)

// clientConfigTargetURL can be any URL. For example, https://registry.wabbit-networks.io/v2/
req, err := http.NewRequestWithContext(ctx, http.MethodGet, clientConfigTargetURL, nil)
if err != nil {
	panic(err)
}
resp, err := client.Do(req)
if err != nil {
	panic(err)
}

fmt.Println(resp.StatusCode)
Output:

200
Example (MinimalClient)

ExampleClient_Do_minimalClient gives an example of a minimal working client.

var client auth.Client
// targetURL can be any URL. For example, https://registry.wabbit-networks.io/v2/
req, err := http.NewRequest(http.MethodGet, targetURL, nil)
if err != nil {
	panic(err)
}
resp, err := client.Do(req)
if err != nil {
	panic(err)
}

fmt.Println(resp.StatusCode)
Output:

200
Example (WithAccessToken)

ExampleClient_Do_withAccessToken gives an example of using client with an access token.

client := &auth.Client{
	// expectedHostAddress is of form ipaddr:port
	Credential: auth.StaticCredential(expectedHostAddress, auth.Credential{
		AccessToken: accessToken,
	}),
}
// accessTokenTargetURL can be any URL. For example, https://registry.wabbit-networks.io/v2/
req, err := http.NewRequest(http.MethodGet, accessTokenTargetURL, nil)
if err != nil {
	panic(err)
}
resp, err := client.Do(req)
if err != nil {
	panic(err)
}

fmt.Println(resp.StatusCode)
Output:

200
Example (WithRefreshToken)

ExampleClient_Do_withRefreshToken gives an example of using client with a refresh token.

client := &auth.Client{
	// expectedHostAddress is of form ipaddr:port
	Credential: auth.StaticCredential(expectedHostAddress, auth.Credential{
		RefreshToken: refreshToken,
	}),
}

// refreshTokenTargetURL can be any URL. For example, https://registry.wabbit-networks.io/v2/
req, err := http.NewRequest(http.MethodGet, refreshTokenTargetURL, nil)
if err != nil {
	panic(err)
}
resp, err := client.Do(req)
if err != nil {
	panic(err)
}

fmt.Println(resp.StatusCode)
Output:

200

func (*Client) SetUserAgent

func (c *Client) SetUserAgent(userAgent string)

SetUserAgent sets the user agent for all out-going requests.

type Credential

type Credential struct {
	// Username is the name of the user for the remote registry.
	Username string

	// Password is the secret associated with the username.
	Password string

	// RefreshToken is a bearer token to be sent to the authorization service
	// for fetching access tokens.
	// A refresh token is often referred as an identity token.
	// Reference: https://docs.docker.com/registry/spec/auth/oauth/
	RefreshToken string

	// AccessToken is a bearer token to be sent to the registry.
	// An access token is often referred as a registry token.
	// Reference: https://docs.docker.com/registry/spec/auth/token/
	AccessToken string
}

Credential contains authentication credentials used to access remote registries.

var EmptyCredential Credential

EmptyCredential represents an empty credential.

type Scheme

type Scheme byte

Scheme define the authentication method.

const (
	// SchemeUnknown represents unknown or unsupported schemes
	SchemeUnknown Scheme = iota

	// SchemeBasic represents the "Basic" HTTP authentication scheme.
	// Reference: https://tools.ietf.org/html/rfc7617
	SchemeBasic

	// SchemeBearer represents the Bearer token in OAuth 2.0.
	// Reference: https://tools.ietf.org/html/rfc6750
	SchemeBearer
)

func (Scheme) String

func (s Scheme) String() string

String return the string for the scheme.

Jump to

Keyboard shortcuts

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