Files
Valentin Rothberg dc80267b59 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 <rothberg@redhat.com>
2020-05-29 15:39:37 +02:00

83 lines
2.6 KiB
Go

package libpod
import (
"io"
"io/ioutil"
"net/http"
"os"
"github.com/containers/image/v5/types"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/api/handlers/utils"
"github.com/containers/libpod/pkg/auth"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/containers/libpod/pkg/domain/infra/abi"
"github.com/gorilla/schema"
"github.com/pkg/errors"
)
func PlayKube(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value("runtime").(*libpod.Runtime)
decoder := r.Context().Value("decoder").(*schema.Decoder)
query := struct {
Network string `schema:"reference"`
TLSVerify bool `schema:"tlsVerify"`
}{
TLSVerify: true,
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
// Fetch the K8s YAML file from the body, and copy it to a temp file.
tmpfile, err := ioutil.TempFile("", "libpod-play-kube.yml")
if err != nil {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile"))
return
}
defer os.Remove(tmpfile.Name())
if _, err := io.Copy(tmpfile, r.Body); err != nil && err != io.EOF {
tmpfile.Close()
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to write archive to temporary file"))
return
}
if err := tmpfile.Close(); err != nil {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "error closing temporary file"))
return
}
authConf, authfile, err := auth.GetCredentials(r)
if err != nil {
utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "Failed to parse %q header for %s", auth.XRegistryAuthHeader, r.URL.String()))
return
}
defer auth.RemoveAuthfile(authfile)
var username, password string
if authConf != nil {
username = authConf.Username
password = authConf.Password
}
containerEngine := abi.ContainerEngine{Libpod: runtime}
options := entities.PlayKubeOptions{
Authfile: authfile,
Username: username,
Password: password,
Network: query.Network,
Quiet: true,
}
if _, found := r.URL.Query()["tlsVerify"]; found {
options.SkipTLSVerify = types.NewOptionalBool(!query.TLSVerify)
}
report, err := containerEngine.PlayKube(r.Context(), tmpfile.Name(), options)
if err != nil {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "error playing YAML file"))
return
}
utils.WriteResponse(w, http.StatusOK, report)
}