Skip to content

Commit

Permalink
Verify SIF sources at build, optional Fingerprint check
Browse files Browse the repository at this point in the history
 - Fixes apptainer#5150
 - Fixes apptainer#2748

When we run a build, and a SIF image is the bootstrap source, run a
verify on it and warn for failures as we do with `push`.

Add a new definition file header key `Fingerprints:` that enforces the
source image must verify, with signatures that match every fingerprint
in the supplied comma separated list.
  • Loading branch information
dtrudg committed Nov 4, 2020
1 parent 89ee3b2 commit b63cc70
Show file tree
Hide file tree
Showing 16 changed files with 632 additions and 56 deletions.
44 changes: 25 additions & 19 deletions cmd/internal/cli/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
ocitypes "github.com/containers/image/v5/types"
"github.com/spf13/cobra"
scsbuildclient "github.com/sylabs/scs-build-client/client"
scskeyclient "github.com/sylabs/scs-key-client/client"
scslibclient "github.com/sylabs/scs-library-client/client"
"github.com/sylabs/singularity/docs"
"github.com/sylabs/singularity/internal/pkg/remote/endpoint"
Expand All @@ -27,20 +28,21 @@ import (
)

var buildArgs struct {
sections []string
arch string
builderURL string
libraryURL string
detached bool
encrypt bool
fakeroot bool
fixPerms bool
isJSON bool
noCleanUp bool
noTest bool
remote bool
sandbox bool
update bool
sections []string
arch string
builderURL string
libraryURL string
keyServerURL string
detached bool
encrypt bool
fakeroot bool
fixPerms bool
isJSON bool
noCleanUp bool
noTest bool
remote bool
sandbox bool
update bool
}

// -s|--sandbox
Expand Down Expand Up @@ -393,15 +395,19 @@ func makeDockerCredentials(cmd *cobra.Command) (authConf *ocitypes.DockerAuthCon
return nil, nil
}

// remote builds need to fail if we cannot resolve remote URLS
func getBuildAndLibraryClientConfig(buildURI, libraryURI string) (*scsbuildclient.Config, *scslibclient.Config, error) {
// get configuration for remote library, builder, keyserver that may be used in the build
func getServiceConfigs(buildURI, libraryURI, keyserverURI string) (*scsbuildclient.Config, *scslibclient.Config, *scskeyclient.Config, error) {
lc, err := getLibraryClientConfig(libraryURI)
if err != nil {
return nil, nil, err
return nil, nil, nil, err
}
bc, err := getBuilderClientConfig(buildURI)
if err != nil {
return nil, nil, err
return nil, nil, nil, err
}
return bc, lc, nil
kc, err := getKeyserverClientConfig(keyserverURI, endpoint.KeyserverVerifyOp)
if err != nil {
return nil, nil, nil, err
}
return bc, lc, kc, nil
}
5 changes: 3 additions & 2 deletions cmd/internal/cli/build_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,13 @@ func runBuild(cmd *cobra.Command, args []string) {
sylog.Fatalf("Only remote builds are supported on this platform")
}

bc, lc, err := getBuildAndLibraryClientConfig(buildArgs.builderURL, buildArgs.libraryURL)
bc, lc, kc, err := getServiceConfigs(buildArgs.builderURL, buildArgs.libraryURL, buildArgs.keyServerURL)
if err != nil {
sylog.Fatalf("Unable to get builder and library client configuration: %v", err)
sylog.Fatalf("Unable to get service configuration: %v", err)
}
buildArgs.libraryURL = lc.BaseURL
buildArgs.builderURL = bc.BaseURL
buildArgs.keyServerURL = kc.BaseURL

// Submiting a remote build requires a valid authToken
if bc.AuthToken == "" {
Expand Down
12 changes: 11 additions & 1 deletion cmd/internal/cli/build_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import (
"strings"
"syscall"

"github.com/sylabs/singularity/internal/pkg/remote/endpoint"

"github.com/spf13/cobra"
"github.com/sylabs/singularity/internal/pkg/build"
"github.com/sylabs/singularity/internal/pkg/build/remotebuilder"
Expand Down Expand Up @@ -115,7 +117,9 @@ func runBuildRemote(ctx context.Context, cmd *cobra.Command, dst, spec string) {
sylog.Fatalf("Building encrypted container with the remote builder is not currently supported.")
}

bc, lc, err := getBuildAndLibraryClientConfig(buildArgs.builderURL, buildArgs.libraryURL)
// TODO - the keyserver config needs to go to the remote builder for fingerprint verification at
// build time to be fully supported.
bc, lc, _, err := getServiceConfigs(buildArgs.builderURL, buildArgs.libraryURL, buildArgs.keyServerURL)
if err != nil {
sylog.Fatalf("Unable to get builder and library client configuration: %v", err)
}
Expand Down Expand Up @@ -267,6 +271,11 @@ func runBuildLocal(ctx context.Context, cmd *cobra.Command, dst, spec string) {
authToken = lc.AuthToken
}

kc, err := getKeyserverClientConfig(buildArgs.keyServerURL, endpoint.KeyserverVerifyOp)
if err != nil {
sylog.Fatalf("Unable to get key server client configuration: %v", err)
}

buildFormat := "sif"
sandboxTarget := false
if buildArgs.sandbox {
Expand All @@ -292,6 +301,7 @@ func runBuildLocal(ctx context.Context, cmd *cobra.Command, dst, spec string) {
NoHTTPS: noHTTPS,
LibraryURL: buildArgs.libraryURL,
LibraryAuthToken: authToken,
KeyServerConfig: kc,
DockerAuthConfig: authConf,
EncryptionKeyInfo: keyInfo,
FixPerms: buildArgs.fixPerms,
Expand Down
24 changes: 12 additions & 12 deletions e2e/ecl/ecl.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
"github.com/sylabs/singularity/internal/pkg/syecl"
)

var keyMap = map[string]string{
var KeyMap = map[string]string{
"key1": "0C5B8C9A5FFC44E2A0AC79851CD6FA281D476DD1",
"key2": "78F8AD36B0DCB84B707F23853D608DAE21C8CA10",
}
Expand Down Expand Up @@ -153,7 +153,7 @@ func (c *ctx) eclConfig(t *testing.T) {
TagName: "group1",
ListMode: "whitelist",
DirPath: tmpDir,
KeyFPs: []string{keyMap["key1"]},
KeyFPs: []string{KeyMap["key1"]},
},
},
},
Expand All @@ -171,7 +171,7 @@ func (c *ctx) eclConfig(t *testing.T) {
TagName: "group1",
ListMode: "whitelist",
DirPath: tmpDir,
KeyFPs: []string{keyMap["key2"]},
KeyFPs: []string{KeyMap["key2"]},
},
},
},
Expand All @@ -189,7 +189,7 @@ func (c *ctx) eclConfig(t *testing.T) {
TagName: "group1",
ListMode: "whitelist",
DirPath: tmpDir,
KeyFPs: []string{keyMap["key1"]},
KeyFPs: []string{KeyMap["key1"]},
},
},
},
Expand Down Expand Up @@ -224,7 +224,7 @@ func (c *ctx) eclConfig(t *testing.T) {
TagName: "group1",
ListMode: "whitelist",
DirPath: "/",
KeyFPs: []string{keyMap["key1"], keyMap["key2"]},
KeyFPs: []string{KeyMap["key1"], KeyMap["key2"]},
},
},
},
Expand All @@ -242,7 +242,7 @@ func (c *ctx) eclConfig(t *testing.T) {
TagName: "group1",
ListMode: "whitestrict",
DirPath: tmpDir,
KeyFPs: []string{keyMap["key1"], keyMap["key2"]},
KeyFPs: []string{KeyMap["key1"], KeyMap["key2"]},
},
},
},
Expand All @@ -260,7 +260,7 @@ func (c *ctx) eclConfig(t *testing.T) {
TagName: "group1",
ListMode: "whitestrict",
DirPath: tmpDir,
KeyFPs: []string{keyMap["key1"], keyMap["key2"]},
KeyFPs: []string{KeyMap["key1"], KeyMap["key2"]},
},
},
},
Expand All @@ -278,7 +278,7 @@ func (c *ctx) eclConfig(t *testing.T) {
TagName: "group1",
ListMode: "whitestrict",
DirPath: tmpDir,
KeyFPs: []string{keyMap["key1"], keyMap["key2"]},
KeyFPs: []string{KeyMap["key1"], KeyMap["key2"]},
},
},
},
Expand All @@ -296,7 +296,7 @@ func (c *ctx) eclConfig(t *testing.T) {
TagName: "group1",
ListMode: "blacklist",
DirPath: tmpDir,
KeyFPs: []string{keyMap["key1"]},
KeyFPs: []string{KeyMap["key1"]},
},
},
},
Expand All @@ -314,7 +314,7 @@ func (c *ctx) eclConfig(t *testing.T) {
TagName: "group1",
ListMode: "blacklist",
DirPath: tmpDir,
KeyFPs: []string{keyMap["key2"]},
KeyFPs: []string{KeyMap["key2"]},
},
},
},
Expand All @@ -325,14 +325,14 @@ func (c *ctx) eclConfig(t *testing.T) {
name: "remove key1 from global",
command: "key remove",
profile: e2e.RootProfile,
args: []string{"--global", keyMap["key1"]},
args: []string{"--global", KeyMap["key1"]},
exit: 0,
},
{
name: "remove key2 from global",
command: "key remove",
profile: e2e.RootProfile,
args: []string{"--global", keyMap["key2"]},
args: []string{"--global", KeyMap["key2"]},
exit: 0,
},
{
Expand Down
Loading

0 comments on commit b63cc70

Please sign in to comment.