mirror of
https://github.com/containers/podman.git
synced 2025-12-10 07:42:12 +08:00
Also includes unreleased https://github.com/openshift/imagebuilder/pull/246 to work with the updated docker/docker dependency. And updates some references to newly deprecated docker/docker symbols. [NO NEW TESTS NEEDED] Signed-off-by: Miloslav Trmač <mitr@redhat.com>
73 lines
2.8 KiB
Go
73 lines
2.8 KiB
Go
package manifest
|
||
|
||
import (
|
||
"encoding/json"
|
||
"fmt"
|
||
)
|
||
|
||
// AllowedManifestFields is a bit mask of “essential” manifest fields that ValidateUnambiguousManifestFormat
|
||
// can expect to be present.
|
||
type AllowedManifestFields int
|
||
|
||
const (
|
||
AllowedFieldConfig AllowedManifestFields = 1 << iota
|
||
AllowedFieldFSLayers
|
||
AllowedFieldHistory
|
||
AllowedFieldLayers
|
||
AllowedFieldManifests
|
||
AllowedFieldFirstUnusedBit // Keep this at the end!
|
||
)
|
||
|
||
// ValidateUnambiguousManifestFormat rejects manifests (incl. multi-arch) that look like more than
|
||
// one kind we currently recognize, i.e. if they contain any of the known “essential” format fields
|
||
// other than the ones the caller specifically allows.
|
||
// expectedMIMEType is used only for diagnostics.
|
||
// NOTE: The caller should do the non-heuristic validations (e.g. check for any specified format
|
||
// identification/version, or other “magic numbers”) before calling this, to cleanly reject unambiguous
|
||
// data that just isn’t what was expected, as opposed to actually ambiguous data.
|
||
func ValidateUnambiguousManifestFormat(manifest []byte, expectedMIMEType string,
|
||
allowed AllowedManifestFields) error {
|
||
if allowed >= AllowedFieldFirstUnusedBit {
|
||
return fmt.Errorf("internal error: invalid allowedManifestFields value %#v", allowed)
|
||
}
|
||
// Use a private type to decode, not just a map[string]any, because we want
|
||
// to also reject case-insensitive matches (which would be used by Go when really decoding
|
||
// the manifest).
|
||
// (It is expected that as manifest formats are added or extended over time, more fields will be added
|
||
// here.)
|
||
detectedFields := struct {
|
||
Config any `json:"config"`
|
||
FSLayers any `json:"fsLayers"`
|
||
History any `json:"history"`
|
||
Layers any `json:"layers"`
|
||
Manifests any `json:"manifests"`
|
||
}{}
|
||
if err := json.Unmarshal(manifest, &detectedFields); err != nil {
|
||
// The caller was supposed to already validate version numbers, so this should not happen;
|
||
// let’s not bother with making this error “nice”.
|
||
return err
|
||
}
|
||
unexpected := []string{}
|
||
// Sadly this isn’t easy to automate in Go, without reflection. So, copy&paste.
|
||
if detectedFields.Config != nil && (allowed&AllowedFieldConfig) == 0 {
|
||
unexpected = append(unexpected, "config")
|
||
}
|
||
if detectedFields.FSLayers != nil && (allowed&AllowedFieldFSLayers) == 0 {
|
||
unexpected = append(unexpected, "fsLayers")
|
||
}
|
||
if detectedFields.History != nil && (allowed&AllowedFieldHistory) == 0 {
|
||
unexpected = append(unexpected, "history")
|
||
}
|
||
if detectedFields.Layers != nil && (allowed&AllowedFieldLayers) == 0 {
|
||
unexpected = append(unexpected, "layers")
|
||
}
|
||
if detectedFields.Manifests != nil && (allowed&AllowedFieldManifests) == 0 {
|
||
unexpected = append(unexpected, "manifests")
|
||
}
|
||
if len(unexpected) != 0 {
|
||
return fmt.Errorf(`rejecting ambiguous manifest, unexpected fields %#v in supposedly %s`,
|
||
unexpected, expectedMIMEType)
|
||
}
|
||
return nil
|
||
}
|