diff --git a/go.sum b/go.sum index da0ea075e..3103dce3b 100644 --- a/go.sum +++ b/go.sum @@ -53,8 +53,6 @@ contrib.go.opencensus.io/exporter/stackdriver v0.12.1/go.mod h1:iwB6wGarfphGGe/e contrib.go.opencensus.io/integrations/ocsql v0.1.4/go.mod h1:8DsSdjz3F+APR+0z0WkU1aRorQCFfRxvqjUUPMbF3fE= contrib.go.opencensus.io/resource v0.1.1/go.mod h1:F361eGI91LCmW1I/Saf+rX0+OFcigGlFvXwEGEnkRLA= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -get.porter.sh/magefiles v0.1.3 h1:91Y7vFDHGmMBbRfHQqEcIlqpp/RfDCMhyHGVusTYlmE= -get.porter.sh/magefiles v0.1.3/go.mod h1:Whw/DSX8dcgn7dUPb6csbY6PtuTy1wujwFR2G6ONf20= get.porter.sh/magefiles v0.3.0 h1:uwCOTblBx2RFN2IEgIUDP4sNj/C4F26KqAdqSREJL7g= get.porter.sh/magefiles v0.3.0/go.mod h1:lwDECEEivbBHACLImnDEhwlr8g3E4xZR1W0DO8FOGa8= git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= diff --git a/pkg/porter/archive.go b/pkg/porter/archive.go index ddaccd12d..35d64653f 100644 --- a/pkg/porter/archive.go +++ b/pkg/porter/archive.go @@ -6,6 +6,7 @@ import ( "io" "os" "path/filepath" + "strings" "time" "get.porter.sh/porter/pkg" @@ -16,6 +17,7 @@ import ( "github.com/cnabio/cnab-go/imagestore/construction" "github.com/docker/docker/pkg/archive" "github.com/pkg/errors" + "github.com/spf13/afero" ) // ArchiveOptions defines the valid options for performing an archive operation @@ -88,14 +90,10 @@ type exporter struct { } func (ex *exporter) export() error { - name := ex.bundle.Name + "-" + ex.bundle.Version - archiveDir, err := ex.fs.TempDir("", name) + archiveDir, err := ex.createArchiveFolder(name) if err != nil { - return err - } - if err := ex.fs.MkdirAll(archiveDir, 0644); err != nil { - return err + return fmt.Errorf("can not create archive folder: %w", err) } defer ex.fs.RemoveAll(archiveDir) @@ -186,6 +184,23 @@ func (ex *exporter) addImage(image bundle.BaseImage) error { return checkDigest(image, dig) } +// createArchiveFolder set up a temporary directory for storing all data needed to archive a bundle. +// It sanitizes the name and make sure only the current user has full permission to it. +// If the name contains a path separator, all path separators will be replaced with "-". +func (ex *exporter) createArchiveFolder(name string) (string, error) { + cleanedPath := strings.ReplaceAll(afero.UnicodeSanitize(name), string(os.PathSeparator), "-") + archiveDir, err := ex.fs.TempDir("", cleanedPath) + if err != nil { + return "", fmt.Errorf("can not create a temporary archive folder: %w", err) + } + + err = ex.fs.Chmod(archiveDir, pkg.FileModeDirectory) + if err != nil { + return "", fmt.Errorf("can not change permission for the temporary archive folder: %w", err) + } + return archiveDir, nil +} + // checkDigest compares the content digest of the given image to the given content digest and returns an error if they // are both non-empty and do not match func checkDigest(image bundle.BaseImage, dig string) error { diff --git a/pkg/porter/archive_test.go b/pkg/porter/archive_test.go index 12905cbae..7c6d949af 100644 --- a/pkg/porter/archive_test.go +++ b/pkg/porter/archive_test.go @@ -4,6 +4,8 @@ import ( "context" "testing" + "get.porter.sh/porter/pkg" + "get.porter.sh/porter/tests" "github.com/stretchr/testify/require" ) @@ -51,3 +53,17 @@ func TestArchive_Validate(t *testing.T) { }) } } + +func TestArchive_ArchiveDirectory(t *testing.T) { + p := NewTestPorter(t) + defer p.Close() + ex := exporter{ + fs: p.FileSystem, + } + + dir, err := ex.createArchiveFolder("examples/test-bundle-0.2.0") + require.NoError(t, err) + require.Contains(t, dir, "/tmp/examples-test-bundle-0.2.0") + + tests.AssertDirectoryPermissionsEqual(t, dir, pkg.FileModeDirectory) +}