From dc80267b594e41cf7e223821dc1446683f0cae36 Mon Sep 17 00:00:00 2001 From: Valentin Rothberg Date: Wed, 13 May 2020 13:44:29 +0200 Subject: compat handlers: add X-Registry-Auth header support * Support the `X-Registry-Auth` http-request header. * The content of the header is a base64 encoded JSON payload which can either be a single auth config or a map of auth configs (user+pw or token) with the corresponding registries being the keys. Vanilla Docker, projectatomic Docker and the bindings are transparantly supported. * Add a hidden `--registries-conf` flag. Buildah exposes the same flag, mostly for testing purposes. * Do all credential parsing in the client (i.e., `cmd/podman`) pass the username and password in the backend instead of unparsed credentials. * Add a `pkg/auth` which handles most of the heavy lifting. * Go through the authentication-handling code of most commands, bindings and endpoints. Migrate them to the new code and fix issues as seen. A final evaluation and more tests is still required *after* this change. * The manifest-push endpoint is missing certain parameters and should use the ABI function instead. Adding auth-support isn't really possible without these parts working. * The container commands and endpoints (i.e., create and run) have not been changed yet. The APIs don't yet account for the authfile. * Add authentication tests to `pkg/bindings`. Fixes: #6384 Signed-off-by: Valentin Rothberg --- pkg/bindings/images/images.go | 58 +++++++++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 18 deletions(-) (limited to 'pkg/bindings/images/images.go') diff --git a/pkg/bindings/images/images.go b/pkg/bindings/images/images.go index f9c02d199..e0802a6e1 100644 --- a/pkg/bindings/images/images.go +++ b/pkg/bindings/images/images.go @@ -12,6 +12,7 @@ import ( "github.com/containers/buildah" "github.com/containers/image/v5/types" "github.com/containers/libpod/pkg/api/handlers" + "github.com/containers/libpod/pkg/auth" "github.com/containers/libpod/pkg/bindings" "github.com/containers/libpod/pkg/domain/entities" "github.com/docker/go-units" @@ -26,7 +27,7 @@ func Exists(ctx context.Context, nameOrID string) (bool, error) { if err != nil { return false, err } - response, err := conn.DoRequest(nil, http.MethodGet, "/images/%s/exists", nil, nameOrID) + response, err := conn.DoRequest(nil, http.MethodGet, "/images/%s/exists", nil, nil, nameOrID) if err != nil { return false, err } @@ -52,7 +53,7 @@ func List(ctx context.Context, all *bool, filters map[string][]string) ([]*entit } params.Set("filters", strFilters) } - response, err := conn.DoRequest(nil, http.MethodGet, "/images/json", params) + response, err := conn.DoRequest(nil, http.MethodGet, "/images/json", params, nil) if err != nil { return imageSummary, err } @@ -71,7 +72,7 @@ func GetImage(ctx context.Context, nameOrID string, size *bool) (*entities.Image params.Set("size", strconv.FormatBool(*size)) } inspectedData := entities.ImageInspectReport{} - response, err := conn.DoRequest(nil, http.MethodGet, "/images/%s/json", params, nameOrID) + response, err := conn.DoRequest(nil, http.MethodGet, "/images/%s/json", params, nil, nameOrID) if err != nil { return &inspectedData, err } @@ -89,7 +90,7 @@ func Tree(ctx context.Context, nameOrId string, whatRequires *bool) (*entities.I if whatRequires != nil { params.Set("size", strconv.FormatBool(*whatRequires)) } - response, err := conn.DoRequest(nil, http.MethodGet, "/images/%s/tree", params, nameOrId) + response, err := conn.DoRequest(nil, http.MethodGet, "/images/%s/tree", params, nil, nameOrId) if err != nil { return nil, err } @@ -103,7 +104,7 @@ func History(ctx context.Context, nameOrID string) ([]*handlers.HistoryResponse, if err != nil { return nil, err } - response, err := conn.DoRequest(nil, http.MethodGet, "/images/%s/history", nil, nameOrID) + response, err := conn.DoRequest(nil, http.MethodGet, "/images/%s/history", nil, nil, nameOrID) if err != nil { return history, err } @@ -120,7 +121,7 @@ func Load(ctx context.Context, r io.Reader, name *string) (*entities.ImageLoadRe if name != nil { params.Set("reference", *name) } - response, err := conn.DoRequest(r, http.MethodPost, "/images/load", params) + response, err := conn.DoRequest(r, http.MethodPost, "/images/load", params, nil) if err != nil { return nil, err } @@ -141,7 +142,7 @@ func Export(ctx context.Context, nameOrID string, w io.Writer, format *string, c if compress != nil { params.Set("compress", strconv.FormatBool(*compress)) } - response, err := conn.DoRequest(nil, http.MethodGet, "/images/%s/get", params, nameOrID) + response, err := conn.DoRequest(nil, http.MethodGet, "/images/%s/get", params, nil, nameOrID) if err != nil { return err } @@ -174,7 +175,7 @@ func Prune(ctx context.Context, all *bool, filters map[string][]string) ([]strin } params.Set("filters", stringFilter) } - response, err := conn.DoRequest(nil, http.MethodPost, "/images/prune", params) + response, err := conn.DoRequest(nil, http.MethodPost, "/images/prune", params, nil) if err != nil { return deleted, err } @@ -190,7 +191,7 @@ func Tag(ctx context.Context, nameOrID, tag, repo string) error { params := url.Values{} params.Set("tag", tag) params.Set("repo", repo) - response, err := conn.DoRequest(nil, http.MethodPost, "/images/%s/tag", params, nameOrID) + response, err := conn.DoRequest(nil, http.MethodPost, "/images/%s/tag", params, nil, nameOrID) if err != nil { return err } @@ -206,7 +207,7 @@ func Untag(ctx context.Context, nameOrID, tag, repo string) error { params := url.Values{} params.Set("tag", tag) params.Set("repo", repo) - response, err := conn.DoRequest(nil, http.MethodPost, "/images/%s/untag", params, nameOrID) + response, err := conn.DoRequest(nil, http.MethodPost, "/images/%s/untag", params, nil, nameOrID) if err != nil { return err } @@ -297,7 +298,7 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO } // TODO outputs? - response, err := conn.DoRequest(tarfile, http.MethodPost, "/build", params) + response, err := conn.DoRequest(tarfile, http.MethodPost, "/build", params, nil) if err != nil { return nil, err } @@ -341,7 +342,7 @@ func Import(ctx context.Context, changes []string, message, reference, u *string if u != nil { params.Set("url", *u) } - response, err := conn.DoRequest(r, http.MethodPost, "/images/import", params) + response, err := conn.DoRequest(r, http.MethodPost, "/images/import", params, nil) if err != nil { return nil, err } @@ -359,7 +360,6 @@ func Pull(ctx context.Context, rawImage string, options entities.ImagePullOption } params := url.Values{} params.Set("reference", rawImage) - params.Set("credentials", options.Credentials) params.Set("overrideArch", options.OverrideArch) params.Set("overrideOS", options.OverrideOS) if options.SkipTLSVerify != types.OptionalBoolUndefined { @@ -369,7 +369,13 @@ func Pull(ctx context.Context, rawImage string, options entities.ImagePullOption } params.Set("allTags", strconv.FormatBool(options.AllTags)) - response, err := conn.DoRequest(nil, http.MethodPost, "/images/pull", params) + // TODO: have a global system context we can pass around (1st argument) + header, err := auth.Header(nil, options.Authfile, options.Username, options.Password) + if err != nil { + return nil, err + } + + response, err := conn.DoRequest(nil, http.MethodPost, "/images/pull", params, header) if err != nil { return nil, err } @@ -397,8 +403,14 @@ func Push(ctx context.Context, source string, destination string, options entiti if err != nil { return err } + + // TODO: have a global system context we can pass around (1st argument) + header, err := auth.Header(nil, options.Authfile, options.Username, options.Password) + if err != nil { + return err + } + params := url.Values{} - params.Set("credentials", options.Credentials) params.Set("destination", destination) if options.SkipTLSVerify != types.OptionalBoolUndefined { // Note: we have to verify if skipped is false. @@ -407,8 +419,12 @@ func Push(ctx context.Context, source string, destination string, options entiti } path := fmt.Sprintf("/images/%s/push", source) - _, err = conn.DoRequest(nil, http.MethodPost, path, params) - return err + response, err := conn.DoRequest(nil, http.MethodPost, path, params, header) + if err != nil { + return err + } + + return response.Process(err) } // Search is the binding for libpod's v2 endpoints for Search images. @@ -430,7 +446,13 @@ func Search(ctx context.Context, term string, opts entities.ImageSearchOptions) params.Set("tlsVerify", strconv.FormatBool(verifyTLS)) } - response, err := conn.DoRequest(nil, http.MethodGet, "/images/search", params) + // TODO: have a global system context we can pass around (1st argument) + header, err := auth.Header(nil, opts.Authfile, "", "") + if err != nil { + return nil, err + } + + response, err := conn.DoRequest(nil, http.MethodGet, "/images/search", params, header) if err != nil { return nil, err } -- cgit v1.2.3-54-g00ecf