...
1 package schema1
2
3 import (
4 "encoding/json"
5 "fmt"
6
7 "github.com/docker/distribution"
8 "github.com/docker/distribution/manifest"
9 "github.com/docker/libtrust"
10 "github.com/opencontainers/go-digest"
11 )
12
13 const (
14
15
16 MediaTypeManifest = "application/vnd.docker.distribution.manifest.v1+json"
17
18 MediaTypeSignedManifest = "application/vnd.docker.distribution.manifest.v1+prettyjws"
19
20 MediaTypeManifestLayer = "application/vnd.docker.container.image.rootfs.diff+x-gtar"
21 )
22
23 var (
24
25
26 SchemaVersion = manifest.Versioned{
27 SchemaVersion: 1,
28 }
29 )
30
31 func init() {
32 schema1Func := func(b []byte) (distribution.Manifest, distribution.Descriptor, error) {
33 sm := new(SignedManifest)
34 err := sm.UnmarshalJSON(b)
35 if err != nil {
36 return nil, distribution.Descriptor{}, err
37 }
38
39 desc := distribution.Descriptor{
40 Digest: digest.FromBytes(sm.Canonical),
41 Size: int64(len(sm.Canonical)),
42 MediaType: MediaTypeSignedManifest,
43 }
44 return sm, desc, err
45 }
46 err := distribution.RegisterManifestSchema(MediaTypeSignedManifest, schema1Func)
47 if err != nil {
48 panic(fmt.Sprintf("Unable to register manifest: %s", err))
49 }
50 err = distribution.RegisterManifestSchema("", schema1Func)
51 if err != nil {
52 panic(fmt.Sprintf("Unable to register manifest: %s", err))
53 }
54 err = distribution.RegisterManifestSchema("application/json", schema1Func)
55 if err != nil {
56 panic(fmt.Sprintf("Unable to register manifest: %s", err))
57 }
58 }
59
60
61 type FSLayer struct {
62
63 BlobSum digest.Digest `json:"blobSum"`
64 }
65
66
67 type History struct {
68
69 V1Compatibility string `json:"v1Compatibility"`
70 }
71
72
73
74 type Manifest struct {
75 manifest.Versioned
76
77
78 Name string `json:"name"`
79
80
81 Tag string `json:"tag"`
82
83
84
85 Architecture string `json:"architecture"`
86
87
88 FSLayers []FSLayer `json:"fsLayers"`
89
90
91 History []History `json:"history"`
92 }
93
94
95
96 type SignedManifest struct {
97 Manifest
98
99
100
101
102 Canonical []byte `json:"-"`
103
104
105
106 all []byte
107 }
108
109
110 func (sm *SignedManifest) UnmarshalJSON(b []byte) error {
111 sm.all = make([]byte, len(b))
112
113 copy(sm.all, b)
114
115 jsig, err := libtrust.ParsePrettySignature(b, "signatures")
116 if err != nil {
117 return err
118 }
119
120
121 bytes, err := jsig.Payload()
122 if err != nil {
123 return err
124 }
125
126
127 sm.Canonical = make([]byte, len(bytes))
128 copy(sm.Canonical, bytes)
129
130
131 var manifest Manifest
132 if err := json.Unmarshal(sm.Canonical, &manifest); err != nil {
133 return err
134 }
135
136 sm.Manifest = manifest
137
138 return nil
139 }
140
141
142 func (sm SignedManifest) References() []distribution.Descriptor {
143 dependencies := make([]distribution.Descriptor, len(sm.FSLayers))
144 for i, fsLayer := range sm.FSLayers {
145 dependencies[i] = distribution.Descriptor{
146 MediaType: "application/vnd.docker.container.image.rootfs.diff+x-gtar",
147 Digest: fsLayer.BlobSum,
148 }
149 }
150
151 return dependencies
152
153 }
154
155
156
157
158
159 func (sm *SignedManifest) MarshalJSON() ([]byte, error) {
160 if len(sm.all) > 0 {
161 return sm.all, nil
162 }
163
164
165 return json.Marshal(&sm.Manifest)
166 }
167
168
169 func (sm SignedManifest) Payload() (string, []byte, error) {
170 return MediaTypeSignedManifest, sm.all, nil
171 }
172
173
174
175
176 func (sm *SignedManifest) Signatures() ([][]byte, error) {
177 jsig, err := libtrust.ParsePrettySignature(sm.all, "signatures")
178 if err != nil {
179 return nil, err
180 }
181
182
183 return jsig.Signatures()
184 }
185
View as plain text