Temporarily remove imgcrypt in CRI to fix circular dependency
Signed-off-by: Derek McGowan <derek@mcg.dev>
This commit is contained in:
2
vendor/github.com/containerd/imgcrypt/.gitignore
generated
vendored
2
vendor/github.com/containerd/imgcrypt/.gitignore
generated
vendored
@@ -1,2 +0,0 @@
|
||||
*~
|
||||
/bin/
|
||||
20
vendor/github.com/containerd/imgcrypt/.golangci.yml
generated
vendored
20
vendor/github.com/containerd/imgcrypt/.golangci.yml
generated
vendored
@@ -1,20 +0,0 @@
|
||||
linters:
|
||||
enable:
|
||||
- structcheck
|
||||
- varcheck
|
||||
- staticcheck
|
||||
- unconvert
|
||||
- gofmt
|
||||
- goimports
|
||||
- revive
|
||||
- ineffassign
|
||||
- vet
|
||||
- unused
|
||||
- misspell
|
||||
|
||||
run:
|
||||
skip-dirs:
|
||||
- cmd/ctr/commands/run
|
||||
- cmd/ctr/commands/images
|
||||
- cmd\\ctr\\commands\\run
|
||||
- cmd\\ctr\\commands\\images
|
||||
48
vendor/github.com/containerd/imgcrypt/CHANGES
generated
vendored
48
vendor/github.com/containerd/imgcrypt/CHANGES
generated
vendored
@@ -1,48 +0,0 @@
|
||||
CHANGES
|
||||
|
||||
v1.1.7:
|
||||
- Added support for zstd-compressed layers
|
||||
- Update to ocicrypt v1.1.6 for zstd-related dependencies
|
||||
- Update to containerd v1.6.8
|
||||
- Sync'ed ctr-enc with upstream ctr changes to import command
|
||||
- Add support for --all-platforms to encrypt command of ctr-enc
|
||||
|
||||
v1.1.6:
|
||||
- Update to ocicrypt v1.1.5 for yaml v3.0 dependency
|
||||
- Update to containerd v1.6.6 for runc v1.1.2 dependency
|
||||
|
||||
v1.1.5:
|
||||
- Update to ocicrypt v1.1.4; sha256 is the default now for padding in OAEP
|
||||
for pkcs11; Set OCICRYPT_OAEP_HASHALG=sha1 environment variable to force
|
||||
sha1 usage, which is required for example for SoftHSM 2.6.1.
|
||||
|
||||
v1.1.4:
|
||||
- Fixed issue in CheckAuthorization() callpath for images with a ManifestList
|
||||
- CVE-2022-24778
|
||||
- Fix: https://github.com/containerd/imgcrypt/commit/6fdd9818a4d8142107b7ecd767d839c9707700d9
|
||||
- Added test case covering this
|
||||
- Updated to ocicrypt 1.1.3
|
||||
- Updated to containerd 1.6.1
|
||||
|
||||
v1.1.3:
|
||||
- Release v1.1.3 addresses issue #62 due to re-tagging of v1.1.2
|
||||
- docs: update referenced containerd project branch to main
|
||||
- Update linter to match containerd repo
|
||||
- Update CI golang version
|
||||
- Updated to containerd 1.5.8
|
||||
|
||||
v1.1.2:
|
||||
- Decouple CreateCryptoConfig() from github.com/urfave/cli
|
||||
- Updated to containerd 1.5.7
|
||||
- Implemented ConvertFunc for image en- and decryption
|
||||
- Replace pkg/errors with errors package
|
||||
- Updated to ocicrypt 1.1.2
|
||||
- Sync'ed ctr-enc with ctr of containerd-1.5.0
|
||||
|
||||
v1.1.1:
|
||||
- rebased on ocicrypt 1.1.1
|
||||
|
||||
v1.1.0:
|
||||
- rebased on ocicrypt 1.1.0
|
||||
- added pkcs11 support; experimental
|
||||
- added keyprovider support
|
||||
191
vendor/github.com/containerd/imgcrypt/LICENSE
generated
vendored
191
vendor/github.com/containerd/imgcrypt/LICENSE
generated
vendored
@@ -1,191 +0,0 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
https://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Copyright The containerd Authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
9
vendor/github.com/containerd/imgcrypt/MAINTAINERS
generated
vendored
9
vendor/github.com/containerd/imgcrypt/MAINTAINERS
generated
vendored
@@ -1,9 +0,0 @@
|
||||
# imgcrypt maintainers
|
||||
#
|
||||
# As a containerd sub-project, containerd maintainers are also included from https://github.com/containerd/project/blob/main/MAINTAINERS.
|
||||
# See https://github.com/containerd/project/blob/main/GOVERNANCE.md for description of maintainer role
|
||||
#
|
||||
# MAINTAINERS
|
||||
# GitHub ID, Name, Email address
|
||||
stefanberger, Stefan Berger, stefanb@linux.ibm.com
|
||||
lumjjb, Brandon Lum, lumjjb@gmail.com
|
||||
67
vendor/github.com/containerd/imgcrypt/Makefile
generated
vendored
67
vendor/github.com/containerd/imgcrypt/Makefile
generated
vendored
@@ -1,67 +0,0 @@
|
||||
# Copyright The containerd Authors.
|
||||
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
|
||||
# Base path used to install.
|
||||
DESTDIR ?= /usr/local
|
||||
|
||||
VERSION=$(shell git describe --match 'v[0-9]*' --dirty='.m' --always)
|
||||
|
||||
CTR_LDFLAGS=-ldflags '-X github.com/containerd/containerd/version.Version=$(VERSION)'
|
||||
COMMANDS=ctd-decoder ctr-enc
|
||||
RELEASE_COMMANDS=ctd-decoder
|
||||
|
||||
BINARIES=$(addprefix bin/,$(COMMANDS))
|
||||
RELEASE_BINARIES=$(addprefix bin/,$(RELEASE_COMMANDS))
|
||||
|
||||
.PHONY: check build ctd-decoder
|
||||
|
||||
all: build
|
||||
|
||||
build: $(BINARIES)
|
||||
|
||||
FORCE:
|
||||
|
||||
bin/ctd-decoder: cmd/ctd-decoder FORCE
|
||||
go build -o $@ -v ./cmd/ctd-decoder/
|
||||
|
||||
bin/ctr-enc: cmd/ctr FORCE
|
||||
go build -o $@ ${CTR_LDFLAGS} -v ./cmd/ctr/
|
||||
|
||||
check:
|
||||
@echo "$@"
|
||||
@golangci-lint run
|
||||
@script/check_format.sh
|
||||
|
||||
install:
|
||||
@echo "$@"
|
||||
@mkdir -p $(DESTDIR)/bin
|
||||
@install $(BINARIES) $(DESTDIR)/bin
|
||||
|
||||
containerd-release:
|
||||
@echo "$@"
|
||||
@mkdir -p $(DESTDIR)/bin
|
||||
@install $(RELEASE_BINARIES) $(DESTDIR)/bin
|
||||
|
||||
uninstall:
|
||||
@echo "$@"
|
||||
@rm -f $(addprefix $(DESTDIR)/bin/,$(notdir $(BINARIES)))
|
||||
|
||||
clean:
|
||||
@echo "$@"
|
||||
@rm -f $(BINARIES)
|
||||
|
||||
test:
|
||||
@echo "$@"
|
||||
@go test ./...
|
||||
107
vendor/github.com/containerd/imgcrypt/README.md
generated
vendored
107
vendor/github.com/containerd/imgcrypt/README.md
generated
vendored
@@ -1,107 +0,0 @@
|
||||
# imgcrypt image encryption library and command line tool
|
||||
|
||||
Project `imgcrypt` is a non-core subproject of containerd.
|
||||
|
||||
The `imgcrypt` library provides API exensions for containerd to support encrypted container images and implements
|
||||
the `ctd-decoder` command line tool for use by containerd to decrypt encrypted container images. An extended version
|
||||
of containerd's `ctr` tool (`ctr-enc`) with support for encrypting and decrypting container images is also provided.
|
||||
|
||||
`imgcrypt` relies on the [`ocicrypt`](https://github.com/containers/ocicrypt) library for crypto functions on image layers.
|
||||
|
||||
# Usage
|
||||
|
||||
`imgcrypt` requires containerd 1.3 or later. Containerd 1.4 or later is required when used with Kubernetes.
|
||||
For configuration instructions for kubernetes, please consult the [CRI decryption document](https://github.com/containerd/containerd/blob/main/docs/cri/decryption.md).
|
||||
|
||||
Build and install `imgcrypt`:
|
||||
|
||||
```
|
||||
# make
|
||||
# sudo make install
|
||||
```
|
||||
|
||||
Start containerd with a configuration file that looks as follows. To avoid interference with a containerd from a Docker
|
||||
installation we use /tmp for directories. Also, we build containerd 1.3 from the source but do not install it.
|
||||
|
||||
```
|
||||
# cat config.toml
|
||||
disable_plugins = ["cri"]
|
||||
root = "/tmp/var/lib/containerd"
|
||||
state = "/tmp/run/containerd"
|
||||
[grpc]
|
||||
address = "/tmp/run/containerd/containerd.sock"
|
||||
uid = 0
|
||||
gid = 0
|
||||
[stream_processors]
|
||||
[stream_processors."io.containerd.ocicrypt.decoder.v1.tar.gzip"]
|
||||
accepts = ["application/vnd.oci.image.layer.v1.tar+gzip+encrypted"]
|
||||
returns = "application/vnd.oci.image.layer.v1.tar+gzip"
|
||||
path = "/usr/local/bin/ctd-decoder"
|
||||
[stream_processors."io.containerd.ocicrypt.decoder.v1.tar.zstd"]
|
||||
accepts = ["application/vnd.oci.image.layer.v1.tar+zstd+encrypted"]
|
||||
returns = "application/vnd.oci.image.layer.v1.tar+zstd"
|
||||
path = "/usr/local/bin/ctd-decoder"
|
||||
[stream_processors."io.containerd.ocicrypt.decoder.v1.tar"]
|
||||
accepts = ["application/vnd.oci.image.layer.v1.tar+encrypted"]
|
||||
returns = "application/vnd.oci.image.layer.v1.tar"
|
||||
path = "/usr/local/bin/ctd-decoder"
|
||||
|
||||
# sudo ~/src/github.com/containerd/containerd/bin/containerd -c config.toml
|
||||
```
|
||||
|
||||
Create an RSA key pair using the openssl command line tool and encrypted an image:
|
||||
|
||||
```
|
||||
# openssl genrsa -out mykey.pem
|
||||
Generating RSA private key, 2048 bit long modulus (2 primes)
|
||||
...............................................+++++
|
||||
............................+++++
|
||||
e is 65537 (0x010001)
|
||||
# openssl rsa -in mykey.pem -pubout -out mypubkey.pem
|
||||
writing RSA key
|
||||
# sudo chmod 0666 /tmp/run/containerd/containerd.sock
|
||||
# CTR="/usr/local/bin/ctr-enc -a /tmp/run/containerd/containerd.sock"
|
||||
# $CTR images pull --all-platforms docker.io/library/bash:latest
|
||||
[...]
|
||||
# $CTR images layerinfo --platform linux/amd64 docker.io/library/bash:latest
|
||||
# DIGEST PLATFORM SIZE ENCRYPTION RECIPIENTS
|
||||
0 sha256:9d48c3bd43c520dc2784e868a780e976b207cbf493eaff8c6596eb871cbd9609 linux/amd64 2789669
|
||||
1 sha256:7dd01fd971d4ec7058c5636a505327b24e5fc8bd7f62816a9d518472bd9b15c0 linux/amd64 3174665
|
||||
2 sha256:691cfbca522787898c8b37f063dd20e5524e7d103e1a3b298bd2e2b8da54faf5 linux/amd64 340
|
||||
# $CTR images encrypt --recipient jwe:mypubkey.pem --platform linux/amd64 docker.io/library/bash:latest bash.enc:latest
|
||||
Encrypting docker.io/library/bash:latest to bash.enc:latest
|
||||
$ $CTR images layerinfo --platform linux/amd64 bash.enc:latest
|
||||
# DIGEST PLATFORM SIZE ENCRYPTION RECIPIENTS
|
||||
0 sha256:360be141b01f69b25427a9085b36ba8ad7d7a335449013fa6b32c1ecb894ab5b linux/amd64 2789669 jwe [jwe]
|
||||
1 sha256:ac601e66cdd275ee0e10afead03a2722e153a60982122d2d369880ea54fe82f8 linux/amd64 3174665 jwe [jwe]
|
||||
2 sha256:41e47064fd00424e328915ad2f7f716bd86ea2d0d8315edaf33ecaa6a2464530 linux/amd64 340 jwe [jwe]
|
||||
```
|
||||
|
||||
Start a local image registry so we can push the encrypted image to it. A recent versions of the registry is required
|
||||
to accept encrypted container images.
|
||||
```
|
||||
# docker pull registry:latest
|
||||
# docker run -d -p 5000:5000 --restart=always --name registry registry
|
||||
```
|
||||
|
||||
Push the encrypted image to the local registry, pull it using `ctr-enc`, and then run the image.
|
||||
```
|
||||
# $CTR images tag bash.enc:latest localhost:5000/bash.enc:latest
|
||||
# $CTR images push localhost:5000/bash.enc:latest
|
||||
# $CTR images rm localhost:5000/bash.enc:latest bash.enc:latest
|
||||
# $CTR images pull localhost:5000/bash.enc:latest
|
||||
# sudo $CTR run --rm localhost:5000/bash.enc:latest test echo 'Hello World!'
|
||||
ctr: you are not authorized to use this image: missing private key needed for decryption
|
||||
# sudo $CTR run --rm --key mykey.pem localhost:5000/bash.enc:latest test echo 'Hello World!'
|
||||
Hello World!
|
||||
```
|
||||
|
||||
## Project details
|
||||
|
||||
**imgcrypt** is a non-core containerd sub-project, licensed under the [Apache 2.0 license](./LICENSE).
|
||||
As a containerd sub-project, you will find the:
|
||||
* [Project governance](https://github.com/containerd/project/blob/main/GOVERNANCE.md),
|
||||
* [Maintainers](MAINTAINERS),
|
||||
* and [Contributing guidelines](https://github.com/containerd/project/blob/main/CONTRIBUTING.md)
|
||||
|
||||
information in our [`containerd/project`](https://github.com/containerd/project) repository.
|
||||
42
vendor/github.com/containerd/imgcrypt/images/encryption/any.go
generated
vendored
42
vendor/github.com/containerd/imgcrypt/images/encryption/any.go
generated
vendored
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package encryption
|
||||
|
||||
import "github.com/gogo/protobuf/types"
|
||||
|
||||
// pbAny takes proto-generated Any type.
|
||||
// https://developers.google.com/protocol-buffers/docs/proto3#any
|
||||
type pbAny interface {
|
||||
GetTypeUrl() string
|
||||
GetValue() []byte
|
||||
}
|
||||
|
||||
func fromAny(from pbAny) *types.Any {
|
||||
if from == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
pbany, ok := from.(*types.Any)
|
||||
if ok {
|
||||
return pbany
|
||||
}
|
||||
|
||||
return &types.Any{
|
||||
TypeUrl: from.GetTypeUrl(),
|
||||
Value: from.GetValue(),
|
||||
}
|
||||
}
|
||||
80
vendor/github.com/containerd/imgcrypt/images/encryption/client.go
generated
vendored
80
vendor/github.com/containerd/imgcrypt/images/encryption/client.go
generated
vendored
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package encryption
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/containerd/containerd"
|
||||
"github.com/containerd/containerd/containers"
|
||||
"github.com/containerd/containerd/diff"
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
"github.com/containerd/imgcrypt"
|
||||
"github.com/containerd/typeurl"
|
||||
|
||||
encconfig "github.com/containers/ocicrypt/config"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// WithDecryptedUnpack allows to pass parameters the 'layertool' needs to the applier
|
||||
func WithDecryptedUnpack(data *imgcrypt.Payload) diff.ApplyOpt {
|
||||
return func(_ context.Context, desc ocispec.Descriptor, c *diff.ApplyConfig) error {
|
||||
data.Descriptor = desc
|
||||
any, err := typeurl.MarshalAny(data)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal payload: %w", err)
|
||||
}
|
||||
|
||||
for _, id := range imgcrypt.PayloadToolIDs {
|
||||
setProcessorPayload(c, id, any)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithUnpackConfigApplyOpts allows to pass an ApplyOpt
|
||||
func WithUnpackConfigApplyOpts(opt diff.ApplyOpt) containerd.UnpackOpt {
|
||||
return func(_ context.Context, uc *containerd.UnpackConfig) error {
|
||||
uc.ApplyOpts = append(uc.ApplyOpts, opt)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithUnpackOpts is used to add unpack options to the unpacker.
|
||||
func WithUnpackOpts(opts []containerd.UnpackOpt) containerd.RemoteOpt {
|
||||
return func(_ *containerd.Client, c *containerd.RemoteContext) error {
|
||||
c.UnpackOpts = append(c.UnpackOpts, opts...)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithAuthorizationCheck checks the authorization of keys used for encrypted containers
|
||||
// be checked upon creation of a container
|
||||
func WithAuthorizationCheck(dc *encconfig.DecryptConfig) containerd.NewContainerOpts {
|
||||
return func(ctx context.Context, client *containerd.Client, c *containers.Container) error {
|
||||
image, err := client.ImageService().Get(ctx, c.Image)
|
||||
if errdefs.IsNotFound(err) {
|
||||
// allow creation of container without a existing image
|
||||
return nil
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return CheckAuthorization(ctx, client.ContentStore(), image.Target, dc)
|
||||
}
|
||||
}
|
||||
512
vendor/github.com/containerd/imgcrypt/images/encryption/encryption.go
generated
vendored
512
vendor/github.com/containerd/imgcrypt/images/encryption/encryption.go
generated
vendored
@@ -1,512 +0,0 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package encryption
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/rand"
|
||||
|
||||
"github.com/containerd/containerd/content"
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
"github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/images/converter"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
|
||||
"github.com/containers/ocicrypt"
|
||||
encconfig "github.com/containers/ocicrypt/config"
|
||||
encocispec "github.com/containers/ocicrypt/spec"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/opencontainers/image-spec/specs-go"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
type cryptoOp int
|
||||
|
||||
const (
|
||||
cryptoOpEncrypt cryptoOp = iota
|
||||
cryptoOpDecrypt = iota
|
||||
cryptoOpUnwrapOnly = iota
|
||||
)
|
||||
|
||||
// LayerFilter allows to select Layers by certain criteria
|
||||
type LayerFilter func(desc ocispec.Descriptor) bool
|
||||
|
||||
// isLocalPlatform determines whether the given platform matches the local one
|
||||
func isLocalPlatform(platform *ocispec.Platform) bool {
|
||||
matcher := platforms.NewMatcher(*platform)
|
||||
|
||||
return matcher.Match(platforms.DefaultSpec())
|
||||
}
|
||||
|
||||
// IsEncryptedDiff returns true if mediaType is a known encrypted media type.
|
||||
func IsEncryptedDiff(ctx context.Context, mediaType string) bool {
|
||||
switch mediaType {
|
||||
case encocispec.MediaTypeLayerZstdEnc, encocispec.MediaTypeLayerGzipEnc, encocispec.MediaTypeLayerEnc:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// HasEncryptedLayer returns true if any LayerInfo indicates that the layer is encrypted
|
||||
func HasEncryptedLayer(ctx context.Context, layerInfos []ocispec.Descriptor) bool {
|
||||
for i := 0; i < len(layerInfos); i++ {
|
||||
if IsEncryptedDiff(ctx, layerInfos[i].MediaType) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// encryptLayer encrypts the layer using the CryptoConfig and creates a new OCI Descriptor.
|
||||
// A call to this function may also only manipulate the wrapped keys list.
|
||||
// The caller is expected to store the returned encrypted data and OCI Descriptor
|
||||
func encryptLayer(cc *encconfig.CryptoConfig, dataReader content.ReaderAt, desc ocispec.Descriptor) (ocispec.Descriptor, io.Reader, ocicrypt.EncryptLayerFinalizer, error) {
|
||||
var (
|
||||
size int64
|
||||
d digest.Digest
|
||||
err error
|
||||
)
|
||||
|
||||
encLayerReader, encLayerFinalizer, err := ocicrypt.EncryptLayer(cc.EncryptConfig, ocicrypt.ReaderFromReaderAt(dataReader), desc)
|
||||
if err != nil {
|
||||
return ocispec.Descriptor{}, nil, nil, err
|
||||
}
|
||||
|
||||
// were data touched ?
|
||||
if encLayerReader != nil {
|
||||
size = 0
|
||||
d = ""
|
||||
} else {
|
||||
size = desc.Size
|
||||
d = desc.Digest
|
||||
}
|
||||
|
||||
newDesc := ocispec.Descriptor{
|
||||
Digest: d,
|
||||
Size: size,
|
||||
Platform: desc.Platform,
|
||||
}
|
||||
|
||||
switch desc.MediaType {
|
||||
case images.MediaTypeDockerSchema2LayerGzip:
|
||||
newDesc.MediaType = encocispec.MediaTypeLayerGzipEnc
|
||||
case images.MediaTypeDockerSchema2Layer:
|
||||
newDesc.MediaType = encocispec.MediaTypeLayerEnc
|
||||
case encocispec.MediaTypeLayerGzipEnc:
|
||||
newDesc.MediaType = encocispec.MediaTypeLayerGzipEnc
|
||||
case encocispec.MediaTypeLayerZstdEnc:
|
||||
newDesc.MediaType = encocispec.MediaTypeLayerZstdEnc
|
||||
case encocispec.MediaTypeLayerEnc:
|
||||
newDesc.MediaType = encocispec.MediaTypeLayerEnc
|
||||
|
||||
// TODO: Mediatypes to be added in ocispec
|
||||
case ocispec.MediaTypeImageLayerGzip:
|
||||
newDesc.MediaType = encocispec.MediaTypeLayerGzipEnc
|
||||
case ocispec.MediaTypeImageLayerZstd:
|
||||
newDesc.MediaType = encocispec.MediaTypeLayerZstdEnc
|
||||
case ocispec.MediaTypeImageLayer:
|
||||
newDesc.MediaType = encocispec.MediaTypeLayerEnc
|
||||
|
||||
default:
|
||||
return ocispec.Descriptor{}, nil, nil, fmt.Errorf("unsupporter layer MediaType: %s", desc.MediaType)
|
||||
}
|
||||
|
||||
return newDesc, encLayerReader, encLayerFinalizer, nil
|
||||
}
|
||||
|
||||
// DecryptLayer decrypts the layer using the DecryptConfig and creates a new OCI Descriptor.
|
||||
// The caller is expected to store the returned plain data and OCI Descriptor
|
||||
func DecryptLayer(dc *encconfig.DecryptConfig, dataReader io.Reader, desc ocispec.Descriptor, unwrapOnly bool) (ocispec.Descriptor, io.Reader, digest.Digest, error) {
|
||||
resultReader, layerDigest, err := ocicrypt.DecryptLayer(dc, dataReader, desc, unwrapOnly)
|
||||
if err != nil || unwrapOnly {
|
||||
return ocispec.Descriptor{}, nil, "", err
|
||||
}
|
||||
|
||||
newDesc := ocispec.Descriptor{
|
||||
Size: 0,
|
||||
Platform: desc.Platform,
|
||||
}
|
||||
|
||||
switch desc.MediaType {
|
||||
case encocispec.MediaTypeLayerGzipEnc:
|
||||
newDesc.MediaType = images.MediaTypeDockerSchema2LayerGzip
|
||||
case encocispec.MediaTypeLayerZstdEnc:
|
||||
newDesc.MediaType = ocispec.MediaTypeImageLayerZstd
|
||||
case encocispec.MediaTypeLayerEnc:
|
||||
newDesc.MediaType = images.MediaTypeDockerSchema2Layer
|
||||
default:
|
||||
return ocispec.Descriptor{}, nil, "", fmt.Errorf("unsupporter layer MediaType: %s", desc.MediaType)
|
||||
}
|
||||
return newDesc, resultReader, layerDigest, nil
|
||||
}
|
||||
|
||||
// decryptLayer decrypts the layer using the CryptoConfig and creates a new OCI Descriptor.
|
||||
// The caller is expected to store the returned plain data and OCI Descriptor
|
||||
func decryptLayer(cc *encconfig.CryptoConfig, dataReader content.ReaderAt, desc ocispec.Descriptor, unwrapOnly bool) (ocispec.Descriptor, io.Reader, error) {
|
||||
resultReader, d, err := ocicrypt.DecryptLayer(cc.DecryptConfig, ocicrypt.ReaderFromReaderAt(dataReader), desc, unwrapOnly)
|
||||
if err != nil || unwrapOnly {
|
||||
return ocispec.Descriptor{}, nil, err
|
||||
}
|
||||
|
||||
newDesc := ocispec.Descriptor{
|
||||
Digest: d,
|
||||
Size: 0,
|
||||
Platform: desc.Platform,
|
||||
}
|
||||
|
||||
switch desc.MediaType {
|
||||
case encocispec.MediaTypeLayerGzipEnc:
|
||||
newDesc.MediaType = images.MediaTypeDockerSchema2LayerGzip
|
||||
case encocispec.MediaTypeLayerZstdEnc:
|
||||
newDesc.MediaType = ocispec.MediaTypeImageLayerZstd
|
||||
case encocispec.MediaTypeLayerEnc:
|
||||
newDesc.MediaType = images.MediaTypeDockerSchema2Layer
|
||||
default:
|
||||
return ocispec.Descriptor{}, nil, fmt.Errorf("unsupporter layer MediaType: %s", desc.MediaType)
|
||||
}
|
||||
return newDesc, resultReader, nil
|
||||
}
|
||||
|
||||
// cryptLayer handles the changes due to encryption or decryption of a layer
|
||||
func cryptLayer(ctx context.Context, cs content.Store, desc ocispec.Descriptor, cc *encconfig.CryptoConfig, cryptoOp cryptoOp) (ocispec.Descriptor, error) {
|
||||
var (
|
||||
resultReader io.Reader
|
||||
newDesc ocispec.Descriptor
|
||||
encLayerFinalizer ocicrypt.EncryptLayerFinalizer
|
||||
)
|
||||
|
||||
dataReader, err := cs.ReaderAt(ctx, desc)
|
||||
if err != nil {
|
||||
return ocispec.Descriptor{}, err
|
||||
}
|
||||
defer dataReader.Close()
|
||||
|
||||
if cryptoOp == cryptoOpEncrypt {
|
||||
newDesc, resultReader, encLayerFinalizer, err = encryptLayer(cc, dataReader, desc)
|
||||
} else {
|
||||
newDesc, resultReader, err = decryptLayer(cc, dataReader, desc, cryptoOp == cryptoOpUnwrapOnly)
|
||||
}
|
||||
if err != nil || cryptoOp == cryptoOpUnwrapOnly {
|
||||
return ocispec.Descriptor{}, err
|
||||
}
|
||||
|
||||
newDesc.Annotations = ocicrypt.FilterOutAnnotations(desc.Annotations)
|
||||
|
||||
// some operations, such as changing recipients, may not touch the layer at all
|
||||
if resultReader != nil {
|
||||
var ref string
|
||||
// If we have the digest, write blob with checks
|
||||
haveDigest := newDesc.Digest.String() != ""
|
||||
if haveDigest {
|
||||
ref = fmt.Sprintf("layer-%s", newDesc.Digest.String())
|
||||
} else {
|
||||
ref = fmt.Sprintf("blob-%d-%d", rand.Int(), rand.Int())
|
||||
}
|
||||
|
||||
if haveDigest {
|
||||
if err := content.WriteBlob(ctx, cs, ref, resultReader, newDesc); err != nil {
|
||||
return ocispec.Descriptor{}, fmt.Errorf("failed to write config: %w", err)
|
||||
}
|
||||
} else {
|
||||
newDesc.Digest, newDesc.Size, err = ingestReader(ctx, cs, ref, resultReader)
|
||||
if err != nil {
|
||||
return ocispec.Descriptor{}, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// After performing encryption, call finalizer to get annotations
|
||||
if encLayerFinalizer != nil {
|
||||
annotations, err := encLayerFinalizer()
|
||||
if err != nil {
|
||||
return ocispec.Descriptor{}, fmt.Errorf("error getting annotations from encLayer finalizer: %w", err)
|
||||
}
|
||||
for k, v := range annotations {
|
||||
newDesc.Annotations[k] = v
|
||||
}
|
||||
}
|
||||
return newDesc, err
|
||||
}
|
||||
|
||||
func ingestReader(ctx context.Context, cs content.Ingester, ref string, r io.Reader) (digest.Digest, int64, error) {
|
||||
cw, err := content.OpenWriter(ctx, cs, content.WithRef(ref))
|
||||
if err != nil {
|
||||
return "", 0, fmt.Errorf("failed to open writer: %w", err)
|
||||
}
|
||||
defer cw.Close()
|
||||
|
||||
if _, err := content.CopyReader(cw, r); err != nil {
|
||||
return "", 0, fmt.Errorf("copy failed: %w", err)
|
||||
}
|
||||
|
||||
st, err := cw.Status()
|
||||
if err != nil {
|
||||
return "", 0, fmt.Errorf("failed to get state: %w", err)
|
||||
}
|
||||
|
||||
if err := cw.Commit(ctx, st.Offset, ""); err != nil {
|
||||
if !errdefs.IsAlreadyExists(err) {
|
||||
return "", 0, fmt.Errorf("failed commit on ref %q: %w", ref, err)
|
||||
}
|
||||
}
|
||||
|
||||
return cw.Digest(), st.Offset, nil
|
||||
}
|
||||
|
||||
// Encrypt or decrypt all the Children of a given descriptor
|
||||
func cryptChildren(ctx context.Context, cs content.Store, desc ocispec.Descriptor, cc *encconfig.CryptoConfig, lf LayerFilter, cryptoOp cryptoOp, thisPlatform *ocispec.Platform) (ocispec.Descriptor, bool, error) {
|
||||
children, err := images.Children(ctx, cs, desc)
|
||||
if err != nil {
|
||||
if errdefs.IsNotFound(err) {
|
||||
return desc, false, nil
|
||||
}
|
||||
return ocispec.Descriptor{}, false, err
|
||||
}
|
||||
|
||||
var newLayers []ocispec.Descriptor
|
||||
var config ocispec.Descriptor
|
||||
modified := false
|
||||
|
||||
for _, child := range children {
|
||||
// we only encrypt child layers and have to update their parents if encryption happened
|
||||
switch child.MediaType {
|
||||
case images.MediaTypeDockerSchema2Config, ocispec.MediaTypeImageConfig:
|
||||
config = child
|
||||
case images.MediaTypeDockerSchema2LayerGzip, images.MediaTypeDockerSchema2Layer,
|
||||
ocispec.MediaTypeImageLayerGzip, ocispec.MediaTypeImageLayer,
|
||||
ocispec.MediaTypeImageLayerZstd:
|
||||
if cryptoOp == cryptoOpEncrypt && lf(child) {
|
||||
nl, err := cryptLayer(ctx, cs, child, cc, cryptoOp)
|
||||
if err != nil {
|
||||
return ocispec.Descriptor{}, false, err
|
||||
}
|
||||
modified = true
|
||||
newLayers = append(newLayers, nl)
|
||||
} else {
|
||||
newLayers = append(newLayers, child)
|
||||
}
|
||||
case encocispec.MediaTypeLayerGzipEnc, encocispec.MediaTypeLayerZstdEnc, encocispec.MediaTypeLayerEnc:
|
||||
// this one can be decrypted but also its recipients list changed
|
||||
if lf(child) {
|
||||
nl, err := cryptLayer(ctx, cs, child, cc, cryptoOp)
|
||||
if err != nil || cryptoOp == cryptoOpUnwrapOnly {
|
||||
return ocispec.Descriptor{}, false, err
|
||||
}
|
||||
modified = true
|
||||
newLayers = append(newLayers, nl)
|
||||
} else {
|
||||
newLayers = append(newLayers, child)
|
||||
}
|
||||
case images.MediaTypeDockerSchema2LayerForeign, images.MediaTypeDockerSchema2LayerForeignGzip:
|
||||
// never encrypt/decrypt
|
||||
newLayers = append(newLayers, child)
|
||||
default:
|
||||
return ocispec.Descriptor{}, false, fmt.Errorf("bad/unhandled MediaType %s in encryptChildren", child.MediaType)
|
||||
}
|
||||
}
|
||||
|
||||
if modified && len(newLayers) > 0 {
|
||||
newManifest := ocispec.Manifest{
|
||||
Versioned: specs.Versioned{
|
||||
SchemaVersion: 2,
|
||||
},
|
||||
Config: config,
|
||||
Layers: newLayers,
|
||||
}
|
||||
|
||||
mb, err := json.MarshalIndent(newManifest, "", " ")
|
||||
if err != nil {
|
||||
return ocispec.Descriptor{}, false, fmt.Errorf("failed to marshal image: %w", err)
|
||||
}
|
||||
|
||||
newDesc := ocispec.Descriptor{
|
||||
MediaType: ocispec.MediaTypeImageManifest,
|
||||
Size: int64(len(mb)),
|
||||
Digest: digest.Canonical.FromBytes(mb),
|
||||
Platform: desc.Platform,
|
||||
}
|
||||
|
||||
labels := map[string]string{}
|
||||
labels["containerd.io/gc.ref.content.0"] = newManifest.Config.Digest.String()
|
||||
for i, ch := range newManifest.Layers {
|
||||
labels[fmt.Sprintf("containerd.io/gc.ref.content.%d", i+1)] = ch.Digest.String()
|
||||
}
|
||||
|
||||
ref := fmt.Sprintf("manifest-%s", newDesc.Digest.String())
|
||||
|
||||
if err := content.WriteBlob(ctx, cs, ref, bytes.NewReader(mb), newDesc, content.WithLabels(labels)); err != nil {
|
||||
return ocispec.Descriptor{}, false, fmt.Errorf("failed to write config: %w", err)
|
||||
}
|
||||
return newDesc, true, nil
|
||||
}
|
||||
|
||||
return desc, modified, nil
|
||||
}
|
||||
|
||||
// cryptManifest encrypts or decrypts the children of a top level manifest
|
||||
func cryptManifest(ctx context.Context, cs content.Store, desc ocispec.Descriptor, cc *encconfig.CryptoConfig, lf LayerFilter, cryptoOp cryptoOp) (ocispec.Descriptor, bool, error) {
|
||||
p, err := content.ReadBlob(ctx, cs, desc)
|
||||
if err != nil {
|
||||
return ocispec.Descriptor{}, false, err
|
||||
}
|
||||
var manifest ocispec.Manifest
|
||||
if err := json.Unmarshal(p, &manifest); err != nil {
|
||||
return ocispec.Descriptor{}, false, err
|
||||
}
|
||||
platform := platforms.DefaultSpec()
|
||||
newDesc, modified, err := cryptChildren(ctx, cs, desc, cc, lf, cryptoOp, &platform)
|
||||
if err != nil || cryptoOp == cryptoOpUnwrapOnly {
|
||||
return ocispec.Descriptor{}, false, err
|
||||
}
|
||||
return newDesc, modified, nil
|
||||
}
|
||||
|
||||
// cryptManifestList encrypts or decrypts the children of a top level manifest list
|
||||
func cryptManifestList(ctx context.Context, cs content.Store, desc ocispec.Descriptor, cc *encconfig.CryptoConfig, lf LayerFilter, cryptoOp cryptoOp) (ocispec.Descriptor, bool, error) {
|
||||
// read the index; if any layer is encrypted and any manifests change we will need to rewrite it
|
||||
b, err := content.ReadBlob(ctx, cs, desc)
|
||||
if err != nil {
|
||||
return ocispec.Descriptor{}, false, err
|
||||
}
|
||||
|
||||
var index ocispec.Index
|
||||
if err := json.Unmarshal(b, &index); err != nil {
|
||||
return ocispec.Descriptor{}, false, err
|
||||
}
|
||||
|
||||
var newManifests []ocispec.Descriptor
|
||||
modified := false
|
||||
for _, manifest := range index.Manifests {
|
||||
if cryptoOp == cryptoOpUnwrapOnly && !isLocalPlatform(manifest.Platform) {
|
||||
continue
|
||||
}
|
||||
newManifest, m, err := cryptChildren(ctx, cs, manifest, cc, lf, cryptoOp, manifest.Platform)
|
||||
if err != nil || cryptoOp == cryptoOpUnwrapOnly {
|
||||
return ocispec.Descriptor{}, false, err
|
||||
}
|
||||
if m {
|
||||
modified = true
|
||||
}
|
||||
newManifests = append(newManifests, newManifest)
|
||||
}
|
||||
if cryptoOp == cryptoOpUnwrapOnly {
|
||||
return ocispec.Descriptor{}, false, fmt.Errorf("No manifest found for local platform")
|
||||
}
|
||||
|
||||
if modified {
|
||||
// we need to update the index
|
||||
newIndex := ocispec.Index{
|
||||
Versioned: index.Versioned,
|
||||
Manifests: newManifests,
|
||||
}
|
||||
|
||||
mb, err := json.MarshalIndent(newIndex, "", " ")
|
||||
if err != nil {
|
||||
return ocispec.Descriptor{}, false, fmt.Errorf("failed to marshal index: %w", err)
|
||||
}
|
||||
|
||||
newDesc := ocispec.Descriptor{
|
||||
MediaType: ocispec.MediaTypeImageIndex,
|
||||
Size: int64(len(mb)),
|
||||
Digest: digest.Canonical.FromBytes(mb),
|
||||
}
|
||||
|
||||
labels := map[string]string{}
|
||||
for i, m := range newIndex.Manifests {
|
||||
labels[fmt.Sprintf("containerd.io/gc.ref.content.%d", i)] = m.Digest.String()
|
||||
}
|
||||
|
||||
ref := fmt.Sprintf("index-%s", newDesc.Digest.String())
|
||||
|
||||
if err = content.WriteBlob(ctx, cs, ref, bytes.NewReader(mb), newDesc, content.WithLabels(labels)); err != nil {
|
||||
return ocispec.Descriptor{}, false, fmt.Errorf("failed to write index: %w", err)
|
||||
}
|
||||
return newDesc, true, nil
|
||||
}
|
||||
|
||||
return desc, false, nil
|
||||
}
|
||||
|
||||
// cryptImage is the dispatcher to encrypt/decrypt an image; it accepts either an OCI descriptor
|
||||
// representing a manifest list or a single manifest
|
||||
func cryptImage(ctx context.Context, cs content.Store, desc ocispec.Descriptor, cc *encconfig.CryptoConfig, lf LayerFilter, cryptoOp cryptoOp) (ocispec.Descriptor, bool, error) {
|
||||
if cc == nil {
|
||||
return ocispec.Descriptor{}, false, errors.New("invalid argument: CryptoConfig must not be nil")
|
||||
}
|
||||
switch desc.MediaType {
|
||||
case ocispec.MediaTypeImageIndex, images.MediaTypeDockerSchema2ManifestList:
|
||||
return cryptManifestList(ctx, cs, desc, cc, lf, cryptoOp)
|
||||
case ocispec.MediaTypeImageManifest, images.MediaTypeDockerSchema2Manifest:
|
||||
return cryptManifest(ctx, cs, desc, cc, lf, cryptoOp)
|
||||
default:
|
||||
return ocispec.Descriptor{}, false, fmt.Errorf("unhandled media type: %s", desc.MediaType)
|
||||
}
|
||||
}
|
||||
|
||||
// EncryptImage encrypts an image; it accepts either an OCI descriptor representing a manifest list or a single manifest
|
||||
func EncryptImage(ctx context.Context, cs content.Store, desc ocispec.Descriptor, cc *encconfig.CryptoConfig, lf LayerFilter) (ocispec.Descriptor, bool, error) {
|
||||
return cryptImage(ctx, cs, desc, cc, lf, cryptoOpEncrypt)
|
||||
}
|
||||
|
||||
// DecryptImage decrypts an image; it accepts either an OCI descriptor representing a manifest list or a single manifest
|
||||
func DecryptImage(ctx context.Context, cs content.Store, desc ocispec.Descriptor, cc *encconfig.CryptoConfig, lf LayerFilter) (ocispec.Descriptor, bool, error) {
|
||||
return cryptImage(ctx, cs, desc, cc, lf, cryptoOpDecrypt)
|
||||
}
|
||||
|
||||
// GetImageEncryptConverter returns a converter function for image encryption
|
||||
func GetImageEncryptConverter(cc *encconfig.CryptoConfig, lf LayerFilter) converter.ConvertFunc {
|
||||
return func(ctx context.Context, cs content.Store, desc ocispec.Descriptor) (*ocispec.Descriptor, error) {
|
||||
newDesc, _, err := EncryptImage(ctx, cs, desc, cc, lf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &newDesc, nil
|
||||
}
|
||||
}
|
||||
|
||||
// GetImageDecryptConverter returns a converter function for image decryption
|
||||
func GetImageDecryptConverter(cc *encconfig.CryptoConfig, lf LayerFilter) converter.ConvertFunc {
|
||||
return func(ctx context.Context, cs content.Store, desc ocispec.Descriptor) (*ocispec.Descriptor, error) {
|
||||
newDesc, _, err := DecryptImage(ctx, cs, desc, cc, lf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &newDesc, nil
|
||||
}
|
||||
}
|
||||
|
||||
// CheckAuthorization checks whether a user has the right keys to be allowed to access an image (every layer)
|
||||
// It takes decrypting of the layers only as far as decrypting the asymmetrically encrypted data
|
||||
// The decryption is only done for the current platform
|
||||
func CheckAuthorization(ctx context.Context, cs content.Store, desc ocispec.Descriptor, dc *encconfig.DecryptConfig) error {
|
||||
cc := encconfig.InitDecryption(dc.Parameters)
|
||||
|
||||
lf := func(desc ocispec.Descriptor) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
_, _, err := cryptImage(ctx, cs, desc, &cc, lf, cryptoOpUnwrapOnly)
|
||||
if err != nil {
|
||||
return fmt.Errorf("you are not authorized to use this image: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
53
vendor/github.com/containerd/imgcrypt/images/encryption/payload.go
generated
vendored
53
vendor/github.com/containerd/imgcrypt/images/encryption/payload.go
generated
vendored
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package encryption
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/containerd/containerd/diff"
|
||||
"github.com/gogo/protobuf/types"
|
||||
)
|
||||
|
||||
var processorPayloadsUseGogo bool
|
||||
|
||||
func init() {
|
||||
var c = &diff.ApplyConfig{}
|
||||
var pbany *types.Any
|
||||
|
||||
pp := reflect.TypeOf(c.ProcessorPayloads)
|
||||
processorPayloadsUseGogo = pp.Elem() == reflect.TypeOf(pbany)
|
||||
}
|
||||
|
||||
func clearProcessorPayloads(c *diff.ApplyConfig) {
|
||||
var empty = reflect.MakeMap(reflect.TypeOf(c.ProcessorPayloads))
|
||||
reflect.ValueOf(&c.ProcessorPayloads).Elem().Set(empty)
|
||||
}
|
||||
|
||||
func setProcessorPayload(c *diff.ApplyConfig, id string, value pbAny) {
|
||||
if c.ProcessorPayloads == nil {
|
||||
clearProcessorPayloads(c)
|
||||
}
|
||||
|
||||
var v reflect.Value
|
||||
if processorPayloadsUseGogo {
|
||||
v = reflect.ValueOf(fromAny(value))
|
||||
} else {
|
||||
v = reflect.ValueOf(value)
|
||||
}
|
||||
reflect.ValueOf(c.ProcessorPayloads).SetMapIndex(reflect.ValueOf(id), v)
|
||||
}
|
||||
44
vendor/github.com/containerd/imgcrypt/payload.go
generated
vendored
44
vendor/github.com/containerd/imgcrypt/payload.go
generated
vendored
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package imgcrypt
|
||||
|
||||
import (
|
||||
"github.com/containerd/typeurl"
|
||||
|
||||
encconfig "github.com/containers/ocicrypt/config"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
const (
|
||||
PayloadURI = "io.containerd.ocicrypt.v1.Payload"
|
||||
)
|
||||
|
||||
var PayloadToolIDs = []string{
|
||||
"io.containerd.ocicrypt.decoder.v1.tar",
|
||||
"io.containerd.ocicrypt.decoder.v1.tar.gzip",
|
||||
}
|
||||
|
||||
func init() {
|
||||
typeurl.Register(&Payload{}, PayloadURI)
|
||||
}
|
||||
|
||||
// Payload holds data that the external layer decryption tool
|
||||
// needs for decrypting a layer
|
||||
type Payload struct {
|
||||
DecryptConfig encconfig.DecryptConfig
|
||||
Descriptor ocispec.Descriptor
|
||||
}
|
||||
2
vendor/github.com/containerd/typeurl/.gitignore
generated
vendored
2
vendor/github.com/containerd/typeurl/.gitignore
generated
vendored
@@ -1,2 +0,0 @@
|
||||
*.test
|
||||
coverage.txt
|
||||
191
vendor/github.com/containerd/typeurl/LICENSE
generated
vendored
191
vendor/github.com/containerd/typeurl/LICENSE
generated
vendored
@@ -1,191 +0,0 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
https://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Copyright The containerd Authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
20
vendor/github.com/containerd/typeurl/README.md
generated
vendored
20
vendor/github.com/containerd/typeurl/README.md
generated
vendored
@@ -1,20 +0,0 @@
|
||||
# typeurl
|
||||
|
||||
[](https://pkg.go.dev/github.com/containerd/typeurl)
|
||||
[](https://github.com/containerd/typeurl/actions?query=workflow%3ACI)
|
||||
[](https://codecov.io/gh/containerd/typeurl)
|
||||
[](https://goreportcard.com/report/github.com/containerd/typeurl)
|
||||
|
||||
A Go package for managing the registration, marshaling, and unmarshaling of encoded types.
|
||||
|
||||
This package helps when types are sent over a GRPC API and marshaled as a [protobuf.Any](https://github.com/gogo/protobuf/blob/master/protobuf/google/protobuf/any.proto).
|
||||
|
||||
## Project details
|
||||
|
||||
**typeurl** is a containerd sub-project, licensed under the [Apache 2.0 license](./LICENSE).
|
||||
As a containerd sub-project, you will find the:
|
||||
* [Project governance](https://github.com/containerd/project/blob/master/GOVERNANCE.md),
|
||||
* [Maintainers](https://github.com/containerd/project/blob/master/MAINTAINERS),
|
||||
* and [Contributing guidelines](https://github.com/containerd/project/blob/master/CONTRIBUTING.md)
|
||||
|
||||
information in our [`containerd/project`](https://github.com/containerd/project) repository.
|
||||
83
vendor/github.com/containerd/typeurl/doc.go
generated
vendored
83
vendor/github.com/containerd/typeurl/doc.go
generated
vendored
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package typeurl
|
||||
|
||||
// Package typeurl assists with managing the registration, marshaling, and
|
||||
// unmarshaling of types encoded as protobuf.Any.
|
||||
//
|
||||
// A protobuf.Any is a proto message that can contain any arbitrary data. It
|
||||
// consists of two components, a TypeUrl and a Value, and its proto definition
|
||||
// looks like this:
|
||||
//
|
||||
// message Any {
|
||||
// string type_url = 1;
|
||||
// bytes value = 2;
|
||||
// }
|
||||
//
|
||||
// The TypeUrl is used to distinguish the contents from other proto.Any
|
||||
// messages. This typeurl library manages these URLs to enable automagic
|
||||
// marshaling and unmarshaling of the contents.
|
||||
//
|
||||
// For example, consider this go struct:
|
||||
//
|
||||
// type Foo struct {
|
||||
// Field1 string
|
||||
// Field2 string
|
||||
// }
|
||||
//
|
||||
// To use typeurl, types must first be registered. This is typically done in
|
||||
// the init function
|
||||
//
|
||||
// func init() {
|
||||
// typeurl.Register(&Foo{}, "Foo")
|
||||
// }
|
||||
//
|
||||
// This will register the type Foo with the url path "Foo". The arguments to
|
||||
// Register are variadic, and are used to construct a url path. Consider this
|
||||
// example, from the github.com/containerd/containerd/client package:
|
||||
//
|
||||
// func init() {
|
||||
// const prefix = "types.containerd.io"
|
||||
// // register TypeUrls for commonly marshaled external types
|
||||
// major := strconv.Itoa(specs.VersionMajor)
|
||||
// typeurl.Register(&specs.Spec{}, prefix, "opencontainers/runtime-spec", major, "Spec")
|
||||
// // this function has more Register calls, which are elided.
|
||||
// }
|
||||
//
|
||||
// This registers several types under a more complex url, which ends up mapping
|
||||
// to `types.containerd.io/opencontainers/runtime-spec/1/Spec` (or some other
|
||||
// value for major).
|
||||
//
|
||||
// Once a type is registered, it can be marshaled to a proto.Any message simply
|
||||
// by calling `MarshalAny`, like this:
|
||||
//
|
||||
// foo := &Foo{Field1: "value1", Field2: "value2"}
|
||||
// anyFoo, err := typeurl.MarshalAny(foo)
|
||||
//
|
||||
// MarshalAny will resolve the correct URL for the type. If the type in
|
||||
// question implements the proto.Message interface, then it will be marshaled
|
||||
// as a proto message. Otherwise, it will be marshaled as json. This means that
|
||||
// typeurl will work on any arbitrary data, whether or not it has a proto
|
||||
// definition, as long as it can be serialized to json.
|
||||
//
|
||||
// To unmarshal, the process is simply inverse:
|
||||
//
|
||||
// iface, err := typeurl.UnmarshalAny(anyFoo)
|
||||
// foo := iface.(*Foo)
|
||||
//
|
||||
// The correct type is automatically chosen from the type registry, and the
|
||||
// returned interface can be cast straight to that type.
|
||||
214
vendor/github.com/containerd/typeurl/types.go
generated
vendored
214
vendor/github.com/containerd/typeurl/types.go
generated
vendored
@@ -1,214 +0,0 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package typeurl
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"path"
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/gogo/protobuf/types"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
mu sync.RWMutex
|
||||
registry = make(map[reflect.Type]string)
|
||||
)
|
||||
|
||||
// Definitions of common error types used throughout typeurl.
|
||||
//
|
||||
// These error types are used with errors.Wrap and errors.Wrapf to add context
|
||||
// to an error.
|
||||
//
|
||||
// To detect an error class, use errors.Is() functions to tell whether an
|
||||
// error is of this type.
|
||||
var (
|
||||
ErrNotFound = errors.New("not found")
|
||||
)
|
||||
|
||||
// Register a type with a base URL for JSON marshaling. When the MarshalAny and
|
||||
// UnmarshalAny functions are called they will treat the Any type value as JSON.
|
||||
// To use protocol buffers for handling the Any value the proto.Register
|
||||
// function should be used instead of this function.
|
||||
func Register(v interface{}, args ...string) {
|
||||
var (
|
||||
t = tryDereference(v)
|
||||
p = path.Join(args...)
|
||||
)
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
if et, ok := registry[t]; ok {
|
||||
if et != p {
|
||||
panic(errors.Errorf("type registered with alternate path %q != %q", et, p))
|
||||
}
|
||||
return
|
||||
}
|
||||
registry[t] = p
|
||||
}
|
||||
|
||||
// TypeURL returns the type url for a registered type.
|
||||
func TypeURL(v interface{}) (string, error) {
|
||||
mu.RLock()
|
||||
u, ok := registry[tryDereference(v)]
|
||||
mu.RUnlock()
|
||||
if !ok {
|
||||
// fallback to the proto registry if it is a proto message
|
||||
pb, ok := v.(proto.Message)
|
||||
if !ok {
|
||||
return "", errors.Wrapf(ErrNotFound, "type %s", reflect.TypeOf(v))
|
||||
}
|
||||
return proto.MessageName(pb), nil
|
||||
}
|
||||
return u, nil
|
||||
}
|
||||
|
||||
// Is returns true if the type of the Any is the same as v.
|
||||
func Is(any *types.Any, v interface{}) bool {
|
||||
// call to check that v is a pointer
|
||||
tryDereference(v)
|
||||
url, err := TypeURL(v)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return any.TypeUrl == url
|
||||
}
|
||||
|
||||
// MarshalAny marshals the value v into an any with the correct TypeUrl.
|
||||
// If the provided object is already a proto.Any message, then it will be
|
||||
// returned verbatim. If it is of type proto.Message, it will be marshaled as a
|
||||
// protocol buffer. Otherwise, the object will be marshaled to json.
|
||||
func MarshalAny(v interface{}) (*types.Any, error) {
|
||||
var marshal func(v interface{}) ([]byte, error)
|
||||
switch t := v.(type) {
|
||||
case *types.Any:
|
||||
// avoid reserializing the type if we have an any.
|
||||
return t, nil
|
||||
case proto.Message:
|
||||
marshal = func(v interface{}) ([]byte, error) {
|
||||
return proto.Marshal(t)
|
||||
}
|
||||
default:
|
||||
marshal = json.Marshal
|
||||
}
|
||||
|
||||
url, err := TypeURL(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err := marshal(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &types.Any{
|
||||
TypeUrl: url,
|
||||
Value: data,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UnmarshalAny unmarshals the any type into a concrete type.
|
||||
func UnmarshalAny(any *types.Any) (interface{}, error) {
|
||||
return UnmarshalByTypeURL(any.TypeUrl, any.Value)
|
||||
}
|
||||
|
||||
// UnmarshalByTypeURL unmarshals the given type and value to into a concrete type.
|
||||
func UnmarshalByTypeURL(typeURL string, value []byte) (interface{}, error) {
|
||||
return unmarshal(typeURL, value, nil)
|
||||
}
|
||||
|
||||
// UnmarshalTo unmarshals the any type into a concrete type passed in the out
|
||||
// argument. It is identical to UnmarshalAny, but lets clients provide a
|
||||
// destination type through the out argument.
|
||||
func UnmarshalTo(any *types.Any, out interface{}) error {
|
||||
return UnmarshalToByTypeURL(any.TypeUrl, any.Value, out)
|
||||
}
|
||||
|
||||
// UnmarshalTo unmarshals the given type and value into a concrete type passed
|
||||
// in the out argument. It is identical to UnmarshalByTypeURL, but lets clients
|
||||
// provide a destination type through the out argument.
|
||||
func UnmarshalToByTypeURL(typeURL string, value []byte, out interface{}) error {
|
||||
_, err := unmarshal(typeURL, value, out)
|
||||
return err
|
||||
}
|
||||
|
||||
func unmarshal(typeURL string, value []byte, v interface{}) (interface{}, error) {
|
||||
t, err := getTypeByUrl(typeURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if v == nil {
|
||||
v = reflect.New(t.t).Interface()
|
||||
} else {
|
||||
// Validate interface type provided by client
|
||||
vURL, err := TypeURL(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if typeURL != vURL {
|
||||
return nil, errors.Errorf("can't unmarshal type %q to output %q", typeURL, vURL)
|
||||
}
|
||||
}
|
||||
|
||||
if t.isProto {
|
||||
err = proto.Unmarshal(value, v.(proto.Message))
|
||||
} else {
|
||||
err = json.Unmarshal(value, v)
|
||||
}
|
||||
|
||||
return v, err
|
||||
}
|
||||
|
||||
type urlType struct {
|
||||
t reflect.Type
|
||||
isProto bool
|
||||
}
|
||||
|
||||
func getTypeByUrl(url string) (urlType, error) {
|
||||
mu.RLock()
|
||||
for t, u := range registry {
|
||||
if u == url {
|
||||
mu.RUnlock()
|
||||
return urlType{
|
||||
t: t,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
mu.RUnlock()
|
||||
// fallback to proto registry
|
||||
t := proto.MessageType(url)
|
||||
if t != nil {
|
||||
return urlType{
|
||||
// get the underlying Elem because proto returns a pointer to the type
|
||||
t: t.Elem(),
|
||||
isProto: true,
|
||||
}, nil
|
||||
}
|
||||
return urlType{}, errors.Wrapf(ErrNotFound, "type with url %s", url)
|
||||
}
|
||||
|
||||
func tryDereference(v interface{}) reflect.Type {
|
||||
t := reflect.TypeOf(v)
|
||||
if t.Kind() == reflect.Ptr {
|
||||
// require check of pointer but dereference to register
|
||||
return t.Elem()
|
||||
}
|
||||
panic("v is not a pointer to a type")
|
||||
}
|
||||
Reference in New Issue
Block a user