image level lint: enforce manifest mandatory annotations

closes #536

Signed-off-by: Lisca Ana-Roberta <ana.kagome@yahoo.com>
This commit is contained in:
Lisca Ana-Roberta
2022-06-24 16:08:47 +03:00
committed by Andrei Aaron
parent 3d72dad507
commit 87fc941b3c
34 changed files with 1391 additions and 110 deletions
+2 -1
View File
@@ -274,7 +274,8 @@ func syncOneImage(imageChannel chan error, cfg Config, storeController storage.S
imageChannel <- nil
}
func syncRun(regCfg RegistryConfig, localRepo, remoteRepo, tag string, utils syncContextUtils,
func syncRun(regCfg RegistryConfig,
localRepo, remoteRepo, tag string, utils syncContextUtils,
log log.Logger,
) (bool, error) {
upstreamImageRef, err := getImageRef(utils.upstreamAddr, remoteRepo, tag)
+2 -1
View File
@@ -196,7 +196,8 @@ func syncCosignSignature(client *resty.Client, imageStore storage.ImageStore,
}
// push manifest
_, err = imageStore.PutImageManifest(localRepo, cosignTag, ispec.MediaTypeImageManifest, cosignManifestBuf)
_, err = imageStore.PutImageManifest(localRepo, cosignTag,
ispec.MediaTypeImageManifest, cosignManifestBuf)
if err != nil {
log.Error().Str("errorType", TypeOf(err)).
Err(err).Msg("couldn't upload cosign manifest")
+4 -3
View File
@@ -296,7 +296,8 @@ func getUpstreamContext(regCfg *RegistryConfig, credentials Credentials) *types.
}
// nolint:gocyclo // offloading some of the functionalities from here would make the code harder to follow
func syncRegistry(ctx context.Context, regCfg RegistryConfig, upstreamURL string,
func syncRegistry(ctx context.Context, regCfg RegistryConfig,
upstreamURL string,
storeController storage.StoreController, localCtx *types.SystemContext,
policyCtx *signature.PolicyContext, credentials Credentials,
retryOptions *retry.RetryOptions, log log.Logger,
@@ -509,7 +510,6 @@ func syncRegistry(ctx context.Context, regCfg RegistryConfig, upstreamURL string
}
// push from cache to repo
err = pushSyncedLocalImage(localRepo, tag, localCachePath, imageStore, log)
if err != nil {
log.Error().Str("errorType", TypeOf(err)).
Err(err).Msgf("error while pushing synced cached image %s",
@@ -573,7 +573,8 @@ func getLocalContexts(log log.Logger) (*types.SystemContext, *signature.PolicyCo
return localCtx, policyContext, nil
}
func Run(ctx context.Context, cfg Config, storeController storage.StoreController,
func Run(ctx context.Context, cfg Config,
storeController storage.StoreController,
wtgrp *goSync.WaitGroup, logger log.Logger,
) error {
var credentialsFile CredentialsFile
+13 -6
View File
@@ -61,7 +61,9 @@ func TestInjectSyncUtils(t *testing.T) {
log := log.Logger{Logger: zerolog.New(os.Stdout)}
metrics := monitoring.NewMetricsServer(false, log)
imageStore := storage.NewImageStore(t.TempDir(), false, storage.DefaultGCDelay, false, false, log, metrics)
imageStore := storage.NewImageStore(t.TempDir(), false, storage.DefaultGCDelay,
false, false, log, metrics, nil,
)
injected = test.InjectFailure(0)
_, err = getLocalCachePath(imageStore, testImage)
@@ -147,7 +149,8 @@ func TestSyncInternal(t *testing.T) {
}
ctx := context.Background()
So(Run(ctx, cfg, storage.StoreController{}, new(goSync.WaitGroup), log.NewLogger("debug", "")), ShouldNotBeNil)
So(Run(ctx, cfg, storage.StoreController{},
new(goSync.WaitGroup), log.NewLogger("debug", "")), ShouldNotBeNil)
_, err = getFileCredentials("/invalid/path/to/file")
So(err, ShouldNotBeNil)
@@ -157,7 +160,8 @@ func TestSyncInternal(t *testing.T) {
log := log.Logger{Logger: zerolog.New(os.Stdout)}
metrics := monitoring.NewMetricsServer(false, log)
imageStore := storage.NewImageStore(t.TempDir(), false, storage.DefaultGCDelay, false, false, log, metrics)
imageStore := storage.NewImageStore(t.TempDir(), false, storage.DefaultGCDelay,
false, false, log, metrics, nil)
err := os.Chmod(imageStore.RootDir(), 0o000)
So(err, ShouldBeNil)
@@ -340,7 +344,8 @@ func TestSyncInternal(t *testing.T) {
log := log.Logger{Logger: zerolog.New(os.Stdout)}
metrics := monitoring.NewMetricsServer(false, log)
imageStore := storage.NewImageStore(storageDir, false, storage.DefaultGCDelay, false, false, log, metrics)
imageStore := storage.NewImageStore(storageDir, false, storage.DefaultGCDelay,
false, false, log, metrics, nil)
refs := ReferenceList{[]artifactspec.Descriptor{
{
@@ -422,7 +427,8 @@ func TestSyncInternal(t *testing.T) {
log := log.Logger{Logger: zerolog.New(os.Stdout)}
metrics := monitoring.NewMetricsServer(false, log)
imageStore := storage.NewImageStore(storageDir, false, storage.DefaultGCDelay, false, false, log, metrics)
imageStore := storage.NewImageStore(storageDir, false, storage.DefaultGCDelay,
false, false, log, metrics, nil)
storeController := storage.StoreController{}
storeController.DefaultStore = imageStore
@@ -443,7 +449,8 @@ func TestSyncInternal(t *testing.T) {
panic(err)
}
testImageStore := storage.NewImageStore(testRootDir, false, storage.DefaultGCDelay, false, false, log, metrics)
testImageStore := storage.NewImageStore(testRootDir, false,
storage.DefaultGCDelay, false, false, log, metrics, nil)
manifestContent, _, _, err := testImageStore.GetImageManifest(testImage, testImageTag)
So(err, ShouldBeNil)
+101
View File
@@ -862,6 +862,107 @@ func TestConfigReloader(t *testing.T) {
})
}
func TestMandatoryAnnotations(t *testing.T) {
Convey("Verify mandatory annotations failing - on demand disabled", t, func() {
updateDuration, _ := time.ParseDuration("30m")
sctlr, srcBaseURL, _, _, _ := startUpstreamServer(t, false, false)
defer func() {
sctlr.Shutdown()
}()
regex := ".*"
var semver bool
tlsVerify := false
syncRegistryConfig := sync.RegistryConfig{
Content: []sync.Content{
{
Prefix: testImage,
Tags: &sync.Tags{
Regex: &regex,
Semver: &semver,
},
},
},
URLs: []string{srcBaseURL},
OnDemand: false,
PollInterval: updateDuration,
TLSVerify: &tlsVerify,
}
defaultVal := true
syncConfig := &sync.Config{
Enable: &defaultVal,
Registries: []sync.RegistryConfig{syncRegistryConfig},
}
destPort := test.GetFreePort()
destConfig := config.New()
destClient := resty.New()
destBaseURL := test.GetBaseURL(destPort)
destConfig.HTTP.Port = destPort
destDir := t.TempDir()
destConfig.Storage.RootDirectory = destDir
destConfig.Storage.Dedupe = false
destConfig.Storage.GC = false
destConfig.Extensions = &extconf.ExtensionConfig{}
destConfig.Extensions.Sync = syncConfig
logFile, err := ioutil.TempFile("", "zot-log*.txt")
So(err, ShouldBeNil)
destConfig.Log.Output = logFile.Name()
lintEnabled := true
destConfig.Extensions.Lint = &extconf.LintConfig{}
destConfig.Extensions.Lint.Enabled = &lintEnabled
destConfig.Extensions.Lint.MandatoryAnnotations = []string{"annot1", "annot2", "annot3"}
dctlr := api.NewController(destConfig)
go func() {
// this blocks
if err := dctlr.Run(context.Background()); err != nil {
return
}
}()
// wait till ready
for {
_, err := destClient.R().Get(destBaseURL)
if err == nil {
break
}
time.Sleep(100 * time.Millisecond)
}
defer func() {
dctlr.Shutdown()
}()
// give it time to set up sync
time.Sleep(3 * time.Second)
resp, err := destClient.R().Get(destBaseURL + "/v2/" + testImage + "/manifest/0.0.1")
So(err, ShouldBeNil)
So(resp, ShouldNotBeNil)
So(resp.StatusCode(), ShouldEqual, 404)
data, err := os.ReadFile(logFile.Name())
t.Logf("downstream log: %s", string(data))
So(err, ShouldBeNil)
So(string(data), ShouldContainSubstring, "couldn't upload manifest because of missing annotations")
})
}
func TestBadTLS(t *testing.T) {
Convey("Verify sync TLS feature", t, func() {
updateDuration, _ := time.ParseDuration("30m")
+12 -2
View File
@@ -270,7 +270,9 @@ func pushSyncedLocalImage(localRepo, tag, localCachePath string,
log.Info().Msgf("pushing synced local image %s/%s:%s to local registry", localCachePath, localRepo, tag)
metrics := monitoring.NewMetricsServer(false, log)
cacheImageStore := storage.NewImageStore(localCachePath, false, storage.DefaultGCDelay, false, false, log, metrics)
cacheImageStore := storage.NewImageStore(localCachePath, false,
storage.DefaultGCDelay, false, false, log, metrics, nil)
manifestContent, _, _, err := cacheImageStore.GetImageManifest(localRepo, tag)
if err != nil {
@@ -331,8 +333,16 @@ func pushSyncedLocalImage(localRepo, tag, localCachePath string,
}
}
_, err = imageStore.PutImageManifest(localRepo, tag, ispec.MediaTypeImageManifest, manifestContent)
_, err = imageStore.PutImageManifest(localRepo, tag,
ispec.MediaTypeImageManifest, manifestContent)
if err != nil {
if errors.Is(err, zerr.ErrImageLintAnnotations) {
log.Error().Str("errorType", TypeOf(err)).
Err(err).Msg("couldn't upload manifest because of missing annotations")
return nil
}
log.Error().Str("errorType", TypeOf(err)).
Err(err).Msg("couldn't upload manifest")