2014-02-25 11:17:48 -05:00
package main
import (
2015-05-01 18:01:10 -04:00
"archive/tar"
2014-02-25 11:17:48 -05:00
"fmt"
2015-01-24 16:08:47 -05:00
"io/ioutil"
2016-03-14 16:11:35 -04:00
"net/http"
"net/http/httptest"
2015-01-24 16:08:47 -05:00
"os"
2015-12-23 19:34:46 -05:00
"path/filepath"
2015-01-13 13:46:32 -05:00
"strings"
2016-09-01 18:18:15 -04:00
"sync"
2017-04-17 19:18:46 -04:00
"github.com/docker/distribution/reference"
2017-06-01 16:34:31 -04:00
"github.com/docker/docker/cli/config"
2017-04-17 19:18:46 -04:00
"github.com/docker/docker/integration-cli/checker"
"github.com/docker/docker/integration-cli/cli"
"github.com/docker/docker/integration-cli/cli/build"
icmd "github.com/docker/docker/pkg/testutil/cmd"
"github.com/go-check/check"
2014-02-25 11:17:48 -05:00
)
2015-07-07 04:10:37 -04:00
// Pushing an image to a private registry.
2015-12-18 18:06:23 -05:00
func testPushBusyboxImage ( c * check . C ) {
2015-01-13 13:46:32 -05:00
repoName := fmt . Sprintf ( "%v/dockercli/busybox" , privateRegistryURL )
2015-02-26 21:23:50 -05:00
// tag the image to upload it to the private registry
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "tag" , "busybox" , repoName )
// push the image to the registry
dockerCmd ( c , "push" , repoName )
2014-02-25 11:17:48 -05:00
}
2015-12-18 18:06:23 -05:00
func ( s * DockerRegistrySuite ) TestPushBusyboxImage ( c * check . C ) {
testPushBusyboxImage ( c )
}
func ( s * DockerSchema1RegistrySuite ) TestPushBusyboxImage ( c * check . C ) {
testPushBusyboxImage ( c )
}
2014-02-25 11:17:48 -05:00
// pushing an image without a prefix should throw an error
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestPushUnprefixedRepo ( c * check . C ) {
2015-10-13 08:01:58 -04:00
out , _ , err := dockerCmdWithError ( "push" , "busybox" )
c . Assert ( err , check . NotNil , check . Commentf ( "pushing an unprefixed repo didn't result in a non-zero exit status: %s" , out ) )
2015-01-13 13:46:32 -05:00
}
2015-12-18 18:06:23 -05:00
func testPushUntagged ( c * check . C ) {
2015-01-13 13:46:32 -05:00
repoName := fmt . Sprintf ( "%v/dockercli/busybox" , privateRegistryURL )
2016-04-03 16:25:07 -04:00
expected := "An image does not exist locally with the tag"
2015-10-13 08:01:58 -04:00
out , _ , err := dockerCmdWithError ( "push" , repoName )
c . Assert ( err , check . NotNil , check . Commentf ( "pushing the image to the private registry should have failed: output %q" , out ) )
c . Assert ( out , checker . Contains , expected , check . Commentf ( "pushing the image failed" ) )
2015-01-13 13:46:32 -05:00
}
2015-12-18 18:06:23 -05:00
func ( s * DockerRegistrySuite ) TestPushUntagged ( c * check . C ) {
testPushUntagged ( c )
}
func ( s * DockerSchema1RegistrySuite ) TestPushUntagged ( c * check . C ) {
testPushUntagged ( c )
}
func testPushBadTag ( c * check . C ) {
2015-01-30 17:20:32 -05:00
repoName := fmt . Sprintf ( "%v/dockercli/busybox:latest" , privateRegistryURL )
expected := "does not exist"
2015-07-14 02:35:36 -04:00
2015-10-13 08:01:58 -04:00
out , _ , err := dockerCmdWithError ( "push" , repoName )
c . Assert ( err , check . NotNil , check . Commentf ( "pushing the image to the private registry should have failed: output %q" , out ) )
c . Assert ( out , checker . Contains , expected , check . Commentf ( "pushing the image failed" ) )
2015-01-30 17:20:32 -05:00
}
2015-12-18 18:06:23 -05:00
func ( s * DockerRegistrySuite ) TestPushBadTag ( c * check . C ) {
testPushBadTag ( c )
}
func ( s * DockerSchema1RegistrySuite ) TestPushBadTag ( c * check . C ) {
testPushBadTag ( c )
}
func testPushMultipleTags ( c * check . C ) {
2015-01-30 17:20:32 -05:00
repoName := fmt . Sprintf ( "%v/dockercli/busybox" , privateRegistryURL )
repoTag1 := fmt . Sprintf ( "%v/dockercli/busybox:t1" , privateRegistryURL )
repoTag2 := fmt . Sprintf ( "%v/dockercli/busybox:t2" , privateRegistryURL )
2015-04-23 04:50:41 -04:00
// tag the image and upload it to the private registry
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "tag" , "busybox" , repoTag1 )
2015-01-30 17:20:32 -05:00
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "tag" , "busybox" , repoTag2 )
2015-08-12 21:32:23 -04:00
dockerCmd ( c , "push" , repoName )
2015-08-12 21:36:46 -04:00
// Ensure layer list is equivalent for repoTag1 and repoTag2
out1 , _ := dockerCmd ( c , "pull" , repoTag1 )
2015-10-13 08:01:58 -04:00
2015-08-12 21:36:46 -04:00
imageAlreadyExists := ": Image already exists"
var out1Lines [ ] string
for _ , outputLine := range strings . Split ( out1 , "\n" ) {
if strings . Contains ( outputLine , imageAlreadyExists ) {
out1Lines = append ( out1Lines , outputLine )
}
}
out2 , _ := dockerCmd ( c , "pull" , repoTag2 )
2015-10-13 08:01:58 -04:00
2015-08-12 21:36:46 -04:00
var out2Lines [ ] string
for _ , outputLine := range strings . Split ( out2 , "\n" ) {
if strings . Contains ( outputLine , imageAlreadyExists ) {
out1Lines = append ( out1Lines , outputLine )
}
}
2015-10-13 08:01:58 -04:00
c . Assert ( out2Lines , checker . HasLen , len ( out1Lines ) )
2015-08-12 21:36:46 -04:00
for i := range out1Lines {
2015-10-13 08:01:58 -04:00
c . Assert ( out1Lines [ i ] , checker . Equals , out2Lines [ i ] )
2015-08-12 21:36:46 -04:00
}
2015-01-30 17:20:32 -05:00
}
2015-12-18 18:06:23 -05:00
func ( s * DockerRegistrySuite ) TestPushMultipleTags ( c * check . C ) {
testPushMultipleTags ( c )
}
func ( s * DockerSchema1RegistrySuite ) TestPushMultipleTags ( c * check . C ) {
testPushMultipleTags ( c )
}
func testPushEmptyLayer ( c * check . C ) {
2015-01-24 16:08:47 -05:00
repoName := fmt . Sprintf ( "%v/dockercli/emptylayer" , privateRegistryURL )
emptyTarball , err := ioutil . TempFile ( "" , "empty_tarball" )
2015-10-13 08:01:58 -04:00
c . Assert ( err , check . IsNil , check . Commentf ( "Unable to create test file" ) )
2015-01-24 16:08:47 -05:00
tw := tar . NewWriter ( emptyTarball )
err = tw . Close ( )
2015-10-13 08:01:58 -04:00
c . Assert ( err , check . IsNil , check . Commentf ( "Error creating empty tarball" ) )
2015-01-24 16:08:47 -05:00
freader , err := os . Open ( emptyTarball . Name ( ) )
2015-10-13 08:01:58 -04:00
c . Assert ( err , check . IsNil , check . Commentf ( "Could not open test tarball" ) )
2016-06-24 23:57:21 -04:00
defer freader . Close ( )
2015-01-24 16:08:47 -05:00
2017-01-05 06:38:34 -05:00
icmd . RunCmd ( icmd . Cmd {
Command : [ ] string { dockerBinary , "import" , "-" , repoName } ,
2017-01-05 13:08:24 -05:00
Stdin : freader ,
2017-01-05 06:38:34 -05:00
} ) . Assert ( c , icmd . Success )
2015-01-24 16:08:47 -05:00
// Now verify we can push it
2017-01-05 13:08:24 -05:00
out , _ , err := dockerCmdWithError ( "push" , repoName )
2015-10-13 08:01:58 -04:00
c . Assert ( err , check . IsNil , check . Commentf ( "pushing the image to the private registry has failed: %s" , out ) )
2015-01-24 16:08:47 -05:00
}
2015-07-20 01:56:10 -04:00
2015-12-18 18:06:23 -05:00
func ( s * DockerRegistrySuite ) TestPushEmptyLayer ( c * check . C ) {
testPushEmptyLayer ( c )
}
func ( s * DockerSchema1RegistrySuite ) TestPushEmptyLayer ( c * check . C ) {
testPushEmptyLayer ( c )
}
2016-03-01 13:56:05 -05:00
// testConcurrentPush pushes multiple tags to the same repo
// concurrently.
func testConcurrentPush ( c * check . C ) {
repoName := fmt . Sprintf ( "%v/dockercli/busybox" , privateRegistryURL )
repos := [ ] string { }
for _ , tag := range [ ] string { "push1" , "push2" , "push3" } {
repo := fmt . Sprintf ( "%v:%v" , repoName , tag )
2017-03-23 13:35:22 -04:00
buildImageSuccessfully ( c , repo , build . WithDockerfile ( fmt . Sprintf ( `
2016-03-01 13:56:05 -05:00
FROM busybox
ENTRYPOINT [ "/bin/echo" ]
ENV FOO foo
ENV BAR bar
CMD echo % s
2017-01-16 05:30:14 -05:00
` , repo ) ) )
2016-03-01 13:56:05 -05:00
repos = append ( repos , repo )
}
// Push tags, in parallel
results := make ( chan error )
for _ , repo := range repos {
go func ( repo string ) {
2017-01-05 06:38:34 -05:00
result := icmd . RunCommand ( dockerBinary , "push" , repo )
results <- result . Error
2016-03-01 13:56:05 -05:00
} ( repo )
}
for range repos {
err := <- results
c . Assert ( err , checker . IsNil , check . Commentf ( "concurrent push failed with error: %v" , err ) )
}
// Clear local images store.
args := append ( [ ] string { "rmi" } , repos ... )
dockerCmd ( c , args ... )
// Re-pull and run individual tags, to make sure pushes succeeded
for _ , repo := range repos {
dockerCmd ( c , "pull" , repo )
dockerCmd ( c , "inspect" , repo )
out , _ := dockerCmd ( c , "run" , "--rm" , repo )
c . Assert ( strings . TrimSpace ( out ) , checker . Equals , "/bin/sh -c echo " + repo )
}
}
func ( s * DockerRegistrySuite ) TestConcurrentPush ( c * check . C ) {
testConcurrentPush ( c )
}
func ( s * DockerSchema1RegistrySuite ) TestConcurrentPush ( c * check . C ) {
testConcurrentPush ( c )
}
2016-01-05 17:17:42 -05:00
func ( s * DockerRegistrySuite ) TestCrossRepositoryLayerPush ( c * check . C ) {
sourceRepoName := fmt . Sprintf ( "%v/dockercli/busybox" , privateRegistryURL )
// tag the image to upload it to the private registry
dockerCmd ( c , "tag" , "busybox" , sourceRepoName )
// push the image to the registry
out1 , _ , err := dockerCmdWithError ( "push" , sourceRepoName )
c . Assert ( err , check . IsNil , check . Commentf ( "pushing the image to the private registry has failed: %s" , out1 ) )
// ensure that none of the layers were mounted from another repository during push
c . Assert ( strings . Contains ( out1 , "Mounted from" ) , check . Equals , false )
2016-06-09 05:00:41 -04:00
digest1 := reference . DigestRegexp . FindString ( out1 )
2016-01-20 14:39:32 -05:00
c . Assert ( len ( digest1 ) , checker . GreaterThan , 0 , check . Commentf ( "no digest found for pushed manifest" ) )
2016-01-05 17:17:42 -05:00
destRepoName := fmt . Sprintf ( "%v/dockercli/crossrepopush" , privateRegistryURL )
// retag the image to upload the same layers to another repo in the same registry
dockerCmd ( c , "tag" , "busybox" , destRepoName )
// push the image to the registry
out2 , _ , err := dockerCmdWithError ( "push" , destRepoName )
c . Assert ( err , check . IsNil , check . Commentf ( "pushing the image to the private registry has failed: %s" , out2 ) )
// ensure that layers were mounted from the first repo during push
c . Assert ( strings . Contains ( out2 , "Mounted from dockercli/busybox" ) , check . Equals , true )
2016-06-09 05:00:41 -04:00
digest2 := reference . DigestRegexp . FindString ( out2 )
2016-01-20 14:39:32 -05:00
c . Assert ( len ( digest2 ) , checker . GreaterThan , 0 , check . Commentf ( "no digest found for pushed manifest" ) )
c . Assert ( digest1 , check . Equals , digest2 )
2016-07-06 06:17:19 -04:00
// ensure that pushing again produces the same digest
out3 , _ , err := dockerCmdWithError ( "push" , destRepoName )
c . Assert ( err , check . IsNil , check . Commentf ( "pushing the image to the private registry has failed: %s" , out2 ) )
digest3 := reference . DigestRegexp . FindString ( out3 )
c . Assert ( len ( digest2 ) , checker . GreaterThan , 0 , check . Commentf ( "no digest found for pushed manifest" ) )
c . Assert ( digest3 , check . Equals , digest2 )
2016-01-13 22:34:27 -05:00
// ensure that we can pull and run the cross-repo-pushed repository
2016-01-05 17:17:42 -05:00
dockerCmd ( c , "rmi" , destRepoName )
dockerCmd ( c , "pull" , destRepoName )
2016-07-06 06:17:19 -04:00
out4 , _ := dockerCmd ( c , "run" , destRepoName , "echo" , "-n" , "hello world" )
c . Assert ( out4 , check . Equals , "hello world" )
2016-01-05 17:17:42 -05:00
}
func ( s * DockerSchema1RegistrySuite ) TestCrossRepositoryLayerPushNotSupported ( c * check . C ) {
sourceRepoName := fmt . Sprintf ( "%v/dockercli/busybox" , privateRegistryURL )
// tag the image to upload it to the private registry
dockerCmd ( c , "tag" , "busybox" , sourceRepoName )
// push the image to the registry
out1 , _ , err := dockerCmdWithError ( "push" , sourceRepoName )
c . Assert ( err , check . IsNil , check . Commentf ( "pushing the image to the private registry has failed: %s" , out1 ) )
// ensure that none of the layers were mounted from another repository during push
c . Assert ( strings . Contains ( out1 , "Mounted from" ) , check . Equals , false )
2016-06-09 05:00:41 -04:00
digest1 := reference . DigestRegexp . FindString ( out1 )
2016-01-20 14:39:32 -05:00
c . Assert ( len ( digest1 ) , checker . GreaterThan , 0 , check . Commentf ( "no digest found for pushed manifest" ) )
2016-01-05 17:17:42 -05:00
destRepoName := fmt . Sprintf ( "%v/dockercli/crossrepopush" , privateRegistryURL )
// retag the image to upload the same layers to another repo in the same registry
dockerCmd ( c , "tag" , "busybox" , destRepoName )
// push the image to the registry
out2 , _ , err := dockerCmdWithError ( "push" , destRepoName )
c . Assert ( err , check . IsNil , check . Commentf ( "pushing the image to the private registry has failed: %s" , out2 ) )
// schema1 registry should not support cross-repo layer mounts, so ensure that this does not happen
2016-02-22 14:27:17 -05:00
c . Assert ( strings . Contains ( out2 , "Mounted from" ) , check . Equals , false )
2016-01-05 17:17:42 -05:00
2016-06-09 05:00:41 -04:00
digest2 := reference . DigestRegexp . FindString ( out2 )
2016-01-20 14:39:32 -05:00
c . Assert ( len ( digest2 ) , checker . GreaterThan , 0 , check . Commentf ( "no digest found for pushed manifest" ) )
2016-06-09 05:00:41 -04:00
c . Assert ( digest1 , check . Not ( check . Equals ) , digest2 )
2016-01-20 14:39:32 -05:00
2016-01-13 22:34:27 -05:00
// ensure that we can pull and run the second pushed repository
2016-01-05 17:17:42 -05:00
dockerCmd ( c , "rmi" , destRepoName )
dockerCmd ( c , "pull" , destRepoName )
2016-01-13 22:34:27 -05:00
out3 , _ := dockerCmd ( c , "run" , destRepoName , "echo" , "-n" , "hello world" )
c . Assert ( out3 , check . Equals , "hello world" )
2016-01-05 17:17:42 -05:00
}
2015-07-20 01:56:10 -04:00
func ( s * DockerTrustSuite ) TestTrustedPush ( c * check . C ) {
2016-01-26 20:52:36 -05:00
repoName := fmt . Sprintf ( "%v/dockerclitrusted/pushtest:latest" , privateRegistryURL )
2015-07-20 01:56:10 -04:00
// tag the image and upload it to the private registry
2017-04-19 08:04:39 -04:00
cli . DockerCmd ( c , "tag" , "busybox" , repoName )
2015-07-20 01:56:10 -04:00
2017-04-19 08:04:39 -04:00
cli . Docker ( cli . Args ( "push" , repoName ) , trustedCmd ) . Assert ( c , SuccessSigningAndPushing )
2015-12-18 21:47:35 -05:00
// Try pull after push
2017-04-19 08:04:39 -04:00
cli . Docker ( cli . Args ( "pull" , repoName ) , trustedCmd ) . Assert ( c , icmd . Expected {
2017-01-05 13:08:24 -05:00
Out : "Status: Image is up to date" ,
} )
2016-03-02 19:51:32 -05:00
// Assert that we rotated the snapshot key to the server by checking our local keystore
2017-06-01 16:34:31 -04:00
contents , err := ioutil . ReadDir ( filepath . Join ( config . Dir ( ) , "trust/private/tuf_keys" , privateRegistryURL , "dockerclitrusted/pushtest" ) )
2016-03-02 19:51:32 -05:00
c . Assert ( err , check . IsNil , check . Commentf ( "Unable to read local tuf key files" ) )
// Check that we only have 1 key (targets key)
c . Assert ( contents , checker . HasLen , 1 )
2015-07-20 01:56:10 -04:00
}
2015-07-21 23:36:22 -04:00
2015-10-09 15:14:34 -04:00
func ( s * DockerTrustSuite ) TestTrustedPushWithEnvPasswords ( c * check . C ) {
2015-12-18 21:47:35 -05:00
repoName := fmt . Sprintf ( "%v/dockerclienv/trusted:latest" , privateRegistryURL )
2015-10-09 15:14:34 -04:00
// tag the image and upload it to the private registry
2017-04-19 08:04:39 -04:00
cli . DockerCmd ( c , "tag" , "busybox" , repoName )
2015-10-09 15:14:34 -04:00
2017-04-19 08:04:39 -04:00
cli . Docker ( cli . Args ( "push" , repoName ) , trustedCmdWithPassphrases ( "12345678" , "12345678" ) ) . Assert ( c , SuccessSigningAndPushing )
2015-12-18 21:47:35 -05:00
// Try pull after push
2017-04-19 08:04:39 -04:00
cli . Docker ( cli . Args ( "pull" , repoName ) , trustedCmd ) . Assert ( c , icmd . Expected {
2017-01-05 13:08:24 -05:00
Out : "Status: Image is up to date" ,
} )
2015-10-09 15:14:34 -04:00
}
2015-12-05 05:42:46 -05:00
func ( s * DockerTrustSuite ) TestTrustedPushWithFailingServer ( c * check . C ) {
2016-01-26 20:52:36 -05:00
repoName := fmt . Sprintf ( "%v/dockerclitrusted/failingserver:latest" , privateRegistryURL )
2015-07-21 23:36:22 -04:00
// tag the image and upload it to the private registry
2017-04-19 08:04:39 -04:00
cli . DockerCmd ( c , "tag" , "busybox" , repoName )
2015-07-21 23:36:22 -04:00
2016-06-02 17:58:53 -04:00
// Using a name that doesn't resolve to an address makes this test faster
2017-04-19 08:04:39 -04:00
cli . Docker ( cli . Args ( "push" , repoName ) , trustedCmdWithServer ( "https://server.invalid:81/" ) ) . Assert ( c , icmd . Expected {
2017-01-05 13:08:24 -05:00
ExitCode : 1 ,
Err : "error contacting notary server" ,
} )
2015-07-21 23:36:22 -04:00
}
func ( s * DockerTrustSuite ) TestTrustedPushWithoutServerAndUntrusted ( c * check . C ) {
2016-01-26 20:52:36 -05:00
repoName := fmt . Sprintf ( "%v/dockerclitrusted/trustedandnot:latest" , privateRegistryURL )
2015-07-21 23:36:22 -04:00
// tag the image and upload it to the private registry
2017-04-19 08:04:39 -04:00
cli . DockerCmd ( c , "tag" , "busybox" , repoName )
2015-07-21 23:36:22 -04:00
2017-04-19 08:04:39 -04:00
result := cli . Docker ( cli . Args ( "push" , "--disable-content-trust" , repoName ) , trustedCmdWithServer ( "https://server.invalid:81/" ) )
2017-01-05 13:08:24 -05:00
result . Assert ( c , icmd . Success )
c . Assert ( result . Combined ( ) , check . Not ( checker . Contains ) , "Error establishing connection to notary repository" , check . Commentf ( "Missing expected output on trusted push with --disable-content-trust:" ) )
2015-07-21 23:36:22 -04:00
}
func ( s * DockerTrustSuite ) TestTrustedPushWithExistingTag ( c * check . C ) {
2015-12-18 21:47:35 -05:00
repoName := fmt . Sprintf ( "%v/dockerclitag/trusted:latest" , privateRegistryURL )
2015-07-21 23:36:22 -04:00
// tag the image and upload it to the private registry
2017-04-19 08:04:39 -04:00
cli . DockerCmd ( c , "tag" , "busybox" , repoName )
cli . DockerCmd ( c , "push" , repoName )
2015-07-21 23:36:22 -04:00
2017-04-19 08:04:39 -04:00
cli . Docker ( cli . Args ( "push" , repoName ) , trustedCmd ) . Assert ( c , SuccessSigningAndPushing )
2015-12-18 21:47:35 -05:00
// Try pull after push
2017-04-19 08:04:39 -04:00
cli . Docker ( cli . Args ( "pull" , repoName ) , trustedCmd ) . Assert ( c , icmd . Expected {
2017-01-05 13:08:24 -05:00
Out : "Status: Image is up to date" ,
} )
2015-07-21 23:36:22 -04:00
}
2015-07-22 14:39:35 -04:00
func ( s * DockerTrustSuite ) TestTrustedPushWithExistingSignedTag ( c * check . C ) {
repoName := fmt . Sprintf ( "%v/dockerclipushpush/trusted:latest" , privateRegistryURL )
2015-07-21 23:36:22 -04:00
// tag the image and upload it to the private registry
2017-04-19 08:04:39 -04:00
cli . DockerCmd ( c , "tag" , "busybox" , repoName )
2015-07-21 23:36:22 -04:00
2015-07-22 14:39:35 -04:00
// Do a trusted push
2017-04-19 08:04:39 -04:00
cli . Docker ( cli . Args ( "push" , repoName ) , trustedCmd ) . Assert ( c , SuccessSigningAndPushing )
2015-07-21 23:36:22 -04:00
2015-07-22 14:39:35 -04:00
// Do another trusted push
2017-04-19 08:04:39 -04:00
cli . Docker ( cli . Args ( "push" , repoName ) , trustedCmd ) . Assert ( c , SuccessSigningAndPushing )
cli . DockerCmd ( c , "rmi" , repoName )
2015-07-22 14:39:35 -04:00
// Try pull to ensure the double push did not break our ability to pull
2017-04-19 08:04:39 -04:00
cli . Docker ( cli . Args ( "pull" , repoName ) , trustedCmd ) . Assert ( c , SuccessDownloaded )
2015-07-21 23:36:22 -04:00
}
2015-07-22 14:39:35 -04:00
func ( s * DockerTrustSuite ) TestTrustedPushWithIncorrectPassphraseForNonRoot ( c * check . C ) {
repoName := fmt . Sprintf ( "%v/dockercliincorretpwd/trusted:latest" , privateRegistryURL )
2015-07-21 23:36:22 -04:00
// tag the image and upload it to the private registry
2017-04-19 08:04:39 -04:00
cli . DockerCmd ( c , "tag" , "busybox" , repoName )
2015-07-21 23:36:22 -04:00
2015-07-22 14:39:35 -04:00
// Push with default passphrases
2017-04-19 08:04:39 -04:00
cli . Docker ( cli . Args ( "push" , repoName ) , trustedCmd ) . Assert ( c , SuccessSigningAndPushing )
2015-07-22 14:39:35 -04:00
// Push with wrong passphrases
2017-04-19 08:04:39 -04:00
cli . Docker ( cli . Args ( "push" , repoName ) , trustedCmdWithPassphrases ( "12345678" , "87654321" ) ) . Assert ( c , icmd . Expected {
2017-01-05 13:08:24 -05:00
ExitCode : 1 ,
Err : "could not find necessary signing keys" ,
} )
2015-07-21 23:36:22 -04:00
}
2015-07-22 21:46:59 -04:00
2016-03-07 14:48:11 -05:00
func ( s * DockerTrustSuite ) TestTrustedPushWithReleasesDelegationOnly ( c * check . C ) {
2016-03-11 17:11:35 -05:00
testRequires ( c , NotaryHosting )
2016-03-07 14:48:11 -05:00
repoName := fmt . Sprintf ( "%v/dockerclireleasedelegationinitfirst/trusted" , privateRegistryURL )
2015-12-23 19:34:46 -05:00
targetName := fmt . Sprintf ( "%s:latest" , repoName )
2016-03-16 22:59:18 -04:00
s . notaryInitRepo ( c , repoName )
s . notaryCreateDelegation ( c , repoName , "targets/releases" , s . not . keys [ 0 ] . Public )
s . notaryPublish ( c , repoName )
2016-03-07 14:48:11 -05:00
s . notaryImportKey ( c , repoName , "targets/releases" , s . not . keys [ 0 ] . Private )
2015-12-23 19:34:46 -05:00
// tag the image and upload it to the private registry
2017-04-19 08:04:39 -04:00
cli . DockerCmd ( c , "tag" , "busybox" , targetName )
2015-12-23 19:34:46 -05:00
2017-04-19 08:04:39 -04:00
cli . Docker ( cli . Args ( "push" , targetName ) , trustedCmd ) . Assert ( c , SuccessSigningAndPushing )
2016-03-16 22:59:18 -04:00
// check to make sure that the target has been added to targets/releases and not targets
s . assertTargetInRoles ( c , repoName , "latest" , "targets/releases" )
s . assertTargetNotInRoles ( c , repoName , "latest" , "targets" )
2015-12-23 19:34:46 -05:00
// Try pull after push
2017-06-01 16:34:31 -04:00
os . RemoveAll ( filepath . Join ( config . Dir ( ) , "trust" ) )
2016-03-07 14:48:11 -05:00
2017-04-19 08:04:39 -04:00
cli . Docker ( cli . Args ( "pull" , targetName ) , trustedCmd ) . Assert ( c , icmd . Expected {
2017-01-05 13:08:24 -05:00
Out : "Status: Image is up to date" ,
} )
2016-03-07 14:48:11 -05:00
}
func ( s * DockerTrustSuite ) TestTrustedPushSignsAllFirstLevelRolesWeHaveKeysFor ( c * check . C ) {
testRequires ( c , NotaryHosting )
repoName := fmt . Sprintf ( "%v/dockerclimanyroles/trusted" , privateRegistryURL )
targetName := fmt . Sprintf ( "%s:latest" , repoName )
2016-03-16 22:59:18 -04:00
s . notaryInitRepo ( c , repoName )
s . notaryCreateDelegation ( c , repoName , "targets/role1" , s . not . keys [ 0 ] . Public )
s . notaryCreateDelegation ( c , repoName , "targets/role2" , s . not . keys [ 1 ] . Public )
s . notaryCreateDelegation ( c , repoName , "targets/role3" , s . not . keys [ 2 ] . Public )
2016-03-07 14:48:11 -05:00
// import everything except the third key
s . notaryImportKey ( c , repoName , "targets/role1" , s . not . keys [ 0 ] . Private )
s . notaryImportKey ( c , repoName , "targets/role2" , s . not . keys [ 1 ] . Private )
2016-03-16 22:59:18 -04:00
s . notaryCreateDelegation ( c , repoName , "targets/role1/subrole" , s . not . keys [ 3 ] . Public )
2016-03-07 14:48:11 -05:00
s . notaryImportKey ( c , repoName , "targets/role1/subrole" , s . not . keys [ 3 ] . Private )
2016-03-16 22:59:18 -04:00
s . notaryPublish ( c , repoName )
2016-03-07 14:48:11 -05:00
// tag the image and upload it to the private registry
2017-04-19 08:04:39 -04:00
cli . DockerCmd ( c , "tag" , "busybox" , targetName )
2016-03-07 14:48:11 -05:00
2017-04-19 08:04:39 -04:00
cli . Docker ( cli . Args ( "push" , targetName ) , trustedCmd ) . Assert ( c , SuccessSigningAndPushing )
2016-03-07 14:48:11 -05:00
2016-03-16 22:59:18 -04:00
// check to make sure that the target has been added to targets/role1 and targets/role2, and
// not targets (because there are delegations) or targets/role3 (due to missing key) or
// targets/role1/subrole (due to it being a second level delegation)
s . assertTargetInRoles ( c , repoName , "latest" , "targets/role1" , "targets/role2" )
s . assertTargetNotInRoles ( c , repoName , "latest" , "targets" )
2016-03-07 14:48:11 -05:00
// Try pull after push
2017-06-01 16:34:31 -04:00
os . RemoveAll ( filepath . Join ( config . Dir ( ) , "trust" ) )
2016-03-07 14:48:11 -05:00
2016-03-16 22:59:18 -04:00
// pull should fail because none of these are the releases role
2017-04-19 08:04:39 -04:00
cli . Docker ( cli . Args ( "pull" , targetName ) , trustedCmd ) . Assert ( c , icmd . Expected {
2017-01-05 13:08:24 -05:00
ExitCode : 1 ,
} )
2016-03-07 14:48:11 -05:00
}
func ( s * DockerTrustSuite ) TestTrustedPushSignsForRolesWithKeysAndValidPaths ( c * check . C ) {
repoName := fmt . Sprintf ( "%v/dockerclirolesbykeysandpaths/trusted" , privateRegistryURL )
targetName := fmt . Sprintf ( "%s:latest" , repoName )
2016-03-16 22:59:18 -04:00
s . notaryInitRepo ( c , repoName )
s . notaryCreateDelegation ( c , repoName , "targets/role1" , s . not . keys [ 0 ] . Public , "l" , "z" )
s . notaryCreateDelegation ( c , repoName , "targets/role2" , s . not . keys [ 1 ] . Public , "x" , "y" )
s . notaryCreateDelegation ( c , repoName , "targets/role3" , s . not . keys [ 2 ] . Public , "latest" )
s . notaryCreateDelegation ( c , repoName , "targets/role4" , s . not . keys [ 3 ] . Public , "latest" )
2015-12-23 19:34:46 -05:00
2016-03-07 14:48:11 -05:00
// import everything except the third key
s . notaryImportKey ( c , repoName , "targets/role1" , s . not . keys [ 0 ] . Private )
s . notaryImportKey ( c , repoName , "targets/role2" , s . not . keys [ 1 ] . Private )
s . notaryImportKey ( c , repoName , "targets/role4" , s . not . keys [ 3 ] . Private )
2016-03-16 22:59:18 -04:00
s . notaryPublish ( c , repoName )
2016-03-07 14:48:11 -05:00
// tag the image and upload it to the private registry
2017-04-19 08:04:39 -04:00
cli . DockerCmd ( c , "tag" , "busybox" , targetName )
2016-03-07 14:48:11 -05:00
2017-04-19 08:04:39 -04:00
cli . Docker ( cli . Args ( "push" , targetName ) , trustedCmd ) . Assert ( c , SuccessSigningAndPushing )
2016-03-07 14:48:11 -05:00
2016-03-16 22:59:18 -04:00
// check to make sure that the target has been added to targets/role1 and targets/role4, and
// not targets (because there are delegations) or targets/role2 (due to path restrictions) or
// targets/role3 (due to missing key)
s . assertTargetInRoles ( c , repoName , "latest" , "targets/role1" , "targets/role4" )
s . assertTargetNotInRoles ( c , repoName , "latest" , "targets" )
2016-03-07 14:48:11 -05:00
// Try pull after push
2017-06-01 16:34:31 -04:00
os . RemoveAll ( filepath . Join ( config . Dir ( ) , "trust" ) )
2016-03-07 14:48:11 -05:00
2016-03-16 22:59:18 -04:00
// pull should fail because none of these are the releases role
2017-04-19 08:04:39 -04:00
cli . Docker ( cli . Args ( "pull" , targetName ) , trustedCmd ) . Assert ( c , icmd . Expected {
2017-01-05 13:08:24 -05:00
ExitCode : 1 ,
} )
2016-03-07 14:48:11 -05:00
}
func ( s * DockerTrustSuite ) TestTrustedPushDoesntSignTargetsIfDelegationsExist ( c * check . C ) {
testRequires ( c , NotaryHosting )
repoName := fmt . Sprintf ( "%v/dockerclireleasedelegationnotsignable/trusted" , privateRegistryURL )
targetName := fmt . Sprintf ( "%s:latest" , repoName )
2016-03-16 22:59:18 -04:00
s . notaryInitRepo ( c , repoName )
s . notaryCreateDelegation ( c , repoName , "targets/role1" , s . not . keys [ 0 ] . Public )
s . notaryPublish ( c , repoName )
2016-03-07 14:48:11 -05:00
// do not import any delegations key
// tag the image and upload it to the private registry
2017-04-19 08:04:39 -04:00
cli . DockerCmd ( c , "tag" , "busybox" , targetName )
2016-03-07 14:48:11 -05:00
2017-04-19 08:04:39 -04:00
cli . Docker ( cli . Args ( "push" , targetName ) , trustedCmd ) . Assert ( c , icmd . Expected {
2017-01-05 13:08:24 -05:00
ExitCode : 1 ,
Err : "no valid signing keys" ,
} )
2016-03-16 22:59:18 -04:00
s . assertTargetNotInRoles ( c , repoName , "latest" , "targets" , "targets/role1" )
2015-12-23 19:34:46 -05:00
}
2016-03-12 12:01:01 -05:00
2016-03-14 16:11:35 -04:00
func ( s * DockerRegistryAuthHtpasswdSuite ) TestPushNoCredentialsNoRetry ( c * check . C ) {
2016-03-12 12:01:01 -05:00
repoName := fmt . Sprintf ( "%s/busybox" , privateRegistryURL )
dockerCmd ( c , "tag" , "busybox" , repoName )
out , _ , err := dockerCmdWithError ( "push" , repoName )
c . Assert ( err , check . NotNil , check . Commentf ( out ) )
c . Assert ( out , check . Not ( checker . Contains ) , "Retrying" )
c . Assert ( out , checker . Contains , "no basic auth credentials" )
}
2016-03-12 14:34:07 -05:00
// This may be flaky but it's needed not to regress on unauthorized push, see #21054
func ( s * DockerSuite ) TestPushToCentralRegistryUnauthorized ( c * check . C ) {
testRequires ( c , Network )
repoName := "test/busybox"
dockerCmd ( c , "tag" , "busybox" , repoName )
out , _ , err := dockerCmdWithError ( "push" , repoName )
c . Assert ( err , check . NotNil , check . Commentf ( out ) )
2016-03-18 13:54:05 -04:00
c . Assert ( out , check . Not ( checker . Contains ) , "Retrying" )
2016-03-12 14:34:07 -05:00
}
2016-03-14 16:11:35 -04:00
2016-09-01 18:18:15 -04:00
func getTestTokenService ( status int , body string , retries int ) * httptest . Server {
var mu sync . Mutex
2016-03-19 07:19:43 -04:00
return httptest . NewServer ( http . HandlerFunc ( func ( w http . ResponseWriter , r * http . Request ) {
2016-09-01 18:18:15 -04:00
mu . Lock ( )
if retries > 0 {
w . WriteHeader ( http . StatusServiceUnavailable )
w . Header ( ) . Set ( "Content-Type" , "application/json" )
w . Write ( [ ] byte ( ` { "errors":[ { "code":"UNAVAILABLE","message":"cannot create token at this time"}]} ` ) )
retries --
} else {
w . WriteHeader ( status )
w . Header ( ) . Set ( "Content-Type" , "application/json" )
w . Write ( [ ] byte ( body ) )
}
mu . Unlock ( )
2016-03-14 16:11:35 -04:00
} ) )
2016-03-19 07:19:43 -04:00
}
func ( s * DockerRegistryAuthTokenSuite ) TestPushTokenServiceUnauthResponse ( c * check . C ) {
2016-09-01 18:18:15 -04:00
ts := getTestTokenService ( http . StatusUnauthorized , ` { "errors": [ { "Code":"UNAUTHORIZED", "message": "a message", "detail": null}]} ` , 0 )
2016-03-14 16:11:35 -04:00
defer ts . Close ( )
s . setupRegistryWithTokenService ( c , ts . URL )
repoName := fmt . Sprintf ( "%s/busybox" , privateRegistryURL )
dockerCmd ( c , "tag" , "busybox" , repoName )
out , _ , err := dockerCmdWithError ( "push" , repoName )
c . Assert ( err , check . NotNil , check . Commentf ( out ) )
2016-03-19 07:19:43 -04:00
c . Assert ( out , checker . Not ( checker . Contains ) , "Retrying" )
2016-03-14 16:11:35 -04:00
c . Assert ( out , checker . Contains , "unauthorized: a message" )
}
2016-03-19 07:19:43 -04:00
func ( s * DockerRegistryAuthTokenSuite ) TestPushMisconfiguredTokenServiceResponseUnauthorized ( c * check . C ) {
2016-09-01 18:18:15 -04:00
ts := getTestTokenService ( http . StatusUnauthorized , ` { "error": "unauthorized"} ` , 0 )
2016-03-19 07:19:43 -04:00
defer ts . Close ( )
s . setupRegistryWithTokenService ( c , ts . URL )
repoName := fmt . Sprintf ( "%s/busybox" , privateRegistryURL )
dockerCmd ( c , "tag" , "busybox" , repoName )
out , _ , err := dockerCmdWithError ( "push" , repoName )
c . Assert ( err , check . NotNil , check . Commentf ( out ) )
c . Assert ( out , checker . Not ( checker . Contains ) , "Retrying" )
split := strings . Split ( out , "\n" )
c . Assert ( split [ len ( split ) - 2 ] , check . Equals , "unauthorized: authentication required" )
}
func ( s * DockerRegistryAuthTokenSuite ) TestPushMisconfiguredTokenServiceResponseError ( c * check . C ) {
2017-04-05 19:07:43 -04:00
ts := getTestTokenService ( http . StatusTooManyRequests , ` { "errors": [ { "code":"TOOMANYREQUESTS","message":"out of tokens"}]} ` , 3 )
2016-03-19 07:19:43 -04:00
defer ts . Close ( )
s . setupRegistryWithTokenService ( c , ts . URL )
repoName := fmt . Sprintf ( "%s/busybox" , privateRegistryURL )
dockerCmd ( c , "tag" , "busybox" , repoName )
out , _ , err := dockerCmdWithError ( "push" , repoName )
c . Assert ( err , check . NotNil , check . Commentf ( out ) )
2017-04-05 19:07:43 -04:00
// TODO: isolate test so that it can be guaranteed that the 503 will trigger xfer retries
//c.Assert(out, checker.Contains, "Retrying")
//c.Assert(out, checker.Not(checker.Contains), "Retrying in 15")
2016-03-19 07:19:43 -04:00
split := strings . Split ( out , "\n" )
2016-09-01 18:18:15 -04:00
c . Assert ( split [ len ( split ) - 2 ] , check . Equals , "toomanyrequests: out of tokens" )
2016-03-19 07:19:43 -04:00
}
func ( s * DockerRegistryAuthTokenSuite ) TestPushMisconfiguredTokenServiceResponseUnparsable ( c * check . C ) {
2016-09-01 18:18:15 -04:00
ts := getTestTokenService ( http . StatusForbidden , ` no way ` , 0 )
2016-03-14 16:11:35 -04:00
defer ts . Close ( )
s . setupRegistryWithTokenService ( c , ts . URL )
repoName := fmt . Sprintf ( "%s/busybox" , privateRegistryURL )
dockerCmd ( c , "tag" , "busybox" , repoName )
out , _ , err := dockerCmdWithError ( "push" , repoName )
c . Assert ( err , check . NotNil , check . Commentf ( out ) )
2016-03-19 07:19:43 -04:00
c . Assert ( out , checker . Not ( checker . Contains ) , "Retrying" )
split := strings . Split ( out , "\n" )
c . Assert ( split [ len ( split ) - 2 ] , checker . Contains , "error parsing HTTP 403 response body: " )
2016-03-14 16:11:35 -04:00
}
2016-03-18 13:54:05 -04:00
func ( s * DockerRegistryAuthTokenSuite ) TestPushMisconfiguredTokenServiceResponseNoToken ( c * check . C ) {
2016-09-01 18:18:15 -04:00
ts := getTestTokenService ( http . StatusOK , ` { "something": "wrong"} ` , 0 )
2016-03-18 13:54:05 -04:00
defer ts . Close ( )
s . setupRegistryWithTokenService ( c , ts . URL )
repoName := fmt . Sprintf ( "%s/busybox" , privateRegistryURL )
dockerCmd ( c , "tag" , "busybox" , repoName )
out , _ , err := dockerCmdWithError ( "push" , repoName )
c . Assert ( err , check . NotNil , check . Commentf ( out ) )
c . Assert ( out , checker . Not ( checker . Contains ) , "Retrying" )
split := strings . Split ( out , "\n" )
c . Assert ( split [ len ( split ) - 2 ] , check . Equals , "authorization server did not include a token in the response" )
}