From abaad4d7602fa251886d4ce43206038858a26139 Mon Sep 17 00:00:00 2001 From: Ethan Lowman Date: Mon, 20 Mar 2023 18:41:24 -0400 Subject: [PATCH] feat: Backport to v1.7.12: Implement CRI image verification plugin system Signed-off-by: Ethan Lowman Signed-off-by: Maxime Visonneau Signed-off-by: Eric Mountain --- Protobuild.toml | 1 + docs/cri/config.md | 10 + pkg/cri/config/config.go | 13 + pkg/cri/server/image_pull.go | 15 + pkg/cri/server/image_verifier.go | 85 ++++++ pkg/cri/server/imageverifier/v1/doc.go | 17 ++ .../imageverifier/v1/image_verifier.pb.go | 262 ++++++++++++++++++ .../imageverifier/v1/image_verifier.proto | 34 +++ .../v1/image_verifier_ttrpc.pb.go | 44 +++ 9 files changed, 481 insertions(+) create mode 100644 pkg/cri/server/image_verifier.go create mode 100644 pkg/cri/server/imageverifier/v1/doc.go create mode 100644 pkg/cri/server/imageverifier/v1/image_verifier.pb.go create mode 100644 pkg/cri/server/imageverifier/v1/image_verifier.proto create mode 100644 pkg/cri/server/imageverifier/v1/image_verifier_ttrpc.pb.go diff --git a/Protobuild.toml b/Protobuild.toml index 09a4c97047044..2449f0f4bc4be 100644 --- a/Protobuild.toml +++ b/Protobuild.toml @@ -19,6 +19,7 @@ prefixes = [ "github.com/containerd/containerd/runtime/v1/shim/v1", "github.com/containerd/containerd/api/runtime/task/v2", "github.com/containerd/containerd/api/runtime/sandbox/v1", + "github.com/containerd/containerd/pkg/cri/server/imageverifier/v1", ] generators = ["go", "go-ttrpc"] diff --git a/docs/cri/config.md b/docs/cri/config.md index 782a2773b2df9..81cf53408a3f2 100644 --- a/docs/cri/config.md +++ b/docs/cri/config.md @@ -436,6 +436,16 @@ version = 2 # * Containerd imgcrypt: https://github.com/containerd/imgcrypt key_model = "node" + # 'plugins."io.containerd.grpc.v1.cri".image_verification' contains config related + # to handling runtime verification of container images. + [plugins."io.containerd.grpc.v1.cri".image_verification] + # address specifies address of the TTRPC plugin handing image verification + # requests. + # + # Omission of this field defaults to the empty string "", which disables + # image verification. + address = "" + # 'plugins."io.containerd.grpc.v1.cri".registry' contains config related to # the registry [plugins."io.containerd.grpc.v1.cri".registry] diff --git a/pkg/cri/config/config.go b/pkg/cri/config/config.go index 4c9d6c22faad6..1c69c6a18e035 100644 --- a/pkg/cri/config/config.go +++ b/pkg/cri/config/config.go @@ -268,6 +268,17 @@ type ImageDecryption struct { KeyModel string `toml:"key_model" json:"keyModel"` } +// ImageVerification contains configuration related to runtime verification of +// container images. +type ImageVerification struct { + // Address specifies address of the TTRPC plugin handing image verification + // requests. + // + // Details of field usage can be found in: + // https://github.com/containerd/containerd/tree/main/docs/cri/config.md + Address string `toml:"address" json:"address"` +} + // PluginConfig contains toml config related to CRI plugin, // it is a subset of Config. type PluginConfig struct { @@ -279,6 +290,8 @@ type PluginConfig struct { Registry Registry `toml:"registry" json:"registry"` // ImageDecryption contains config related to handling decryption of encrypted container images ImageDecryption `toml:"image_decryption" json:"imageDecryption"` + // ImageVerification contains config related to runtime verification of container images + ImageVerification `toml:"image_verification" json:"imageVerification"` // DisableTCPService disables serving CRI on the TCP server. DisableTCPService bool `toml:"disable_tcp_service" json:"disableTCPService"` // StreamServerAddress is the ip address streaming server is listening on. diff --git a/pkg/cri/server/image_pull.go b/pkg/cri/server/image_pull.go index 3e8d5d2bb382b..c82974a112938 100644 --- a/pkg/cri/server/image_pull.go +++ b/pkg/cri/server/image_pull.go @@ -46,11 +46,14 @@ import ( "github.com/containerd/containerd/pkg/cri/annotations" criconfig "github.com/containerd/containerd/pkg/cri/config" crilabels "github.com/containerd/containerd/pkg/cri/labels" + "github.com/containerd/containerd/pkg/cri/server/imageverifier/v1" + "github.com/containerd/containerd/pkg/dialer" snpkg "github.com/containerd/containerd/pkg/snapshotters" distribution "github.com/containerd/containerd/reference/docker" "github.com/containerd/containerd/remotes/docker" "github.com/containerd/containerd/remotes/docker/config" "github.com/containerd/containerd/tracing" + "github.com/containerd/ttrpc" ) // For image management: @@ -156,6 +159,18 @@ func (c *criService) PullImage(ctx context.Context, r *runtime.PullImageRequest) tracing.Attribute("snapshotter.name", snapshotter), ) + if vAddr := c.config.ImageVerification.Address; vAddr != "" { + vctx, vcancel := context.WithTimeout(ctx, 1*time.Second) + defer vcancel() + conn, err := dialer.ContextDialer(vctx, "unix://"+vAddr) + if err != nil { + return nil, fmt.Errorf("failed to connect to image verification plugin: %w", err) + } + defer conn.Close() + client := imageverifier.NewImageVerifierClient(ttrpc.NewClient(conn)) + resolver = NewVerifyingResolver(resolver, client) + } + labels := c.getLabels(ctx, ref) pullOpts := []containerd.RemoteOpt{ diff --git a/pkg/cri/server/image_verifier.go b/pkg/cri/server/image_verifier.go new file mode 100644 index 0000000000000..a43f8a254f04b --- /dev/null +++ b/pkg/cri/server/image_verifier.go @@ -0,0 +1,85 @@ +/* + 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 server + +import ( + "context" + "fmt" + + "github.com/containerd/containerd/log" + "github.com/containerd/containerd/pkg/cri/server/imageverifier/v1" + "github.com/containerd/containerd/remotes" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/sirupsen/logrus" +) + +type verifyingResolver struct { + wrapped remotes.Resolver + verifier imageverifier.ImageVerifierService +} + +func NewVerifyingResolver(wrapped remotes.Resolver, verifier imageverifier.ImageVerifierService) remotes.Resolver { + return &verifyingResolver{ + wrapped: wrapped, + verifier: verifier, + } +} + +func (r *verifyingResolver) Resolve(ctx context.Context, ref string) (name string, desc ocispec.Descriptor, err error) { + name, desc, err = r.wrapped.Resolve(ctx, ref) + if err != nil { + return "", ocispec.Descriptor{}, err + } + + digest := desc.Digest.String() + + rlog := log.G(ctx).WithFields(logrus.Fields{ + "req.name": name, + "req.digest": digest, + }) + rlog.Info("Verifying image ref") + + resp, err := r.verifier.VerifyImage(ctx, &imageverifier.VerifyImageRequest{ + ImageName: name, + ImageDigest: digest, + }) + if err != nil { + rlog.WithError(err).Error("Failed to verify image, blocking pull") + return "", ocispec.Descriptor{}, fmt.Errorf("VerifyImage RPC failed: %w", err) + } + + rlog = rlog.WithFields(logrus.Fields{ + "resp.ok": resp.Ok, + "resp.reason": resp.Reason, + }) + + if !resp.Ok { + rlog.Warn("Image verifier blocked pull") + return "", ocispec.Descriptor{}, fmt.Errorf("image verifier blocked pull of %v with digest %v for reason: %v", ref, digest, resp.Reason) + } + + rlog.Info("Image verifier allowed pull") + return name, desc, err +} + +func (r *verifyingResolver) Fetcher(ctx context.Context, ref string) (remotes.Fetcher, error) { + return r.wrapped.Fetcher(ctx, ref) +} + +func (r *verifyingResolver) Pusher(ctx context.Context, ref string) (remotes.Pusher, error) { + return r.wrapped.Pusher(ctx, ref) +} diff --git a/pkg/cri/server/imageverifier/v1/doc.go b/pkg/cri/server/imageverifier/v1/doc.go new file mode 100644 index 0000000000000..f7065ecc29e7e --- /dev/null +++ b/pkg/cri/server/imageverifier/v1/doc.go @@ -0,0 +1,17 @@ +/* + 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 imageverifier diff --git a/pkg/cri/server/imageverifier/v1/image_verifier.pb.go b/pkg/cri/server/imageverifier/v1/image_verifier.pb.go new file mode 100644 index 0000000000000..0367dca1fd20c --- /dev/null +++ b/pkg/cri/server/imageverifier/v1/image_verifier.pb.go @@ -0,0 +1,262 @@ +// +//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. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.28.1 +// protoc v3.20.1 +// source: github.com/containerd/containerd/pkg/cri/server/imageverifier/v1/image_verifier.proto + +package imageverifier + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type VerifyImageRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ImageName string `protobuf:"bytes,1,opt,name=image_name,json=imageName,proto3" json:"image_name,omitempty"` + ImageDigest string `protobuf:"bytes,2,opt,name=image_digest,json=imageDigest,proto3" json:"image_digest,omitempty"` +} + +func (x *VerifyImageRequest) Reset() { + *x = VerifyImageRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_github_com_containerd_containerd_pkg_cri_server_imageverifier_v1_image_verifier_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *VerifyImageRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*VerifyImageRequest) ProtoMessage() {} + +func (x *VerifyImageRequest) ProtoReflect() protoreflect.Message { + mi := &file_github_com_containerd_containerd_pkg_cri_server_imageverifier_v1_image_verifier_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use VerifyImageRequest.ProtoReflect.Descriptor instead. +func (*VerifyImageRequest) Descriptor() ([]byte, []int) { + return file_github_com_containerd_containerd_pkg_cri_server_imageverifier_v1_image_verifier_proto_rawDescGZIP(), []int{0} +} + +func (x *VerifyImageRequest) GetImageName() string { + if x != nil { + return x.ImageName + } + return "" +} + +func (x *VerifyImageRequest) GetImageDigest() string { + if x != nil { + return x.ImageDigest + } + return "" +} + +type VerifyImageResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Ok bool `protobuf:"varint,1,opt,name=ok,proto3" json:"ok,omitempty"` + Reason string `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"` +} + +func (x *VerifyImageResponse) Reset() { + *x = VerifyImageResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_github_com_containerd_containerd_pkg_cri_server_imageverifier_v1_image_verifier_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *VerifyImageResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*VerifyImageResponse) ProtoMessage() {} + +func (x *VerifyImageResponse) ProtoReflect() protoreflect.Message { + mi := &file_github_com_containerd_containerd_pkg_cri_server_imageverifier_v1_image_verifier_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use VerifyImageResponse.ProtoReflect.Descriptor instead. +func (*VerifyImageResponse) Descriptor() ([]byte, []int) { + return file_github_com_containerd_containerd_pkg_cri_server_imageverifier_v1_image_verifier_proto_rawDescGZIP(), []int{1} +} + +func (x *VerifyImageResponse) GetOk() bool { + if x != nil { + return x.Ok + } + return false +} + +func (x *VerifyImageResponse) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +var File_github_com_containerd_containerd_pkg_cri_server_imageverifier_v1_image_verifier_proto protoreflect.FileDescriptor + +var file_github_com_containerd_containerd_pkg_cri_server_imageverifier_v1_image_verifier_proto_rawDesc = []byte{ + 0x0a, 0x55, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, + 0x72, 0x64, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x63, 0x72, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x2f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x72, 0x2f, + 0x76, 0x31, 0x2f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, + 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x64, 0x2e, 0x63, 0x72, 0x69, 0x2e, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x76, 0x65, 0x72, + 0x69, 0x66, 0x69, 0x65, 0x72, 0x22, 0x56, 0x0a, 0x12, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x49, + 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x69, + 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6d, + 0x61, 0x67, 0x65, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x22, 0x3d, 0x0a, + 0x13, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x02, 0x6f, 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x32, 0x83, 0x01, 0x0a, + 0x0d, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x72, + 0x0a, 0x0b, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x30, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x63, 0x72, 0x69, 0x2e, 0x69, + 0x6d, 0x61, 0x67, 0x65, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x72, 0x2e, 0x56, 0x65, 0x72, + 0x69, 0x66, 0x79, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x63, 0x72, 0x69, + 0x2e, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x72, 0x2e, 0x56, + 0x65, 0x72, 0x69, 0x66, 0x79, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x42, 0x50, 0x5a, 0x4e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2f, 0x63, 0x6f, 0x6e, 0x74, + 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x63, 0x72, 0x69, 0x2f, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x76, 0x65, 0x72, 0x69, 0x66, + 0x69, 0x65, 0x72, 0x2f, 0x76, 0x31, 0x3b, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x76, 0x65, 0x72, 0x69, + 0x66, 0x69, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_github_com_containerd_containerd_pkg_cri_server_imageverifier_v1_image_verifier_proto_rawDescOnce sync.Once + file_github_com_containerd_containerd_pkg_cri_server_imageverifier_v1_image_verifier_proto_rawDescData = file_github_com_containerd_containerd_pkg_cri_server_imageverifier_v1_image_verifier_proto_rawDesc +) + +func file_github_com_containerd_containerd_pkg_cri_server_imageverifier_v1_image_verifier_proto_rawDescGZIP() []byte { + file_github_com_containerd_containerd_pkg_cri_server_imageverifier_v1_image_verifier_proto_rawDescOnce.Do(func() { + file_github_com_containerd_containerd_pkg_cri_server_imageverifier_v1_image_verifier_proto_rawDescData = protoimpl.X.CompressGZIP(file_github_com_containerd_containerd_pkg_cri_server_imageverifier_v1_image_verifier_proto_rawDescData) + }) + return file_github_com_containerd_containerd_pkg_cri_server_imageverifier_v1_image_verifier_proto_rawDescData +} + +var file_github_com_containerd_containerd_pkg_cri_server_imageverifier_v1_image_verifier_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_github_com_containerd_containerd_pkg_cri_server_imageverifier_v1_image_verifier_proto_goTypes = []interface{}{ + (*VerifyImageRequest)(nil), // 0: containerd.cri.imageverifier.VerifyImageRequest + (*VerifyImageResponse)(nil), // 1: containerd.cri.imageverifier.VerifyImageResponse +} +var file_github_com_containerd_containerd_pkg_cri_server_imageverifier_v1_image_verifier_proto_depIdxs = []int32{ + 0, // 0: containerd.cri.imageverifier.ImageVerifier.VerifyImage:input_type -> containerd.cri.imageverifier.VerifyImageRequest + 1, // 1: containerd.cri.imageverifier.ImageVerifier.VerifyImage:output_type -> containerd.cri.imageverifier.VerifyImageResponse + 1, // [1:2] is the sub-list for method output_type + 0, // [0:1] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { + file_github_com_containerd_containerd_pkg_cri_server_imageverifier_v1_image_verifier_proto_init() +} +func file_github_com_containerd_containerd_pkg_cri_server_imageverifier_v1_image_verifier_proto_init() { + if File_github_com_containerd_containerd_pkg_cri_server_imageverifier_v1_image_verifier_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_github_com_containerd_containerd_pkg_cri_server_imageverifier_v1_image_verifier_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*VerifyImageRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_github_com_containerd_containerd_pkg_cri_server_imageverifier_v1_image_verifier_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*VerifyImageResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_github_com_containerd_containerd_pkg_cri_server_imageverifier_v1_image_verifier_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_github_com_containerd_containerd_pkg_cri_server_imageverifier_v1_image_verifier_proto_goTypes, + DependencyIndexes: file_github_com_containerd_containerd_pkg_cri_server_imageverifier_v1_image_verifier_proto_depIdxs, + MessageInfos: file_github_com_containerd_containerd_pkg_cri_server_imageverifier_v1_image_verifier_proto_msgTypes, + }.Build() + File_github_com_containerd_containerd_pkg_cri_server_imageverifier_v1_image_verifier_proto = out.File + file_github_com_containerd_containerd_pkg_cri_server_imageverifier_v1_image_verifier_proto_rawDesc = nil + file_github_com_containerd_containerd_pkg_cri_server_imageverifier_v1_image_verifier_proto_goTypes = nil + file_github_com_containerd_containerd_pkg_cri_server_imageverifier_v1_image_verifier_proto_depIdxs = nil +} diff --git a/pkg/cri/server/imageverifier/v1/image_verifier.proto b/pkg/cri/server/imageverifier/v1/image_verifier.proto new file mode 100644 index 0000000000000..f6489caed5e1d --- /dev/null +++ b/pkg/cri/server/imageverifier/v1/image_verifier.proto @@ -0,0 +1,34 @@ +/* + 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. +*/ + +syntax = "proto3"; + +package containerd.cri.imageverifier; +option go_package = "github.com/containerd/containerd/pkg/cri/server/imageverifier/v1;imageverifier"; + +service ImageVerifier { + rpc VerifyImage(VerifyImageRequest) returns (VerifyImageResponse); +} + +message VerifyImageRequest { + string image_name = 1; + string image_digest = 2; +} + +message VerifyImageResponse { + bool ok = 1; + string reason = 2; +} diff --git a/pkg/cri/server/imageverifier/v1/image_verifier_ttrpc.pb.go b/pkg/cri/server/imageverifier/v1/image_verifier_ttrpc.pb.go new file mode 100644 index 0000000000000..6b75d08d46294 --- /dev/null +++ b/pkg/cri/server/imageverifier/v1/image_verifier_ttrpc.pb.go @@ -0,0 +1,44 @@ +// Code generated by protoc-gen-go-ttrpc. DO NOT EDIT. +// source: github.com/containerd/containerd/pkg/cri/server/imageverifier/v1/image_verifier.proto +package imageverifier + +import ( + context "context" + ttrpc "github.com/containerd/ttrpc" +) + +type ImageVerifierService interface { + VerifyImage(context.Context, *VerifyImageRequest) (*VerifyImageResponse, error) +} + +func RegisterImageVerifierService(srv *ttrpc.Server, svc ImageVerifierService) { + srv.RegisterService("containerd.cri.imageverifier.ImageVerifier", &ttrpc.ServiceDesc{ + Methods: map[string]ttrpc.Method{ + "VerifyImage": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) { + var req VerifyImageRequest + if err := unmarshal(&req); err != nil { + return nil, err + } + return svc.VerifyImage(ctx, &req) + }, + }, + }) +} + +type imageverifierClient struct { + client *ttrpc.Client +} + +func NewImageVerifierClient(client *ttrpc.Client) ImageVerifierService { + return &imageverifierClient{ + client: client, + } +} + +func (c *imageverifierClient) VerifyImage(ctx context.Context, req *VerifyImageRequest) (*VerifyImageResponse, error) { + var resp VerifyImageResponse + if err := c.client.Call(ctx, "containerd.cri.imageverifier.ImageVerifier", "VerifyImage", req, &resp); err != nil { + return nil, err + } + return &resp, nil +}