diff --git a/app/controlplane/api/controlplane/v1/signing.pb.go b/app/controlplane/api/controlplane/v1/signing.pb.go new file mode 100644 index 000000000..fa7bc2b0f --- /dev/null +++ b/app/controlplane/api/controlplane/v1/signing.pb.go @@ -0,0 +1,304 @@ +// +// Copyright 2024 The Chainloop 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.31.0 +// protoc (unknown) +// source: controlplane/v1/signing.proto + +package v1 + +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 SigningCertRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + CertificateSigningRequest []byte `protobuf:"bytes,1,opt,name=certificate_signing_request,json=certificateSigningRequest,proto3" json:"certificate_signing_request,omitempty"` +} + +func (x *SigningCertRequest) Reset() { + *x = SigningCertRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_controlplane_v1_signing_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SigningCertRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SigningCertRequest) ProtoMessage() {} + +func (x *SigningCertRequest) ProtoReflect() protoreflect.Message { + mi := &file_controlplane_v1_signing_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 SigningCertRequest.ProtoReflect.Descriptor instead. +func (*SigningCertRequest) Descriptor() ([]byte, []int) { + return file_controlplane_v1_signing_proto_rawDescGZIP(), []int{0} +} + +func (x *SigningCertRequest) GetCertificateSigningRequest() []byte { + if x != nil { + return x.CertificateSigningRequest + } + return nil +} + +type SigningCertResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Chain *CertificateChain `protobuf:"bytes,1,opt,name=chain,proto3" json:"chain,omitempty"` +} + +func (x *SigningCertResponse) Reset() { + *x = SigningCertResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_controlplane_v1_signing_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SigningCertResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SigningCertResponse) ProtoMessage() {} + +func (x *SigningCertResponse) ProtoReflect() protoreflect.Message { + mi := &file_controlplane_v1_signing_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 SigningCertResponse.ProtoReflect.Descriptor instead. +func (*SigningCertResponse) Descriptor() ([]byte, []int) { + return file_controlplane_v1_signing_proto_rawDescGZIP(), []int{1} +} + +func (x *SigningCertResponse) GetChain() *CertificateChain { + if x != nil { + return x.Chain + } + return nil +} + +type CertificateChain struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The PEM-encoded certificate chain, ordered from leaf to intermediate to root as applicable. + Certificates []string `protobuf:"bytes,1,rep,name=certificates,proto3" json:"certificates,omitempty"` +} + +func (x *CertificateChain) Reset() { + *x = CertificateChain{} + if protoimpl.UnsafeEnabled { + mi := &file_controlplane_v1_signing_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CertificateChain) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CertificateChain) ProtoMessage() {} + +func (x *CertificateChain) ProtoReflect() protoreflect.Message { + mi := &file_controlplane_v1_signing_proto_msgTypes[2] + 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 CertificateChain.ProtoReflect.Descriptor instead. +func (*CertificateChain) Descriptor() ([]byte, []int) { + return file_controlplane_v1_signing_proto_rawDescGZIP(), []int{2} +} + +func (x *CertificateChain) GetCertificates() []string { + if x != nil { + return x.Certificates + } + return nil +} + +var File_controlplane_v1_signing_proto protoreflect.FileDescriptor + +var file_controlplane_v1_signing_proto_rawDesc = []byte{ + 0x0a, 0x1d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x76, + 0x31, 0x2f, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, + 0x0f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, + 0x22, 0x54, 0x0a, 0x12, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x65, 0x72, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x1b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x19, 0x63, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x4e, 0x0a, 0x13, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, + 0x67, 0x43, 0x65, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, + 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x52, + 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x22, 0x36, 0x0a, 0x10, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x65, + 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x0c, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x32, 0x6a, + 0x0a, 0x0e, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x12, 0x58, 0x0a, 0x0b, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x65, 0x72, 0x74, 0x12, + 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x65, 0x72, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, + 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x65, + 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x4c, 0x5a, 0x4a, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x6f, + 0x6f, 0x70, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x6f, 0x6f, 0x70, + 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, + 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, + 0x6e, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_controlplane_v1_signing_proto_rawDescOnce sync.Once + file_controlplane_v1_signing_proto_rawDescData = file_controlplane_v1_signing_proto_rawDesc +) + +func file_controlplane_v1_signing_proto_rawDescGZIP() []byte { + file_controlplane_v1_signing_proto_rawDescOnce.Do(func() { + file_controlplane_v1_signing_proto_rawDescData = protoimpl.X.CompressGZIP(file_controlplane_v1_signing_proto_rawDescData) + }) + return file_controlplane_v1_signing_proto_rawDescData +} + +var file_controlplane_v1_signing_proto_msgTypes = make([]protoimpl.MessageInfo, 3) +var file_controlplane_v1_signing_proto_goTypes = []interface{}{ + (*SigningCertRequest)(nil), // 0: controlplane.v1.SigningCertRequest + (*SigningCertResponse)(nil), // 1: controlplane.v1.SigningCertResponse + (*CertificateChain)(nil), // 2: controlplane.v1.CertificateChain +} +var file_controlplane_v1_signing_proto_depIdxs = []int32{ + 2, // 0: controlplane.v1.SigningCertResponse.chain:type_name -> controlplane.v1.CertificateChain + 0, // 1: controlplane.v1.SigningService.SigningCert:input_type -> controlplane.v1.SigningCertRequest + 1, // 2: controlplane.v1.SigningService.SigningCert:output_type -> controlplane.v1.SigningCertResponse + 2, // [2:3] is the sub-list for method output_type + 1, // [1:2] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_controlplane_v1_signing_proto_init() } +func file_controlplane_v1_signing_proto_init() { + if File_controlplane_v1_signing_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_controlplane_v1_signing_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SigningCertRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_controlplane_v1_signing_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SigningCertResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_controlplane_v1_signing_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CertificateChain); 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_controlplane_v1_signing_proto_rawDesc, + NumEnums: 0, + NumMessages: 3, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_controlplane_v1_signing_proto_goTypes, + DependencyIndexes: file_controlplane_v1_signing_proto_depIdxs, + MessageInfos: file_controlplane_v1_signing_proto_msgTypes, + }.Build() + File_controlplane_v1_signing_proto = out.File + file_controlplane_v1_signing_proto_rawDesc = nil + file_controlplane_v1_signing_proto_goTypes = nil + file_controlplane_v1_signing_proto_depIdxs = nil +} diff --git a/app/controlplane/api/controlplane/v1/signing.proto b/app/controlplane/api/controlplane/v1/signing.proto new file mode 100644 index 000000000..04c0a59f5 --- /dev/null +++ b/app/controlplane/api/controlplane/v1/signing.proto @@ -0,0 +1,40 @@ +// +// Copyright 2024 The Chainloop 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 controlplane.v1; + +option go_package = "github.com/chainloop-dev/chainloop/app/controlplane/api/controlplane/v1;v1"; + +service SigningService { + rpc SigningCert (SigningCertRequest) returns (SigningCertResponse); +} + +message SigningCertRequest { + bytes certificate_signing_request = 1; +} + +message SigningCertResponse { + CertificateChain chain = 1; +} + +message CertificateChain { + /* + * The PEM-encoded certificate chain, ordered from leaf to intermediate to root as applicable. + */ + repeated string certificates = 1; +} diff --git a/app/controlplane/api/controlplane/v1/signing_grpc.pb.go b/app/controlplane/api/controlplane/v1/signing_grpc.pb.go new file mode 100644 index 000000000..4edeb2c44 --- /dev/null +++ b/app/controlplane/api/controlplane/v1/signing_grpc.pb.go @@ -0,0 +1,124 @@ +// +// Copyright 2024 The Chainloop 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-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.3.0 +// - protoc (unknown) +// source: controlplane/v1/signing.proto + +package v1 + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +const ( + SigningService_SigningCert_FullMethodName = "/controlplane.v1.SigningService/SigningCert" +) + +// SigningServiceClient is the client API for SigningService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type SigningServiceClient interface { + SigningCert(ctx context.Context, in *SigningCertRequest, opts ...grpc.CallOption) (*SigningCertResponse, error) +} + +type signingServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewSigningServiceClient(cc grpc.ClientConnInterface) SigningServiceClient { + return &signingServiceClient{cc} +} + +func (c *signingServiceClient) SigningCert(ctx context.Context, in *SigningCertRequest, opts ...grpc.CallOption) (*SigningCertResponse, error) { + out := new(SigningCertResponse) + err := c.cc.Invoke(ctx, SigningService_SigningCert_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// SigningServiceServer is the server API for SigningService service. +// All implementations must embed UnimplementedSigningServiceServer +// for forward compatibility +type SigningServiceServer interface { + SigningCert(context.Context, *SigningCertRequest) (*SigningCertResponse, error) + mustEmbedUnimplementedSigningServiceServer() +} + +// UnimplementedSigningServiceServer must be embedded to have forward compatible implementations. +type UnimplementedSigningServiceServer struct { +} + +func (UnimplementedSigningServiceServer) SigningCert(context.Context, *SigningCertRequest) (*SigningCertResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SigningCert not implemented") +} +func (UnimplementedSigningServiceServer) mustEmbedUnimplementedSigningServiceServer() {} + +// UnsafeSigningServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to SigningServiceServer will +// result in compilation errors. +type UnsafeSigningServiceServer interface { + mustEmbedUnimplementedSigningServiceServer() +} + +func RegisterSigningServiceServer(s grpc.ServiceRegistrar, srv SigningServiceServer) { + s.RegisterService(&SigningService_ServiceDesc, srv) +} + +func _SigningService_SigningCert_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SigningCertRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SigningServiceServer).SigningCert(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: SigningService_SigningCert_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SigningServiceServer).SigningCert(ctx, req.(*SigningCertRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// SigningService_ServiceDesc is the grpc.ServiceDesc for SigningService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var SigningService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "controlplane.v1.SigningService", + HandlerType: (*SigningServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "SigningCert", + Handler: _SigningService_SigningCert_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "controlplane/v1/signing.proto", +} diff --git a/app/controlplane/api/gen/frontend/controlplane/v1/signing.ts b/app/controlplane/api/gen/frontend/controlplane/v1/signing.ts new file mode 100644 index 000000000..9a1af9402 --- /dev/null +++ b/app/controlplane/api/gen/frontend/controlplane/v1/signing.ts @@ -0,0 +1,375 @@ +/* eslint-disable */ +import { grpc } from "@improbable-eng/grpc-web"; +import { BrowserHeaders } from "browser-headers"; +import _m0 from "protobufjs/minimal"; + +export const protobufPackage = "controlplane.v1"; + +export interface SigningCertRequest { + certificateSigningRequest: Uint8Array; +} + +export interface SigningCertResponse { + chain?: CertificateChain; +} + +export interface CertificateChain { + /** The PEM-encoded certificate chain, ordered from leaf to intermediate to root as applicable. */ + certificates: string[]; +} + +function createBaseSigningCertRequest(): SigningCertRequest { + return { certificateSigningRequest: new Uint8Array(0) }; +} + +export const SigningCertRequest = { + encode(message: SigningCertRequest, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.certificateSigningRequest.length !== 0) { + writer.uint32(10).bytes(message.certificateSigningRequest); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): SigningCertRequest { + const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseSigningCertRequest(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + if (tag !== 10) { + break; + } + + message.certificateSigningRequest = reader.bytes(); + continue; + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skipType(tag & 7); + } + return message; + }, + + fromJSON(object: any): SigningCertRequest { + return { + certificateSigningRequest: isSet(object.certificateSigningRequest) + ? bytesFromBase64(object.certificateSigningRequest) + : new Uint8Array(0), + }; + }, + + toJSON(message: SigningCertRequest): unknown { + const obj: any = {}; + message.certificateSigningRequest !== undefined && + (obj.certificateSigningRequest = base64FromBytes( + message.certificateSigningRequest !== undefined ? message.certificateSigningRequest : new Uint8Array(0), + )); + return obj; + }, + + create, I>>(base?: I): SigningCertRequest { + return SigningCertRequest.fromPartial(base ?? {}); + }, + + fromPartial, I>>(object: I): SigningCertRequest { + const message = createBaseSigningCertRequest(); + message.certificateSigningRequest = object.certificateSigningRequest ?? new Uint8Array(0); + return message; + }, +}; + +function createBaseSigningCertResponse(): SigningCertResponse { + return { chain: undefined }; +} + +export const SigningCertResponse = { + encode(message: SigningCertResponse, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.chain !== undefined) { + CertificateChain.encode(message.chain, writer.uint32(10).fork()).ldelim(); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): SigningCertResponse { + const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseSigningCertResponse(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + if (tag !== 10) { + break; + } + + message.chain = CertificateChain.decode(reader, reader.uint32()); + continue; + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skipType(tag & 7); + } + return message; + }, + + fromJSON(object: any): SigningCertResponse { + return { chain: isSet(object.chain) ? CertificateChain.fromJSON(object.chain) : undefined }; + }, + + toJSON(message: SigningCertResponse): unknown { + const obj: any = {}; + message.chain !== undefined && (obj.chain = message.chain ? CertificateChain.toJSON(message.chain) : undefined); + return obj; + }, + + create, I>>(base?: I): SigningCertResponse { + return SigningCertResponse.fromPartial(base ?? {}); + }, + + fromPartial, I>>(object: I): SigningCertResponse { + const message = createBaseSigningCertResponse(); + message.chain = (object.chain !== undefined && object.chain !== null) + ? CertificateChain.fromPartial(object.chain) + : undefined; + return message; + }, +}; + +function createBaseCertificateChain(): CertificateChain { + return { certificates: [] }; +} + +export const CertificateChain = { + encode(message: CertificateChain, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + for (const v of message.certificates) { + writer.uint32(10).string(v!); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): CertificateChain { + const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseCertificateChain(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + if (tag !== 10) { + break; + } + + message.certificates.push(reader.string()); + continue; + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skipType(tag & 7); + } + return message; + }, + + fromJSON(object: any): CertificateChain { + return { certificates: Array.isArray(object?.certificates) ? object.certificates.map((e: any) => String(e)) : [] }; + }, + + toJSON(message: CertificateChain): unknown { + const obj: any = {}; + if (message.certificates) { + obj.certificates = message.certificates.map((e) => e); + } else { + obj.certificates = []; + } + return obj; + }, + + create, I>>(base?: I): CertificateChain { + return CertificateChain.fromPartial(base ?? {}); + }, + + fromPartial, I>>(object: I): CertificateChain { + const message = createBaseCertificateChain(); + message.certificates = object.certificates?.map((e) => e) || []; + return message; + }, +}; + +export interface SigningService { + SigningCert(request: DeepPartial, metadata?: grpc.Metadata): Promise; +} + +export class SigningServiceClientImpl implements SigningService { + private readonly rpc: Rpc; + + constructor(rpc: Rpc) { + this.rpc = rpc; + this.SigningCert = this.SigningCert.bind(this); + } + + SigningCert(request: DeepPartial, metadata?: grpc.Metadata): Promise { + return this.rpc.unary(SigningServiceSigningCertDesc, SigningCertRequest.fromPartial(request), metadata); + } +} + +export const SigningServiceDesc = { serviceName: "controlplane.v1.SigningService" }; + +export const SigningServiceSigningCertDesc: UnaryMethodDefinitionish = { + methodName: "SigningCert", + service: SigningServiceDesc, + requestStream: false, + responseStream: false, + requestType: { + serializeBinary() { + return SigningCertRequest.encode(this).finish(); + }, + } as any, + responseType: { + deserializeBinary(data: Uint8Array) { + const value = SigningCertResponse.decode(data); + return { + ...value, + toObject() { + return value; + }, + }; + }, + } as any, +}; + +interface UnaryMethodDefinitionishR extends grpc.UnaryMethodDefinition { + requestStream: any; + responseStream: any; +} + +type UnaryMethodDefinitionish = UnaryMethodDefinitionishR; + +interface Rpc { + unary( + methodDesc: T, + request: any, + metadata: grpc.Metadata | undefined, + ): Promise; +} + +export class GrpcWebImpl { + private host: string; + private options: { + transport?: grpc.TransportFactory; + + debug?: boolean; + metadata?: grpc.Metadata; + upStreamRetryCodes?: number[]; + }; + + constructor( + host: string, + options: { + transport?: grpc.TransportFactory; + + debug?: boolean; + metadata?: grpc.Metadata; + upStreamRetryCodes?: number[]; + }, + ) { + this.host = host; + this.options = options; + } + + unary( + methodDesc: T, + _request: any, + metadata: grpc.Metadata | undefined, + ): Promise { + const request = { ..._request, ...methodDesc.requestType }; + const maybeCombinedMetadata = metadata && this.options.metadata + ? new BrowserHeaders({ ...this.options?.metadata.headersMap, ...metadata?.headersMap }) + : metadata || this.options.metadata; + return new Promise((resolve, reject) => { + grpc.unary(methodDesc, { + request, + host: this.host, + metadata: maybeCombinedMetadata, + transport: this.options.transport, + debug: this.options.debug, + onEnd: function (response) { + if (response.status === grpc.Code.OK) { + resolve(response.message!.toObject()); + } else { + const err = new GrpcWebError(response.statusMessage, response.status, response.trailers); + reject(err); + } + }, + }); + }); + } +} + +declare var self: any | undefined; +declare var window: any | undefined; +declare var global: any | undefined; +var tsProtoGlobalThis: any = (() => { + if (typeof globalThis !== "undefined") { + return globalThis; + } + if (typeof self !== "undefined") { + return self; + } + if (typeof window !== "undefined") { + return window; + } + if (typeof global !== "undefined") { + return global; + } + throw "Unable to locate global object"; +})(); + +function bytesFromBase64(b64: string): Uint8Array { + if (tsProtoGlobalThis.Buffer) { + return Uint8Array.from(tsProtoGlobalThis.Buffer.from(b64, "base64")); + } else { + const bin = tsProtoGlobalThis.atob(b64); + const arr = new Uint8Array(bin.length); + for (let i = 0; i < bin.length; ++i) { + arr[i] = bin.charCodeAt(i); + } + return arr; + } +} + +function base64FromBytes(arr: Uint8Array): string { + if (tsProtoGlobalThis.Buffer) { + return tsProtoGlobalThis.Buffer.from(arr).toString("base64"); + } else { + const bin: string[] = []; + arr.forEach((byte) => { + bin.push(String.fromCharCode(byte)); + }); + return tsProtoGlobalThis.btoa(bin.join("")); + } +} + +type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; + +export type DeepPartial = T extends Builtin ? T + : T extends Array ? Array> : T extends ReadonlyArray ? ReadonlyArray> + : T extends {} ? { [K in keyof T]?: DeepPartial } + : Partial; + +type KeysOfUnion = T extends T ? keyof T : never; +export type Exact = P extends Builtin ? P + : P & { [K in keyof P]: Exact } & { [K in Exclude>]: never }; + +function isSet(value: any): boolean { + return value !== null && value !== undefined; +} + +export class GrpcWebError extends tsProtoGlobalThis.Error { + constructor(message: string, public code: grpc.Code, public metadata: grpc.Metadata) { + super(message); + } +} diff --git a/app/controlplane/internal/service/service.go b/app/controlplane/internal/service/service.go index 6d544f0ba..7f851d866 100644 --- a/app/controlplane/internal/service/service.go +++ b/app/controlplane/internal/service/service.go @@ -47,6 +47,7 @@ var ProviderSet = wire.NewSet( NewAPITokenService, NewAttestationStateService, NewUserService, + NewSigningService, wire.Struct(new(NewWorkflowRunServiceOpts), "*"), wire.Struct(new(NewAttestationServiceOpts), "*"), ) diff --git a/app/controlplane/internal/service/signing.go b/app/controlplane/internal/service/signing.go new file mode 100644 index 000000000..5db496255 --- /dev/null +++ b/app/controlplane/internal/service/signing.go @@ -0,0 +1,58 @@ +// +// Copyright 2024 The Chainloop 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 service + +import ( + "context" + + v1 "github.com/chainloop-dev/chainloop/app/controlplane/api/controlplane/v1" + "github.com/chainloop-dev/chainloop/app/controlplane/internal/biz" + "github.com/chainloop-dev/chainloop/app/controlplane/internal/usercontext" + "github.com/go-kratos/kratos/v2/errors" +) + +type SigningService struct { + v1.UnimplementedSigningServiceServer + *service + + signing biz.SigningCertCreator +} + +var _ v1.SigningServiceServer = (*SigningService)(nil) + +func NewSigningService(signing biz.SigningCertCreator) *SigningService { + return &SigningService{ + signing: signing, + } +} + +func (s *SigningService) SigningCert(ctx context.Context, req *v1.SigningCertRequest) (*v1.SigningCertResponse, error) { + if len(req.GetCertificateSigningRequest()) == 0 { + return nil, errors.BadRequest("missing csr", "a certificate request is expected") + } + + ra := usercontext.CurrentRobotAccount(ctx) + if ra == nil { + return nil, errors.Unauthorized("missing org", "authentication data is required") + } + + certs, err := s.signing.CreateSigningCert(ctx, ra.OrgID, req.GetCertificateSigningRequest()) + if err != nil { + return nil, handleUseCaseErr(err, s.log) + } + + return &v1.SigningCertResponse{Chain: &v1.CertificateChain{Certificates: certs}}, nil +}