mirror of
https://github.com/containers/podman.git
synced 2025-08-16 12:28:48 +08:00

* 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>
144 lines
3.8 KiB
Go
144 lines
3.8 KiB
Go
package test_bindings
|
|
|
|
import (
|
|
"io/ioutil"
|
|
"os"
|
|
"time"
|
|
|
|
"github.com/containers/common/pkg/auth"
|
|
"github.com/containers/image/v5/types"
|
|
podmanRegistry "github.com/containers/libpod/hack/podman-registry-go"
|
|
"github.com/containers/libpod/pkg/bindings/images"
|
|
"github.com/containers/libpod/pkg/domain/entities"
|
|
. "github.com/onsi/ginkgo"
|
|
. "github.com/onsi/gomega"
|
|
"github.com/onsi/gomega/gexec"
|
|
)
|
|
|
|
var _ = Describe("Podman images", func() {
|
|
var (
|
|
registry *podmanRegistry.Registry
|
|
bt *bindingTest
|
|
s *gexec.Session
|
|
err error
|
|
)
|
|
|
|
BeforeEach(func() {
|
|
// Note: we need to start the registry **before** setting up
|
|
// the test. Otherwise, the registry is not reachable for
|
|
// currently unknown reasons.
|
|
registry, err = podmanRegistry.Start()
|
|
Expect(err).To(BeNil())
|
|
|
|
bt = newBindingTest()
|
|
bt.RestoreImagesFromCache()
|
|
s = bt.startAPIService()
|
|
time.Sleep(1 * time.Second)
|
|
err := bt.NewConnection()
|
|
Expect(err).To(BeNil())
|
|
})
|
|
|
|
AfterEach(func() {
|
|
s.Kill()
|
|
bt.cleanup()
|
|
registry.Stop()
|
|
})
|
|
|
|
// Test using credentials.
|
|
It("tag + push + pull (with credentials)", func() {
|
|
|
|
imageRep := "localhost:" + registry.Port + "/test"
|
|
imageTag := "latest"
|
|
imageRef := imageRep + ":" + imageTag
|
|
|
|
// Tag the alpine image and verify it has worked.
|
|
err = images.Tag(bt.conn, alpine.shortName, imageTag, imageRep)
|
|
Expect(err).To(BeNil())
|
|
_, err = images.GetImage(bt.conn, imageRef, nil)
|
|
Expect(err).To(BeNil())
|
|
|
|
// Now push the image.
|
|
pushOpts := entities.ImagePushOptions{
|
|
Username: registry.User,
|
|
Password: registry.Password,
|
|
SkipTLSVerify: types.OptionalBoolTrue,
|
|
}
|
|
err = images.Push(bt.conn, imageRef, imageRef, pushOpts)
|
|
Expect(err).To(BeNil())
|
|
|
|
// Now pull the image.
|
|
pullOpts := entities.ImagePullOptions{
|
|
Username: registry.User,
|
|
Password: registry.Password,
|
|
SkipTLSVerify: types.OptionalBoolTrue,
|
|
}
|
|
_, err = images.Pull(bt.conn, imageRef, pullOpts)
|
|
Expect(err).To(BeNil())
|
|
})
|
|
|
|
// Test using authfile.
|
|
It("tag + push + pull + search (with authfile)", func() {
|
|
|
|
imageRep := "localhost:" + registry.Port + "/test"
|
|
imageTag := "latest"
|
|
imageRef := imageRep + ":" + imageTag
|
|
|
|
// Create a temporary authentication file.
|
|
tmpFile, err := ioutil.TempFile("", "auth.json.")
|
|
Expect(err).To(BeNil())
|
|
_, err = tmpFile.Write([]byte{'{', '}'})
|
|
Expect(err).To(BeNil())
|
|
err = tmpFile.Close()
|
|
Expect(err).To(BeNil())
|
|
|
|
authFilePath := tmpFile.Name()
|
|
|
|
// Now login to a) test the credentials and to b) store them in
|
|
// the authfile for later use.
|
|
sys := types.SystemContext{
|
|
AuthFilePath: authFilePath,
|
|
DockerInsecureSkipTLSVerify: types.OptionalBoolTrue,
|
|
}
|
|
loginOptions := auth.LoginOptions{
|
|
Username: registry.User,
|
|
Password: registry.Password,
|
|
AuthFile: authFilePath,
|
|
Stdin: os.Stdin,
|
|
Stdout: os.Stdout,
|
|
}
|
|
err = auth.Login(bt.conn, &sys, &loginOptions, []string{imageRep})
|
|
Expect(err).To(BeNil())
|
|
|
|
// Tag the alpine image and verify it has worked.
|
|
err = images.Tag(bt.conn, alpine.shortName, imageTag, imageRep)
|
|
Expect(err).To(BeNil())
|
|
_, err = images.GetImage(bt.conn, imageRef, nil)
|
|
Expect(err).To(BeNil())
|
|
|
|
// Now push the image.
|
|
pushOpts := entities.ImagePushOptions{
|
|
Authfile: authFilePath,
|
|
SkipTLSVerify: types.OptionalBoolTrue,
|
|
}
|
|
err = images.Push(bt.conn, imageRef, imageRef, pushOpts)
|
|
Expect(err).To(BeNil())
|
|
|
|
// Now pull the image.
|
|
pullOpts := entities.ImagePullOptions{
|
|
Authfile: authFilePath,
|
|
SkipTLSVerify: types.OptionalBoolTrue,
|
|
}
|
|
_, err = images.Pull(bt.conn, imageRef, pullOpts)
|
|
Expect(err).To(BeNil())
|
|
|
|
// Last, but not least, exercise search.
|
|
searchOptions := entities.ImageSearchOptions{
|
|
Authfile: authFilePath,
|
|
SkipTLSVerify: types.OptionalBoolTrue,
|
|
}
|
|
_, err = images.Search(bt.conn, imageRef, searchOptions)
|
|
Expect(err).To(BeNil())
|
|
})
|
|
|
|
})
|