mirror of
https://github.com/rancher/os.git
synced 2025-09-01 23:04:41 +00:00
Update vendor
This commit is contained in:
281
vendor/github.com/docker/distribution/manifest/schema1/config_builder.go
generated
vendored
Normal file
281
vendor/github.com/docker/distribution/manifest/schema1/config_builder.go
generated
vendored
Normal file
@@ -0,0 +1,281 @@
|
||||
package schema1
|
||||
|
||||
import (
|
||||
"crypto/sha512"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/docker/distribution"
|
||||
"github.com/docker/distribution/context"
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/docker/libtrust"
|
||||
|
||||
"github.com/docker/distribution/digest"
|
||||
"github.com/docker/distribution/manifest"
|
||||
)
|
||||
|
||||
type diffID digest.Digest
|
||||
|
||||
// gzippedEmptyTar is a gzip-compressed version of an empty tar file
|
||||
// (1024 NULL bytes)
|
||||
var gzippedEmptyTar = []byte{
|
||||
31, 139, 8, 0, 0, 9, 110, 136, 0, 255, 98, 24, 5, 163, 96, 20, 140, 88,
|
||||
0, 8, 0, 0, 255, 255, 46, 175, 181, 239, 0, 4, 0, 0,
|
||||
}
|
||||
|
||||
// digestSHA256GzippedEmptyTar is the canonical sha256 digest of
|
||||
// gzippedEmptyTar
|
||||
const digestSHA256GzippedEmptyTar = digest.Digest("sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4")
|
||||
|
||||
// configManifestBuilder is a type for constructing manifests from an image
|
||||
// configuration and generic descriptors.
|
||||
type configManifestBuilder struct {
|
||||
// bs is a BlobService used to create empty layer tars in the
|
||||
// blob store if necessary.
|
||||
bs distribution.BlobService
|
||||
// pk is the libtrust private key used to sign the final manifest.
|
||||
pk libtrust.PrivateKey
|
||||
// configJSON is configuration supplied when the ManifestBuilder was
|
||||
// created.
|
||||
configJSON []byte
|
||||
// ref contains the name and optional tag provided to NewConfigManifestBuilder.
|
||||
ref reference.Named
|
||||
// descriptors is the set of descriptors referencing the layers.
|
||||
descriptors []distribution.Descriptor
|
||||
// emptyTarDigest is set to a valid digest if an empty tar has been
|
||||
// put in the blob store; otherwise it is empty.
|
||||
emptyTarDigest digest.Digest
|
||||
}
|
||||
|
||||
// NewConfigManifestBuilder is used to build new manifests for the current
|
||||
// schema version from an image configuration and a set of descriptors.
|
||||
// It takes a BlobService so that it can add an empty tar to the blob store
|
||||
// if the resulting manifest needs empty layers.
|
||||
func NewConfigManifestBuilder(bs distribution.BlobService, pk libtrust.PrivateKey, ref reference.Named, configJSON []byte) distribution.ManifestBuilder {
|
||||
return &configManifestBuilder{
|
||||
bs: bs,
|
||||
pk: pk,
|
||||
configJSON: configJSON,
|
||||
ref: ref,
|
||||
}
|
||||
}
|
||||
|
||||
// Build produces a final manifest from the given references
|
||||
func (mb *configManifestBuilder) Build(ctx context.Context) (m distribution.Manifest, err error) {
|
||||
type imageRootFS struct {
|
||||
Type string `json:"type"`
|
||||
DiffIDs []diffID `json:"diff_ids,omitempty"`
|
||||
BaseLayer string `json:"base_layer,omitempty"`
|
||||
}
|
||||
|
||||
type imageHistory struct {
|
||||
Created time.Time `json:"created"`
|
||||
Author string `json:"author,omitempty"`
|
||||
CreatedBy string `json:"created_by,omitempty"`
|
||||
Comment string `json:"comment,omitempty"`
|
||||
EmptyLayer bool `json:"empty_layer,omitempty"`
|
||||
}
|
||||
|
||||
type imageConfig struct {
|
||||
RootFS *imageRootFS `json:"rootfs,omitempty"`
|
||||
History []imageHistory `json:"history,omitempty"`
|
||||
Architecture string `json:"architecture,omitempty"`
|
||||
}
|
||||
|
||||
var img imageConfig
|
||||
|
||||
if err := json.Unmarshal(mb.configJSON, &img); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(img.History) == 0 {
|
||||
return nil, errors.New("empty history when trying to create schema1 manifest")
|
||||
}
|
||||
|
||||
if len(img.RootFS.DiffIDs) != len(mb.descriptors) {
|
||||
return nil, errors.New("number of descriptors and number of layers in rootfs must match")
|
||||
}
|
||||
|
||||
// Generate IDs for each layer
|
||||
// For non-top-level layers, create fake V1Compatibility strings that
|
||||
// fit the format and don't collide with anything else, but don't
|
||||
// result in runnable images on their own.
|
||||
type v1Compatibility struct {
|
||||
ID string `json:"id"`
|
||||
Parent string `json:"parent,omitempty"`
|
||||
Comment string `json:"comment,omitempty"`
|
||||
Created time.Time `json:"created"`
|
||||
ContainerConfig struct {
|
||||
Cmd []string
|
||||
} `json:"container_config,omitempty"`
|
||||
ThrowAway bool `json:"throwaway,omitempty"`
|
||||
}
|
||||
|
||||
fsLayerList := make([]FSLayer, len(img.History))
|
||||
history := make([]History, len(img.History))
|
||||
|
||||
parent := ""
|
||||
layerCounter := 0
|
||||
for i, h := range img.History[:len(img.History)-1] {
|
||||
var blobsum digest.Digest
|
||||
if h.EmptyLayer {
|
||||
if blobsum, err = mb.emptyTar(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
if len(img.RootFS.DiffIDs) <= layerCounter {
|
||||
return nil, errors.New("too many non-empty layers in History section")
|
||||
}
|
||||
blobsum = mb.descriptors[layerCounter].Digest
|
||||
layerCounter++
|
||||
}
|
||||
|
||||
v1ID := digest.FromBytes([]byte(blobsum.Hex() + " " + parent)).Hex()
|
||||
|
||||
if i == 0 && img.RootFS.BaseLayer != "" {
|
||||
// windows-only baselayer setup
|
||||
baseID := sha512.Sum384([]byte(img.RootFS.BaseLayer))
|
||||
parent = fmt.Sprintf("%x", baseID[:32])
|
||||
}
|
||||
|
||||
v1Compatibility := v1Compatibility{
|
||||
ID: v1ID,
|
||||
Parent: parent,
|
||||
Comment: h.Comment,
|
||||
Created: h.Created,
|
||||
}
|
||||
v1Compatibility.ContainerConfig.Cmd = []string{img.History[i].CreatedBy}
|
||||
if h.EmptyLayer {
|
||||
v1Compatibility.ThrowAway = true
|
||||
}
|
||||
jsonBytes, err := json.Marshal(&v1Compatibility)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
reversedIndex := len(img.History) - i - 1
|
||||
history[reversedIndex].V1Compatibility = string(jsonBytes)
|
||||
fsLayerList[reversedIndex] = FSLayer{BlobSum: blobsum}
|
||||
|
||||
parent = v1ID
|
||||
}
|
||||
|
||||
latestHistory := img.History[len(img.History)-1]
|
||||
|
||||
var blobsum digest.Digest
|
||||
if latestHistory.EmptyLayer {
|
||||
if blobsum, err = mb.emptyTar(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
if len(img.RootFS.DiffIDs) <= layerCounter {
|
||||
return nil, errors.New("too many non-empty layers in History section")
|
||||
}
|
||||
blobsum = mb.descriptors[layerCounter].Digest
|
||||
}
|
||||
|
||||
fsLayerList[0] = FSLayer{BlobSum: blobsum}
|
||||
dgst := digest.FromBytes([]byte(blobsum.Hex() + " " + parent + " " + string(mb.configJSON)))
|
||||
|
||||
// Top-level v1compatibility string should be a modified version of the
|
||||
// image config.
|
||||
transformedConfig, err := MakeV1ConfigFromConfig(mb.configJSON, dgst.Hex(), parent, latestHistory.EmptyLayer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
history[0].V1Compatibility = string(transformedConfig)
|
||||
|
||||
tag := ""
|
||||
if tagged, isTagged := mb.ref.(reference.Tagged); isTagged {
|
||||
tag = tagged.Tag()
|
||||
}
|
||||
|
||||
mfst := Manifest{
|
||||
Versioned: manifest.Versioned{
|
||||
SchemaVersion: 1,
|
||||
},
|
||||
Name: mb.ref.Name(),
|
||||
Tag: tag,
|
||||
Architecture: img.Architecture,
|
||||
FSLayers: fsLayerList,
|
||||
History: history,
|
||||
}
|
||||
|
||||
return Sign(&mfst, mb.pk)
|
||||
}
|
||||
|
||||
// emptyTar pushes a compressed empty tar to the blob store if one doesn't
|
||||
// already exist, and returns its blobsum.
|
||||
func (mb *configManifestBuilder) emptyTar(ctx context.Context) (digest.Digest, error) {
|
||||
if mb.emptyTarDigest != "" {
|
||||
// Already put an empty tar
|
||||
return mb.emptyTarDigest, nil
|
||||
}
|
||||
|
||||
descriptor, err := mb.bs.Stat(ctx, digestSHA256GzippedEmptyTar)
|
||||
switch err {
|
||||
case nil:
|
||||
mb.emptyTarDigest = descriptor.Digest
|
||||
return descriptor.Digest, nil
|
||||
case distribution.ErrBlobUnknown:
|
||||
// nop
|
||||
default:
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Add gzipped empty tar to the blob store
|
||||
descriptor, err = mb.bs.Put(ctx, "", gzippedEmptyTar)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
mb.emptyTarDigest = descriptor.Digest
|
||||
|
||||
return descriptor.Digest, nil
|
||||
}
|
||||
|
||||
// AppendReference adds a reference to the current ManifestBuilder
|
||||
func (mb *configManifestBuilder) AppendReference(d distribution.Describable) error {
|
||||
// todo: verification here?
|
||||
mb.descriptors = append(mb.descriptors, d.Descriptor())
|
||||
return nil
|
||||
}
|
||||
|
||||
// References returns the current references added to this builder
|
||||
func (mb *configManifestBuilder) References() []distribution.Descriptor {
|
||||
return mb.descriptors
|
||||
}
|
||||
|
||||
// MakeV1ConfigFromConfig creates an legacy V1 image config from image config JSON
|
||||
func MakeV1ConfigFromConfig(configJSON []byte, v1ID, parentV1ID string, throwaway bool) ([]byte, error) {
|
||||
// Top-level v1compatibility string should be a modified version of the
|
||||
// image config.
|
||||
var configAsMap map[string]*json.RawMessage
|
||||
if err := json.Unmarshal(configJSON, &configAsMap); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Delete fields that didn't exist in old manifest
|
||||
delete(configAsMap, "rootfs")
|
||||
delete(configAsMap, "history")
|
||||
configAsMap["id"] = rawJSON(v1ID)
|
||||
if parentV1ID != "" {
|
||||
configAsMap["parent"] = rawJSON(parentV1ID)
|
||||
}
|
||||
if throwaway {
|
||||
configAsMap["throwaway"] = rawJSON(true)
|
||||
}
|
||||
|
||||
return json.Marshal(configAsMap)
|
||||
}
|
||||
|
||||
func rawJSON(value interface{}) *json.RawMessage {
|
||||
jsonval, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return (*json.RawMessage)(&jsonval)
|
||||
}
|
184
vendor/github.com/docker/distribution/manifest/schema1/manifest.go
generated
vendored
Normal file
184
vendor/github.com/docker/distribution/manifest/schema1/manifest.go
generated
vendored
Normal file
@@ -0,0 +1,184 @@
|
||||
package schema1
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/distribution"
|
||||
"github.com/docker/distribution/digest"
|
||||
"github.com/docker/distribution/manifest"
|
||||
"github.com/docker/libtrust"
|
||||
)
|
||||
|
||||
const (
|
||||
// MediaTypeManifest specifies the mediaType for the current version. Note
|
||||
// that for schema version 1, the the media is optionally "application/json".
|
||||
MediaTypeManifest = "application/vnd.docker.distribution.manifest.v1+json"
|
||||
// MediaTypeSignedManifest specifies the mediatype for current SignedManifest version
|
||||
MediaTypeSignedManifest = "application/vnd.docker.distribution.manifest.v1+prettyjws"
|
||||
// MediaTypeManifestLayer specifies the media type for manifest layers
|
||||
MediaTypeManifestLayer = "application/vnd.docker.container.image.rootfs.diff+x-gtar"
|
||||
)
|
||||
|
||||
var (
|
||||
// SchemaVersion provides a pre-initialized version structure for this
|
||||
// packages version of the manifest.
|
||||
SchemaVersion = manifest.Versioned{
|
||||
SchemaVersion: 1,
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
schema1Func := func(b []byte) (distribution.Manifest, distribution.Descriptor, error) {
|
||||
sm := new(SignedManifest)
|
||||
err := sm.UnmarshalJSON(b)
|
||||
if err != nil {
|
||||
return nil, distribution.Descriptor{}, err
|
||||
}
|
||||
|
||||
desc := distribution.Descriptor{
|
||||
Digest: digest.FromBytes(sm.Canonical),
|
||||
Size: int64(len(sm.Canonical)),
|
||||
MediaType: MediaTypeSignedManifest,
|
||||
}
|
||||
return sm, desc, err
|
||||
}
|
||||
err := distribution.RegisterManifestSchema(MediaTypeSignedManifest, schema1Func)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Unable to register manifest: %s", err))
|
||||
}
|
||||
err = distribution.RegisterManifestSchema("", schema1Func)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Unable to register manifest: %s", err))
|
||||
}
|
||||
err = distribution.RegisterManifestSchema("application/json", schema1Func)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Unable to register manifest: %s", err))
|
||||
}
|
||||
}
|
||||
|
||||
// FSLayer is a container struct for BlobSums defined in an image manifest
|
||||
type FSLayer struct {
|
||||
// BlobSum is the tarsum of the referenced filesystem image layer
|
||||
BlobSum digest.Digest `json:"blobSum"`
|
||||
}
|
||||
|
||||
// History stores unstructured v1 compatibility information
|
||||
type History struct {
|
||||
// V1Compatibility is the raw v1 compatibility information
|
||||
V1Compatibility string `json:"v1Compatibility"`
|
||||
}
|
||||
|
||||
// Manifest provides the base accessible fields for working with V2 image
|
||||
// format in the registry.
|
||||
type Manifest struct {
|
||||
manifest.Versioned
|
||||
|
||||
// Name is the name of the image's repository
|
||||
Name string `json:"name"`
|
||||
|
||||
// Tag is the tag of the image specified by this manifest
|
||||
Tag string `json:"tag"`
|
||||
|
||||
// Architecture is the host architecture on which this image is intended to
|
||||
// run
|
||||
Architecture string `json:"architecture"`
|
||||
|
||||
// FSLayers is a list of filesystem layer blobSums contained in this image
|
||||
FSLayers []FSLayer `json:"fsLayers"`
|
||||
|
||||
// History is a list of unstructured historical data for v1 compatibility
|
||||
History []History `json:"history"`
|
||||
}
|
||||
|
||||
// SignedManifest provides an envelope for a signed image manifest, including
|
||||
// the format sensitive raw bytes.
|
||||
type SignedManifest struct {
|
||||
Manifest
|
||||
|
||||
// Canonical is the canonical byte representation of the ImageManifest,
|
||||
// without any attached signatures. The manifest byte
|
||||
// representation cannot change or it will have to be re-signed.
|
||||
Canonical []byte `json:"-"`
|
||||
|
||||
// all contains the byte representation of the Manifest including signatures
|
||||
// and is returned by Payload()
|
||||
all []byte
|
||||
}
|
||||
|
||||
// UnmarshalJSON populates a new SignedManifest struct from JSON data.
|
||||
func (sm *SignedManifest) UnmarshalJSON(b []byte) error {
|
||||
sm.all = make([]byte, len(b), len(b))
|
||||
// store manifest and signatures in all
|
||||
copy(sm.all, b)
|
||||
|
||||
jsig, err := libtrust.ParsePrettySignature(b, "signatures")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Resolve the payload in the manifest.
|
||||
bytes, err := jsig.Payload()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// sm.Canonical stores the canonical manifest JSON
|
||||
sm.Canonical = make([]byte, len(bytes), len(bytes))
|
||||
copy(sm.Canonical, bytes)
|
||||
|
||||
// Unmarshal canonical JSON into Manifest object
|
||||
var manifest Manifest
|
||||
if err := json.Unmarshal(sm.Canonical, &manifest); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sm.Manifest = manifest
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// References returnes the descriptors of this manifests references
|
||||
func (sm SignedManifest) References() []distribution.Descriptor {
|
||||
dependencies := make([]distribution.Descriptor, len(sm.FSLayers))
|
||||
for i, fsLayer := range sm.FSLayers {
|
||||
dependencies[i] = distribution.Descriptor{
|
||||
MediaType: "application/vnd.docker.container.image.rootfs.diff+x-gtar",
|
||||
Digest: fsLayer.BlobSum,
|
||||
}
|
||||
}
|
||||
|
||||
return dependencies
|
||||
|
||||
}
|
||||
|
||||
// MarshalJSON returns the contents of raw. If Raw is nil, marshals the inner
|
||||
// contents. Applications requiring a marshaled signed manifest should simply
|
||||
// use Raw directly, since the the content produced by json.Marshal will be
|
||||
// compacted and will fail signature checks.
|
||||
func (sm *SignedManifest) MarshalJSON() ([]byte, error) {
|
||||
if len(sm.all) > 0 {
|
||||
return sm.all, nil
|
||||
}
|
||||
|
||||
// If the raw data is not available, just dump the inner content.
|
||||
return json.Marshal(&sm.Manifest)
|
||||
}
|
||||
|
||||
// Payload returns the signed content of the signed manifest.
|
||||
func (sm SignedManifest) Payload() (string, []byte, error) {
|
||||
return MediaTypeSignedManifest, sm.all, nil
|
||||
}
|
||||
|
||||
// Signatures returns the signatures as provided by
|
||||
// (*libtrust.JSONSignature).Signatures. The byte slices are opaque jws
|
||||
// signatures.
|
||||
func (sm *SignedManifest) Signatures() ([][]byte, error) {
|
||||
jsig, err := libtrust.ParsePrettySignature(sm.all, "signatures")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Resolve the payload in the manifest.
|
||||
return jsig.Signatures()
|
||||
}
|
98
vendor/github.com/docker/distribution/manifest/schema1/reference_builder.go
generated
vendored
Normal file
98
vendor/github.com/docker/distribution/manifest/schema1/reference_builder.go
generated
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
package schema1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"errors"
|
||||
"github.com/docker/distribution"
|
||||
"github.com/docker/distribution/context"
|
||||
"github.com/docker/distribution/digest"
|
||||
"github.com/docker/distribution/manifest"
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/docker/libtrust"
|
||||
)
|
||||
|
||||
// referenceManifestBuilder is a type for constructing manifests from schema1
|
||||
// dependencies.
|
||||
type referenceManifestBuilder struct {
|
||||
Manifest
|
||||
pk libtrust.PrivateKey
|
||||
}
|
||||
|
||||
// NewReferenceManifestBuilder is used to build new manifests for the current
|
||||
// schema version using schema1 dependencies.
|
||||
func NewReferenceManifestBuilder(pk libtrust.PrivateKey, ref reference.Named, architecture string) distribution.ManifestBuilder {
|
||||
tag := ""
|
||||
if tagged, isTagged := ref.(reference.Tagged); isTagged {
|
||||
tag = tagged.Tag()
|
||||
}
|
||||
|
||||
return &referenceManifestBuilder{
|
||||
Manifest: Manifest{
|
||||
Versioned: manifest.Versioned{
|
||||
SchemaVersion: 1,
|
||||
},
|
||||
Name: ref.Name(),
|
||||
Tag: tag,
|
||||
Architecture: architecture,
|
||||
},
|
||||
pk: pk,
|
||||
}
|
||||
}
|
||||
|
||||
func (mb *referenceManifestBuilder) Build(ctx context.Context) (distribution.Manifest, error) {
|
||||
m := mb.Manifest
|
||||
if len(m.FSLayers) == 0 {
|
||||
return nil, errors.New("cannot build manifest with zero layers or history")
|
||||
}
|
||||
|
||||
m.FSLayers = make([]FSLayer, len(mb.Manifest.FSLayers))
|
||||
m.History = make([]History, len(mb.Manifest.History))
|
||||
copy(m.FSLayers, mb.Manifest.FSLayers)
|
||||
copy(m.History, mb.Manifest.History)
|
||||
|
||||
return Sign(&m, mb.pk)
|
||||
}
|
||||
|
||||
// AppendReference adds a reference to the current ManifestBuilder
|
||||
func (mb *referenceManifestBuilder) AppendReference(d distribution.Describable) error {
|
||||
r, ok := d.(Reference)
|
||||
if !ok {
|
||||
return fmt.Errorf("Unable to add non-reference type to v1 builder")
|
||||
}
|
||||
|
||||
// Entries need to be prepended
|
||||
mb.Manifest.FSLayers = append([]FSLayer{{BlobSum: r.Digest}}, mb.Manifest.FSLayers...)
|
||||
mb.Manifest.History = append([]History{r.History}, mb.Manifest.History...)
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
// References returns the current references added to this builder
|
||||
func (mb *referenceManifestBuilder) References() []distribution.Descriptor {
|
||||
refs := make([]distribution.Descriptor, len(mb.Manifest.FSLayers))
|
||||
for i := range mb.Manifest.FSLayers {
|
||||
layerDigest := mb.Manifest.FSLayers[i].BlobSum
|
||||
history := mb.Manifest.History[i]
|
||||
ref := Reference{layerDigest, 0, history}
|
||||
refs[i] = ref.Descriptor()
|
||||
}
|
||||
return refs
|
||||
}
|
||||
|
||||
// Reference describes a manifest v2, schema version 1 dependency.
|
||||
// An FSLayer associated with a history entry.
|
||||
type Reference struct {
|
||||
Digest digest.Digest
|
||||
Size int64 // if we know it, set it for the descriptor.
|
||||
History History
|
||||
}
|
||||
|
||||
// Descriptor describes a reference
|
||||
func (r Reference) Descriptor() distribution.Descriptor {
|
||||
return distribution.Descriptor{
|
||||
MediaType: MediaTypeManifestLayer,
|
||||
Digest: r.Digest,
|
||||
Size: r.Size,
|
||||
}
|
||||
}
|
68
vendor/github.com/docker/distribution/manifest/schema1/sign.go
generated
vendored
Normal file
68
vendor/github.com/docker/distribution/manifest/schema1/sign.go
generated
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
package schema1
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/docker/libtrust"
|
||||
)
|
||||
|
||||
// Sign signs the manifest with the provided private key, returning a
|
||||
// SignedManifest. This typically won't be used within the registry, except
|
||||
// for testing.
|
||||
func Sign(m *Manifest, pk libtrust.PrivateKey) (*SignedManifest, error) {
|
||||
p, err := json.MarshalIndent(m, "", " ")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
js, err := libtrust.NewJSONSignature(p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := js.Sign(pk); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pretty, err := js.PrettySignature("signatures")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &SignedManifest{
|
||||
Manifest: *m,
|
||||
all: pretty,
|
||||
Canonical: p,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SignWithChain signs the manifest with the given private key and x509 chain.
|
||||
// The public key of the first element in the chain must be the public key
|
||||
// corresponding with the sign key.
|
||||
func SignWithChain(m *Manifest, key libtrust.PrivateKey, chain []*x509.Certificate) (*SignedManifest, error) {
|
||||
p, err := json.MarshalIndent(m, "", " ")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
js, err := libtrust.NewJSONSignature(p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := js.SignWithChain(key, chain); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pretty, err := js.PrettySignature("signatures")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &SignedManifest{
|
||||
Manifest: *m,
|
||||
all: pretty,
|
||||
Canonical: p,
|
||||
}, nil
|
||||
}
|
32
vendor/github.com/docker/distribution/manifest/schema1/verify.go
generated
vendored
Normal file
32
vendor/github.com/docker/distribution/manifest/schema1/verify.go
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
package schema1
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/libtrust"
|
||||
)
|
||||
|
||||
// Verify verifies the signature of the signed manifest returning the public
|
||||
// keys used during signing.
|
||||
func Verify(sm *SignedManifest) ([]libtrust.PublicKey, error) {
|
||||
js, err := libtrust.ParsePrettySignature(sm.all, "signatures")
|
||||
if err != nil {
|
||||
logrus.WithField("err", err).Debugf("(*SignedManifest).Verify")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return js.Verify()
|
||||
}
|
||||
|
||||
// VerifyChains verifies the signature of the signed manifest against the
|
||||
// certificate pool returning the list of verified chains. Signatures without
|
||||
// an x509 chain are not checked.
|
||||
func VerifyChains(sm *SignedManifest, ca *x509.CertPool) ([][]*x509.Certificate, error) {
|
||||
js, err := libtrust.ParsePrettySignature(sm.all, "signatures")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return js.VerifyChains(ca)
|
||||
}
|
Reference in New Issue
Block a user