mirror of https://github.com/docker/cli.git
cli/registry/client: set actions when authn with token
When using a personal access token, Docker Hub produces an error if actions are requested beyond the token's allowed actions. This resulted in errors when using a PAT with limited permissions to do a "docker manifest inspect". This patch sets actions to "pull" only by default, and requests "push" action for requests that need it. To verify: - create a PAT with limited access (read-only) - log in with your username and the PAT as password Before this patch: docker manifest inspect ubuntu:latest Get "https://registry-1.docker.io/v2/library/ubuntu/manifests/latest": unauthorized: access token has insufficient scopes With this patch applied: docker manifest inspect ubuntu:latest { "schemaVersion": 2, "mediaType": "application/vnd.oci.image.index.v1+json", "manifests": [ { "mediaType": "application/vnd.oci.image.manifest.v1+json", "size": 424, "digest": "sha256:56887c5194fddd8db7e36ced1c16b3569d89f74c801dc8a5adbf48236fb34564", "platform": { "architecture": "amd64", "os": "linux" } }, { "mediaType": "application/vnd.oci.image.manifest.v1+json", "size": 424, "digest": "sha256:c835a4f2a632bc91a2b494e871549f0dd83f2966c780e66435774e77e048ddf0", "platform": { "architecture": "arm", "os": "linux", "variant": "v7" } } ] } Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
parent
cdabfa2aa5
commit
d2047b954e
|
@ -7,6 +7,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
manifesttypes "github.com/docker/cli/cli/manifest/types"
|
manifesttypes "github.com/docker/cli/cli/manifest/types"
|
||||||
|
"github.com/docker/cli/cli/trust"
|
||||||
"github.com/docker/distribution"
|
"github.com/docker/distribution"
|
||||||
"github.com/docker/distribution/reference"
|
"github.com/docker/distribution/reference"
|
||||||
distributionclient "github.com/docker/distribution/registry/client"
|
distributionclient "github.com/docker/distribution/registry/client"
|
||||||
|
@ -77,6 +78,7 @@ func (c *client) MountBlob(ctx context.Context, sourceRef reference.Canonical, t
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
repoEndpoint.actions = trust.ActionsPushAndPull
|
||||||
repo, err := c.getRepositoryForReference(ctx, targetRef, repoEndpoint)
|
repo, err := c.getRepositoryForReference(ctx, targetRef, repoEndpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -102,6 +104,7 @@ func (c *client) PutManifest(ctx context.Context, ref reference.Named, manifest
|
||||||
return digest.Digest(""), err
|
return digest.Digest(""), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
repoEndpoint.actions = trust.ActionsPushAndPull
|
||||||
repo, err := c.getRepositoryForReference(ctx, ref, repoEndpoint)
|
repo, err := c.getRepositoryForReference(ctx, ref, repoEndpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return digest.Digest(""), err
|
return digest.Digest(""), err
|
||||||
|
@ -151,7 +154,9 @@ func (c *client) getHTTPTransportForRepoEndpoint(ctx context.Context, repoEndpoi
|
||||||
c.authConfigResolver(ctx, repoEndpoint.info.Index),
|
c.authConfigResolver(ctx, repoEndpoint.info.Index),
|
||||||
repoEndpoint.endpoint,
|
repoEndpoint.endpoint,
|
||||||
repoEndpoint.Name(),
|
repoEndpoint.Name(),
|
||||||
c.userAgent)
|
c.userAgent,
|
||||||
|
repoEndpoint.actions,
|
||||||
|
)
|
||||||
return httpTransport, errors.Wrap(err, "failed to configure transport")
|
return httpTransport, errors.Wrap(err, "failed to configure transport")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/docker/cli/cli/trust"
|
||||||
"github.com/docker/distribution/reference"
|
"github.com/docker/distribution/reference"
|
||||||
"github.com/docker/distribution/registry/client/auth"
|
"github.com/docker/distribution/registry/client/auth"
|
||||||
"github.com/docker/distribution/registry/client/transport"
|
"github.com/docker/distribution/registry/client/transport"
|
||||||
|
@ -17,6 +18,7 @@ import (
|
||||||
type repositoryEndpoint struct {
|
type repositoryEndpoint struct {
|
||||||
info *registry.RepositoryInfo
|
info *registry.RepositoryInfo
|
||||||
endpoint registry.APIEndpoint
|
endpoint registry.APIEndpoint
|
||||||
|
actions []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name returns the repository name
|
// Name returns the repository name
|
||||||
|
@ -74,7 +76,7 @@ func getDefaultEndpointFromRepoInfo(repoInfo *registry.RepositoryInfo) (registry
|
||||||
}
|
}
|
||||||
|
|
||||||
// getHTTPTransport builds a transport for use in communicating with a registry
|
// getHTTPTransport builds a transport for use in communicating with a registry
|
||||||
func getHTTPTransport(authConfig registrytypes.AuthConfig, endpoint registry.APIEndpoint, repoName string, userAgent string) (http.RoundTripper, error) {
|
func getHTTPTransport(authConfig registrytypes.AuthConfig, endpoint registry.APIEndpoint, repoName, userAgent string, actions []string) (http.RoundTripper, error) {
|
||||||
// get the http transport, this will be used in a client to upload manifest
|
// get the http transport, this will be used in a client to upload manifest
|
||||||
base := &http.Transport{
|
base := &http.Transport{
|
||||||
Proxy: http.ProxyFromEnvironment,
|
Proxy: http.ProxyFromEnvironment,
|
||||||
|
@ -98,8 +100,11 @@ func getHTTPTransport(authConfig registrytypes.AuthConfig, endpoint registry.API
|
||||||
passThruTokenHandler := &existingTokenHandler{token: authConfig.RegistryToken}
|
passThruTokenHandler := &existingTokenHandler{token: authConfig.RegistryToken}
|
||||||
modifiers = append(modifiers, auth.NewAuthorizer(challengeManager, passThruTokenHandler))
|
modifiers = append(modifiers, auth.NewAuthorizer(challengeManager, passThruTokenHandler))
|
||||||
} else {
|
} else {
|
||||||
|
if len(actions) == 0 {
|
||||||
|
actions = trust.ActionsPullOnly
|
||||||
|
}
|
||||||
creds := registry.NewStaticCredentialStore(&authConfig)
|
creds := registry.NewStaticCredentialStore(&authConfig)
|
||||||
tokenHandler := auth.NewTokenHandler(authTransport, creds, repoName, "push", "pull")
|
tokenHandler := auth.NewTokenHandler(authTransport, creds, repoName, actions...)
|
||||||
basicHandler := auth.NewBasicHandler(creds)
|
basicHandler := auth.NewBasicHandler(creds)
|
||||||
modifiers = append(modifiers, auth.NewAuthorizer(challengeManager, tokenHandler, basicHandler))
|
modifiers = append(modifiers, auth.NewAuthorizer(challengeManager, tokenHandler, basicHandler))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue