diff --git a/actions/client.go b/actions/client.go index db5617a..adaf797 100644 --- a/actions/client.go +++ b/actions/client.go @@ -394,3 +394,71 @@ func ActionClientChangePassword(c *cli.Context) error { } return nil } + +func ActionClientCertList(c *cli.Context) error { + cfg, err := getConfig(c) + if err != nil { + return err + } + + addr := cfg.Client.DefaultServer + if c.IsSet("addr") { + addr = c.String("addr") + } + + clientCreds, err := cfg.Client.Creds() + if err != nil { + return err + } + conn, err := grpc.DialContext(c.Context, addr, grpc.WithTransportCredentials(clientCreds)) + + if err != nil { + return err + } + defer conn.Close() + + client := pb.NewCertificateServiceClient(conn) + resp, err := client.ListCertificates(c.Context, &pb.Empty{}) + if err != nil { + return cli.Exit(fmt.Sprintf("unable to list certificates: %s", err), 1) + } + + for _, info := range resp.Certificates { + fmt.Printf("%s - %s", info.Serial, info.OwnerUsername) + } + return nil +} + +func ActionClientCertRevoke(c *cli.Context) error { + if c.Args().Len() < 1 { + return cli.Exit("need at least 1 argument", 1) + } + cfg, err := getConfig(c) + if err != nil { + return err + } + + addr := cfg.Client.DefaultServer + if c.IsSet("addr") { + addr = c.String("addr") + } + + clientCreds, err := cfg.Client.Creds() + if err != nil { + return err + } + conn, err := grpc.DialContext(c.Context, addr, grpc.WithTransportCredentials(clientCreds)) + + if err != nil { + return err + } + defer conn.Close() + + client := pb.NewCertificateServiceClient(conn) + for _, serial := range c.Args().Slice() { + if _, err := client.RevokeCertificate(c.Context, &pb.RevokeCertificateRequest{Serial: serial}); err != nil { + fmt.Printf("Revoked %s\n", serial) + } + } + return nil +} diff --git a/actions/serve.go b/actions/serve.go index fe557f8..8773b34 100644 --- a/actions/serve.go +++ b/actions/serve.go @@ -33,6 +33,7 @@ func ActionServe(c *cli.Context) error { serverLogger := logger.Named("SERV") authLogger := logger.Named("AUTH") httpLogger := logger.Named("HTTP") + certLogger := logger.Named("CERT") // Read certificates srvCertBytes, err := cfg.Server.GRPC.Certs.GetCertBytes() @@ -108,6 +109,10 @@ func ActionServe(c *cli.Context) error { grpcFileServer.Hostname = c.String("hostname") } + // Setup cert-service + certServiceServer := server.NewCertServiceServer(certSvc, certStore, userStore) + certServiceServer.Logger = certLogger + // Setup user-service grpcUserServer := server.NewGRPCUserServiceServer(userStore, certSvc) grpcUserServer.Logger = logger.Named("USER") @@ -140,6 +145,7 @@ func ActionServe(c *cli.Context) error { ) pb.RegisterFileServiceServer(grpcServer, grpcFileServer) pb.RegisterUserServiceServer(grpcServer, grpcUserServer) + pb.RegisterCertificateServiceServer(grpcServer, certServiceServer) // wait for cancel go func() { diff --git a/certs/certservice.go b/certs/certservice.go index 4624504..046f05b 100644 --- a/certs/certservice.go +++ b/certs/certservice.go @@ -66,11 +66,10 @@ func (cs *CertService) NewClient(id string) ([]byte, []byte, error) { Country: []string{"No"}, Locality: []string{"Oslo"}, }, - NotBefore: time.Now(), - NotAfter: time.Now().AddDate(10, 0, 0), - SubjectKeyId: []byte{1, 2, 3, 4, 6}, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, - KeyUsage: x509.KeyUsageDigitalSignature, + NotBefore: time.Now(), + NotAfter: time.Now().AddDate(0, 0, 30), + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, + KeyUsage: x509.KeyUsageDigitalSignature, } certPrivKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) @@ -102,6 +101,15 @@ func (cs *CertService) NewClient(id string) ([]byte, []byte, error) { return nil, nil, fmt.Errorf("unable to encode client private key: %w", err) } + signed, err := x509.ParseCertificate(certBytes) + if err != nil { + return nil, nil, err + } + + if err := cs.store.StoreCertificate(signed); err != nil { + return nil, nil, err + } + return certPEM.Bytes(), keyPEM.Bytes(), nil } diff --git a/main.go b/main.go index 766d337..15128b6 100644 --- a/main.go +++ b/main.go @@ -114,6 +114,23 @@ func main() { Usage: "Initialize default config", Action: actions.ActionInitConfig, }, + { + Name: "cert", + Usage: "Certificate-related commands", + Subcommands: []*cli.Command{ + { + Name: "list", + Usage: "List certificates", + Action: actions.ActionClientCertList, + }, + { + Name: "revoke", + Usage: "Revoke certificate(s)", + ArgsUsage: "SERIAL [SERIAL...]", + Action: actions.ActionClientCertRevoke, + }, + }, + }, }, }, { diff --git a/pb/ezshare.pb.go b/pb/ezshare.pb.go index a5a2bc9..251bbe5 100644 --- a/pb/ezshare.pb.go +++ b/pb/ezshare.pb.go @@ -1064,6 +1064,102 @@ func (x *ChangePasswordRequest) GetNewPassword() string { return "" } +// List +type ListCertificatesResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Certificates []*ListCertificatesResponse_CertificateInfo `protobuf:"bytes,1,rep,name=certificates,proto3" json:"certificates,omitempty"` +} + +func (x *ListCertificatesResponse) Reset() { + *x = ListCertificatesResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_protos_ezshare_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListCertificatesResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListCertificatesResponse) ProtoMessage() {} + +func (x *ListCertificatesResponse) ProtoReflect() protoreflect.Message { + mi := &file_protos_ezshare_proto_msgTypes[19] + 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 ListCertificatesResponse.ProtoReflect.Descriptor instead. +func (*ListCertificatesResponse) Descriptor() ([]byte, []int) { + return file_protos_ezshare_proto_rawDescGZIP(), []int{19} +} + +func (x *ListCertificatesResponse) GetCertificates() []*ListCertificatesResponse_CertificateInfo { + if x != nil { + return x.Certificates + } + return nil +} + +// Revoke +type RevokeCertificateRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Serial string `protobuf:"bytes,1,opt,name=serial,proto3" json:"serial,omitempty"` +} + +func (x *RevokeCertificateRequest) Reset() { + *x = RevokeCertificateRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_protos_ezshare_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RevokeCertificateRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RevokeCertificateRequest) ProtoMessage() {} + +func (x *RevokeCertificateRequest) ProtoReflect() protoreflect.Message { + mi := &file_protos_ezshare_proto_msgTypes[20] + 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 RevokeCertificateRequest.ProtoReflect.Descriptor instead. +func (*RevokeCertificateRequest) Descriptor() ([]byte, []int) { + return file_protos_ezshare_proto_rawDescGZIP(), []int{20} +} + +func (x *RevokeCertificateRequest) GetSerial() string { + if x != nil { + return x.Serial + } + return "" +} + type File_Metadata struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1077,7 +1173,7 @@ type File_Metadata struct { func (x *File_Metadata) Reset() { *x = File_Metadata{} if protoimpl.UnsafeEnabled { - mi := &file_protos_ezshare_proto_msgTypes[19] + mi := &file_protos_ezshare_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1090,7 +1186,7 @@ func (x *File_Metadata) String() string { func (*File_Metadata) ProtoMessage() {} func (x *File_Metadata) ProtoReflect() protoreflect.Message { - mi := &file_protos_ezshare_proto_msgTypes[19] + mi := &file_protos_ezshare_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1139,7 +1235,7 @@ type ListFilesResponse_ListFileInfo struct { func (x *ListFilesResponse_ListFileInfo) Reset() { *x = ListFilesResponse_ListFileInfo{} if protoimpl.UnsafeEnabled { - mi := &file_protos_ezshare_proto_msgTypes[20] + mi := &file_protos_ezshare_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1152,7 +1248,7 @@ func (x *ListFilesResponse_ListFileInfo) String() string { func (*ListFilesResponse_ListFileInfo) ProtoMessage() {} func (x *ListFilesResponse_ListFileInfo) ProtoReflect() protoreflect.Message { - mi := &file_protos_ezshare_proto_msgTypes[20] + mi := &file_protos_ezshare_proto_msgTypes[22] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1182,6 +1278,69 @@ func (x *ListFilesResponse_ListFileInfo) GetMetadata() *File_Metadata { return nil } +type ListCertificatesResponse_CertificateInfo struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Serial string `protobuf:"bytes,1,opt,name=serial,proto3" json:"serial,omitempty"` + OwnerId string `protobuf:"bytes,2,opt,name=owner_id,json=ownerId,proto3" json:"owner_id,omitempty"` + OwnerUsername string `protobuf:"bytes,3,opt,name=owner_username,json=ownerUsername,proto3" json:"owner_username,omitempty"` +} + +func (x *ListCertificatesResponse_CertificateInfo) Reset() { + *x = ListCertificatesResponse_CertificateInfo{} + if protoimpl.UnsafeEnabled { + mi := &file_protos_ezshare_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListCertificatesResponse_CertificateInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListCertificatesResponse_CertificateInfo) ProtoMessage() {} + +func (x *ListCertificatesResponse_CertificateInfo) ProtoReflect() protoreflect.Message { + mi := &file_protos_ezshare_proto_msgTypes[23] + 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 ListCertificatesResponse_CertificateInfo.ProtoReflect.Descriptor instead. +func (*ListCertificatesResponse_CertificateInfo) Descriptor() ([]byte, []int) { + return file_protos_ezshare_proto_rawDescGZIP(), []int{19, 0} +} + +func (x *ListCertificatesResponse_CertificateInfo) GetSerial() string { + if x != nil { + return x.Serial + } + return "" +} + +func (x *ListCertificatesResponse_CertificateInfo) GetOwnerId() string { + if x != nil { + return x.OwnerId + } + return "" +} + +func (x *ListCertificatesResponse_CertificateInfo) GetOwnerUsername() string { + if x != nil { + return x.OwnerUsername + } + return "" +} + var File_protos_ezshare_proto protoreflect.FileDescriptor var file_protos_ezshare_proto_rawDesc = []byte{ @@ -1289,50 +1448,78 @@ var file_protos_ezshare_proto_rawDesc = []byte{ 0x77, 0x6f, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x6c, 0x64, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x6e, 0x65, 0x77, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6e, - 0x65, 0x77, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x32, 0xa5, 0x02, 0x0a, 0x0b, 0x46, - 0x69, 0x6c, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x47, 0x0a, 0x0a, 0x55, 0x70, - 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x1a, 0x2e, 0x65, 0x7a, 0x73, 0x68, 0x61, - 0x72, 0x65, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x65, 0x7a, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2e, 0x55, - 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x00, 0x12, 0x3e, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x17, - 0x2e, 0x65, 0x7a, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x65, 0x7a, 0x73, 0x68, 0x61, 0x72, - 0x65, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x00, 0x12, 0x47, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x46, 0x69, 0x6c, - 0x65, 0x12, 0x1a, 0x2e, 0x65, 0x7a, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, - 0x65, 0x7a, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x46, 0x69, - 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x44, 0x0a, 0x09, - 0x4c, 0x69, 0x73, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x19, 0x2e, 0x65, 0x7a, 0x73, 0x68, - 0x61, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x65, 0x7a, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x00, 0x32, 0xd9, 0x02, 0x0a, 0x0b, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x12, 0x49, 0x0a, 0x08, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x12, 0x1c, - 0x2e, 0x65, 0x7a, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, - 0x72, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x65, - 0x7a, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x55, - 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x40, 0x0a, - 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x19, 0x2e, 0x65, 0x7a, 0x73, 0x68, 0x61, 0x72, 0x65, - 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1a, 0x2e, 0x65, 0x7a, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2e, 0x4c, 0x6f, 0x67, 0x69, - 0x6e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, - 0x3f, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x19, 0x2e, 0x65, 0x7a, 0x73, 0x68, 0x61, 0x72, - 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x65, 0x7a, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, - 0x12, 0x38, 0x0a, 0x07, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x12, 0x1b, 0x2e, 0x65, 0x7a, - 0x73, 0x68, 0x61, 0x72, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x55, 0x73, 0x65, - 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0e, 0x2e, 0x65, 0x7a, 0x73, 0x68, 0x61, - 0x72, 0x65, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x42, 0x0a, 0x0e, 0x43, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x1e, 0x2e, 0x65, - 0x7a, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x73, - 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0e, 0x2e, 0x65, - 0x7a, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x42, 0x23, - 0x5a, 0x21, 0x67, 0x69, 0x74, 0x65, 0x61, 0x2e, 0x62, 0x65, 0x6e, 0x6e, 0x79, 0x2e, 0x64, 0x6f, - 0x67, 0x2f, 0x74, 0x6f, 0x72, 0x6a, 0x75, 0x73, 0x2f, 0x65, 0x7a, 0x73, 0x68, 0x61, 0x72, 0x65, - 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x77, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0xde, 0x01, 0x0a, 0x18, 0x4c, + 0x69, 0x73, 0x74, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x55, 0x0a, 0x0c, 0x63, 0x65, 0x72, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, + 0x65, 0x7a, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x2e, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x66, 0x6f, + 0x52, 0x0c, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x1a, 0x6b, + 0x0a, 0x0f, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x66, + 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, + 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x77, 0x6e, + 0x65, 0x72, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x75, 0x73, + 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6f, 0x77, + 0x6e, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x32, 0x0a, 0x18, 0x52, + 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x69, 0x61, + 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x32, + 0xa5, 0x02, 0x0a, 0x0b, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, + 0x47, 0x0a, 0x0a, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x1a, 0x2e, + 0x65, 0x7a, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, + 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x65, 0x7a, 0x73, 0x68, + 0x61, 0x72, 0x65, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3e, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x46, + 0x69, 0x6c, 0x65, 0x12, 0x17, 0x2e, 0x65, 0x7a, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2e, 0x47, 0x65, + 0x74, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x65, + 0x7a, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x47, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x1a, 0x2e, 0x65, 0x7a, 0x73, 0x68, 0x61, 0x72, 0x65, + 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x65, 0x7a, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2e, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x00, 0x12, 0x44, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x19, + 0x2e, 0x65, 0x7a, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x69, 0x6c, + 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x65, 0x7a, 0x73, 0x68, + 0x61, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x32, 0xd9, 0x02, 0x0a, 0x0b, 0x55, 0x73, 0x65, 0x72, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x49, 0x0a, 0x08, 0x52, 0x65, 0x67, 0x69, 0x73, + 0x74, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x65, 0x7a, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2e, 0x52, 0x65, + 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1d, 0x2e, 0x65, 0x7a, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2e, 0x52, 0x65, 0x67, 0x69, + 0x73, 0x74, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x00, 0x12, 0x40, 0x0a, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x19, 0x2e, 0x65, 0x7a, + 0x73, 0x68, 0x61, 0x72, 0x65, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x65, 0x7a, 0x73, 0x68, 0x61, 0x72, 0x65, + 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x3f, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x19, 0x2e, 0x65, + 0x7a, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x65, 0x7a, 0x73, 0x68, 0x61, 0x72, + 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x38, 0x0a, 0x07, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, + 0x12, 0x1b, 0x2e, 0x65, 0x7a, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x72, 0x6f, + 0x76, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0e, 0x2e, + 0x65, 0x7a, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, + 0x42, 0x0a, 0x0e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, + 0x64, 0x12, 0x1e, 0x2e, 0x65, 0x7a, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2e, 0x43, 0x68, 0x61, 0x6e, + 0x67, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x0e, 0x2e, 0x65, 0x7a, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x22, 0x00, 0x32, 0xa7, 0x01, 0x0a, 0x12, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x47, 0x0a, 0x10, 0x4c, 0x69, + 0x73, 0x74, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x0e, + 0x2e, 0x65, 0x7a, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x21, + 0x2e, 0x65, 0x7a, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x00, 0x12, 0x48, 0x0a, 0x11, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x21, 0x2e, 0x65, 0x7a, 0x73, 0x68, 0x61, + 0x72, 0x65, 0x2e, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0e, 0x2e, 0x65, 0x7a, + 0x73, 0x68, 0x61, 0x72, 0x65, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x42, 0x23, 0x5a, + 0x21, 0x67, 0x69, 0x74, 0x65, 0x61, 0x2e, 0x62, 0x65, 0x6e, 0x6e, 0x79, 0x2e, 0x64, 0x6f, 0x67, + 0x2f, 0x74, 0x6f, 0x72, 0x6a, 0x75, 0x73, 0x2f, 0x65, 0x7a, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2f, + 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1348,65 +1535,73 @@ func file_protos_ezshare_proto_rawDescGZIP() []byte { } var file_protos_ezshare_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_protos_ezshare_proto_msgTypes = make([]protoimpl.MessageInfo, 21) +var file_protos_ezshare_proto_msgTypes = make([]protoimpl.MessageInfo, 24) var file_protos_ezshare_proto_goTypes = []interface{}{ - (User_Role)(0), // 0: ezshare.User.Role - (*Empty)(nil), // 1: ezshare.Empty - (*File)(nil), // 2: ezshare.File - (*UploadFileRequest)(nil), // 3: ezshare.UploadFileRequest - (*UploadFileResponse)(nil), // 4: ezshare.UploadFileResponse - (*GetFileRequest)(nil), // 5: ezshare.GetFileRequest - (*GetFileResponse)(nil), // 6: ezshare.GetFileResponse - (*DeleteFileRequest)(nil), // 7: ezshare.DeleteFileRequest - (*DeleteFileResponse)(nil), // 8: ezshare.DeleteFileResponse - (*ListFilesRequest)(nil), // 9: ezshare.ListFilesRequest - (*ListFilesResponse)(nil), // 10: ezshare.ListFilesResponse - (*User)(nil), // 11: ezshare.User - (*RegisterUserRequest)(nil), // 12: ezshare.RegisterUserRequest - (*RegisterUserResponse)(nil), // 13: ezshare.RegisterUserResponse - (*LoginUserRequest)(nil), // 14: ezshare.LoginUserRequest - (*LoginUserResponse)(nil), // 15: ezshare.LoginUserResponse - (*ListUsersRequest)(nil), // 16: ezshare.ListUsersRequest - (*ListUsersResponse)(nil), // 17: ezshare.ListUsersResponse - (*ApproveUserRequest)(nil), // 18: ezshare.ApproveUserRequest - (*ChangePasswordRequest)(nil), // 19: ezshare.ChangePasswordRequest - (*File_Metadata)(nil), // 20: ezshare.File.Metadata - (*ListFilesResponse_ListFileInfo)(nil), // 21: ezshare.ListFilesResponse.ListFileInfo - (*timestamppb.Timestamp)(nil), // 22: google.protobuf.Timestamp + (User_Role)(0), // 0: ezshare.User.Role + (*Empty)(nil), // 1: ezshare.Empty + (*File)(nil), // 2: ezshare.File + (*UploadFileRequest)(nil), // 3: ezshare.UploadFileRequest + (*UploadFileResponse)(nil), // 4: ezshare.UploadFileResponse + (*GetFileRequest)(nil), // 5: ezshare.GetFileRequest + (*GetFileResponse)(nil), // 6: ezshare.GetFileResponse + (*DeleteFileRequest)(nil), // 7: ezshare.DeleteFileRequest + (*DeleteFileResponse)(nil), // 8: ezshare.DeleteFileResponse + (*ListFilesRequest)(nil), // 9: ezshare.ListFilesRequest + (*ListFilesResponse)(nil), // 10: ezshare.ListFilesResponse + (*User)(nil), // 11: ezshare.User + (*RegisterUserRequest)(nil), // 12: ezshare.RegisterUserRequest + (*RegisterUserResponse)(nil), // 13: ezshare.RegisterUserResponse + (*LoginUserRequest)(nil), // 14: ezshare.LoginUserRequest + (*LoginUserResponse)(nil), // 15: ezshare.LoginUserResponse + (*ListUsersRequest)(nil), // 16: ezshare.ListUsersRequest + (*ListUsersResponse)(nil), // 17: ezshare.ListUsersResponse + (*ApproveUserRequest)(nil), // 18: ezshare.ApproveUserRequest + (*ChangePasswordRequest)(nil), // 19: ezshare.ChangePasswordRequest + (*ListCertificatesResponse)(nil), // 20: ezshare.ListCertificatesResponse + (*RevokeCertificateRequest)(nil), // 21: ezshare.RevokeCertificateRequest + (*File_Metadata)(nil), // 22: ezshare.File.Metadata + (*ListFilesResponse_ListFileInfo)(nil), // 23: ezshare.ListFilesResponse.ListFileInfo + (*ListCertificatesResponse_CertificateInfo)(nil), // 24: ezshare.ListCertificatesResponse.CertificateInfo + (*timestamppb.Timestamp)(nil), // 25: google.protobuf.Timestamp } var file_protos_ezshare_proto_depIdxs = []int32{ - 20, // 0: ezshare.File.metadata:type_name -> ezshare.File.Metadata - 22, // 1: ezshare.UploadFileRequest.expires_on:type_name -> google.protobuf.Timestamp + 22, // 0: ezshare.File.metadata:type_name -> ezshare.File.Metadata + 25, // 1: ezshare.UploadFileRequest.expires_on:type_name -> google.protobuf.Timestamp 2, // 2: ezshare.GetFileResponse.file:type_name -> ezshare.File - 21, // 3: ezshare.ListFilesResponse.files:type_name -> ezshare.ListFilesResponse.ListFileInfo + 23, // 3: ezshare.ListFilesResponse.files:type_name -> ezshare.ListFilesResponse.ListFileInfo 0, // 4: ezshare.User.user_role:type_name -> ezshare.User.Role 11, // 5: ezshare.ListUsersResponse.users:type_name -> ezshare.User - 22, // 6: ezshare.File.Metadata.uploaded_on:type_name -> google.protobuf.Timestamp - 22, // 7: ezshare.File.Metadata.expires_on:type_name -> google.protobuf.Timestamp - 20, // 8: ezshare.ListFilesResponse.ListFileInfo.metadata:type_name -> ezshare.File.Metadata - 3, // 9: ezshare.FileService.UploadFile:input_type -> ezshare.UploadFileRequest - 5, // 10: ezshare.FileService.GetFile:input_type -> ezshare.GetFileRequest - 7, // 11: ezshare.FileService.DeleteFile:input_type -> ezshare.DeleteFileRequest - 9, // 12: ezshare.FileService.ListFiles:input_type -> ezshare.ListFilesRequest - 12, // 13: ezshare.UserService.Register:input_type -> ezshare.RegisterUserRequest - 14, // 14: ezshare.UserService.Login:input_type -> ezshare.LoginUserRequest - 16, // 15: ezshare.UserService.List:input_type -> ezshare.ListUsersRequest - 18, // 16: ezshare.UserService.Approve:input_type -> ezshare.ApproveUserRequest - 19, // 17: ezshare.UserService.ChangePassword:input_type -> ezshare.ChangePasswordRequest - 4, // 18: ezshare.FileService.UploadFile:output_type -> ezshare.UploadFileResponse - 6, // 19: ezshare.FileService.GetFile:output_type -> ezshare.GetFileResponse - 8, // 20: ezshare.FileService.DeleteFile:output_type -> ezshare.DeleteFileResponse - 10, // 21: ezshare.FileService.ListFiles:output_type -> ezshare.ListFilesResponse - 13, // 22: ezshare.UserService.Register:output_type -> ezshare.RegisterUserResponse - 15, // 23: ezshare.UserService.Login:output_type -> ezshare.LoginUserResponse - 17, // 24: ezshare.UserService.List:output_type -> ezshare.ListUsersResponse - 1, // 25: ezshare.UserService.Approve:output_type -> ezshare.Empty - 1, // 26: ezshare.UserService.ChangePassword:output_type -> ezshare.Empty - 18, // [18:27] is the sub-list for method output_type - 9, // [9:18] is the sub-list for method input_type - 9, // [9:9] is the sub-list for extension type_name - 9, // [9:9] is the sub-list for extension extendee - 0, // [0:9] is the sub-list for field type_name + 24, // 6: ezshare.ListCertificatesResponse.certificates:type_name -> ezshare.ListCertificatesResponse.CertificateInfo + 25, // 7: ezshare.File.Metadata.uploaded_on:type_name -> google.protobuf.Timestamp + 25, // 8: ezshare.File.Metadata.expires_on:type_name -> google.protobuf.Timestamp + 22, // 9: ezshare.ListFilesResponse.ListFileInfo.metadata:type_name -> ezshare.File.Metadata + 3, // 10: ezshare.FileService.UploadFile:input_type -> ezshare.UploadFileRequest + 5, // 11: ezshare.FileService.GetFile:input_type -> ezshare.GetFileRequest + 7, // 12: ezshare.FileService.DeleteFile:input_type -> ezshare.DeleteFileRequest + 9, // 13: ezshare.FileService.ListFiles:input_type -> ezshare.ListFilesRequest + 12, // 14: ezshare.UserService.Register:input_type -> ezshare.RegisterUserRequest + 14, // 15: ezshare.UserService.Login:input_type -> ezshare.LoginUserRequest + 16, // 16: ezshare.UserService.List:input_type -> ezshare.ListUsersRequest + 18, // 17: ezshare.UserService.Approve:input_type -> ezshare.ApproveUserRequest + 19, // 18: ezshare.UserService.ChangePassword:input_type -> ezshare.ChangePasswordRequest + 1, // 19: ezshare.CertificateService.ListCertificates:input_type -> ezshare.Empty + 21, // 20: ezshare.CertificateService.RevokeCertificate:input_type -> ezshare.RevokeCertificateRequest + 4, // 21: ezshare.FileService.UploadFile:output_type -> ezshare.UploadFileResponse + 6, // 22: ezshare.FileService.GetFile:output_type -> ezshare.GetFileResponse + 8, // 23: ezshare.FileService.DeleteFile:output_type -> ezshare.DeleteFileResponse + 10, // 24: ezshare.FileService.ListFiles:output_type -> ezshare.ListFilesResponse + 13, // 25: ezshare.UserService.Register:output_type -> ezshare.RegisterUserResponse + 15, // 26: ezshare.UserService.Login:output_type -> ezshare.LoginUserResponse + 17, // 27: ezshare.UserService.List:output_type -> ezshare.ListUsersResponse + 1, // 28: ezshare.UserService.Approve:output_type -> ezshare.Empty + 1, // 29: ezshare.UserService.ChangePassword:output_type -> ezshare.Empty + 20, // 30: ezshare.CertificateService.ListCertificates:output_type -> ezshare.ListCertificatesResponse + 1, // 31: ezshare.CertificateService.RevokeCertificate:output_type -> ezshare.Empty + 21, // [21:32] is the sub-list for method output_type + 10, // [10:21] is the sub-list for method input_type + 10, // [10:10] is the sub-list for extension type_name + 10, // [10:10] is the sub-list for extension extendee + 0, // [0:10] is the sub-list for field type_name } func init() { file_protos_ezshare_proto_init() } @@ -1644,7 +1839,7 @@ func file_protos_ezshare_proto_init() { } } file_protos_ezshare_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*File_Metadata); i { + switch v := v.(*ListCertificatesResponse); i { case 0: return &v.state case 1: @@ -1656,6 +1851,30 @@ func file_protos_ezshare_proto_init() { } } file_protos_ezshare_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RevokeCertificateRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_protos_ezshare_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*File_Metadata); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_protos_ezshare_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ListFilesResponse_ListFileInfo); i { case 0: return &v.state @@ -1667,6 +1886,18 @@ func file_protos_ezshare_proto_init() { return nil } } + file_protos_ezshare_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListCertificatesResponse_CertificateInfo); 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{ @@ -1674,9 +1905,9 @@ func file_protos_ezshare_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_protos_ezshare_proto_rawDesc, NumEnums: 1, - NumMessages: 21, + NumMessages: 24, NumExtensions: 0, - NumServices: 2, + NumServices: 3, }, GoTypes: file_protos_ezshare_proto_goTypes, DependencyIndexes: file_protos_ezshare_proto_depIdxs, diff --git a/pb/ezshare_grpc.pb.go b/pb/ezshare_grpc.pb.go index 304fb02..3f57b9c 100644 --- a/pb/ezshare_grpc.pb.go +++ b/pb/ezshare_grpc.pb.go @@ -437,3 +437,125 @@ var UserService_ServiceDesc = grpc.ServiceDesc{ Streams: []grpc.StreamDesc{}, Metadata: "protos/ezshare.proto", } + +// CertificateServiceClient is the client API for CertificateService 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 CertificateServiceClient interface { + ListCertificates(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ListCertificatesResponse, error) + RevokeCertificate(ctx context.Context, in *RevokeCertificateRequest, opts ...grpc.CallOption) (*Empty, error) +} + +type certificateServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewCertificateServiceClient(cc grpc.ClientConnInterface) CertificateServiceClient { + return &certificateServiceClient{cc} +} + +func (c *certificateServiceClient) ListCertificates(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ListCertificatesResponse, error) { + out := new(ListCertificatesResponse) + err := c.cc.Invoke(ctx, "/ezshare.CertificateService/ListCertificates", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *certificateServiceClient) RevokeCertificate(ctx context.Context, in *RevokeCertificateRequest, opts ...grpc.CallOption) (*Empty, error) { + out := new(Empty) + err := c.cc.Invoke(ctx, "/ezshare.CertificateService/RevokeCertificate", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// CertificateServiceServer is the server API for CertificateService service. +// All implementations must embed UnimplementedCertificateServiceServer +// for forward compatibility +type CertificateServiceServer interface { + ListCertificates(context.Context, *Empty) (*ListCertificatesResponse, error) + RevokeCertificate(context.Context, *RevokeCertificateRequest) (*Empty, error) + mustEmbedUnimplementedCertificateServiceServer() +} + +// UnimplementedCertificateServiceServer must be embedded to have forward compatible implementations. +type UnimplementedCertificateServiceServer struct { +} + +func (UnimplementedCertificateServiceServer) ListCertificates(context.Context, *Empty) (*ListCertificatesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ListCertificates not implemented") +} +func (UnimplementedCertificateServiceServer) RevokeCertificate(context.Context, *RevokeCertificateRequest) (*Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method RevokeCertificate not implemented") +} +func (UnimplementedCertificateServiceServer) mustEmbedUnimplementedCertificateServiceServer() {} + +// UnsafeCertificateServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to CertificateServiceServer will +// result in compilation errors. +type UnsafeCertificateServiceServer interface { + mustEmbedUnimplementedCertificateServiceServer() +} + +func RegisterCertificateServiceServer(s grpc.ServiceRegistrar, srv CertificateServiceServer) { + s.RegisterService(&CertificateService_ServiceDesc, srv) +} + +func _CertificateService_ListCertificates_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(CertificateServiceServer).ListCertificates(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/ezshare.CertificateService/ListCertificates", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(CertificateServiceServer).ListCertificates(ctx, req.(*Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _CertificateService_RevokeCertificate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RevokeCertificateRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(CertificateServiceServer).RevokeCertificate(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/ezshare.CertificateService/RevokeCertificate", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(CertificateServiceServer).RevokeCertificate(ctx, req.(*RevokeCertificateRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// CertificateService_ServiceDesc is the grpc.ServiceDesc for CertificateService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var CertificateService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "ezshare.CertificateService", + HandlerType: (*CertificateServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "ListCertificates", + Handler: _CertificateService_ListCertificates_Handler, + }, + { + MethodName: "RevokeCertificate", + Handler: _CertificateService_RevokeCertificate_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "protos/ezshare.proto", +} diff --git a/protos/ezshare.proto b/protos/ezshare.proto index 427dd70..bcc680a 100644 --- a/protos/ezshare.proto +++ b/protos/ezshare.proto @@ -135,3 +135,27 @@ service UserService { rpc Approve(ApproveUserRequest) returns (Empty) {} rpc ChangePassword(ChangePasswordRequest) returns (Empty) {} } + +/////////////////////////////// +// Certificate related stuff // +/////////////////////////////// + +// List +message ListCertificatesResponse { + message CertificateInfo { + string serial = 1; + string owner_id = 2; + string owner_username = 3; + } + repeated CertificateInfo certificates = 1; +} + +// Revoke +message RevokeCertificateRequest { + string serial = 1; +} + +service CertificateService { + rpc ListCertificates(Empty) returns (ListCertificatesResponse) {} + rpc RevokeCertificate(RevokeCertificateRequest) returns (Empty) {} +} \ No newline at end of file diff --git a/server/certservice.go b/server/certservice.go new file mode 100644 index 0000000..f91fc38 --- /dev/null +++ b/server/certservice.go @@ -0,0 +1,86 @@ +package server + +import ( + "context" + + "gitea.benny.dog/torjus/ezshare/certs" + "gitea.benny.dog/torjus/ezshare/pb" + "gitea.benny.dog/torjus/ezshare/server/interceptors" + "gitea.benny.dog/torjus/ezshare/store" + "go.uber.org/zap" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +type CertServiceServer struct { + Logger *zap.SugaredLogger + svc *certs.CertService + store store.CertificateStore + userStore store.UserStore + pb.UnimplementedCertificateServiceServer +} + +func NewCertServiceServer(svc *certs.CertService, store store.CertificateStore, userStore store.UserStore) *CertServiceServer { + return &CertServiceServer{ + Logger: zap.NewNop().Sugar(), + svc: svc, + store: store, + userStore: userStore, + } +} + +func (s *CertServiceServer) ListCertificates(ctx context.Context, _ *pb.Empty) (*pb.ListCertificatesResponse, error) { + allCerts, err := s.store.ListCertificates() + if err != nil { + s.Logger.Warnw("Error listing certificates.", "error", err) + return nil, status.Error(codes.Internal, "error fetching certificates") + } + + user := interceptors.UserIDFromContext(ctx) + role := interceptors.RoleFromContext(ctx) + + var certInfos []*pb.ListCertificatesResponse_CertificateInfo + + for _, serial := range allCerts { + cert, err := s.store.GetCertificate(serial) + if err != nil { + s.Logger.Warnw("Error getting certificate.", "error", err) + return nil, status.Error(codes.Internal, "error fetching certificates") + } + owner, err := s.userStore.GetUser(cert.Subject.CommonName) + if err != nil { + s.Logger.Warnw("Error getting user.", "error", err) + return nil, status.Error(codes.Internal, "error fetching certificate owners") + } + if cert.Subject.CommonName == user || role == pb.User_ADMIN { + info := &pb.ListCertificatesResponse_CertificateInfo{ + Serial: serial, + OwnerId: cert.Subject.CommonName, + OwnerUsername: owner.Username, + } + certInfos = append(certInfos, info) + } + } + + return &pb.ListCertificatesResponse{Certificates: certInfos}, nil +} + +func (s *CertServiceServer) RevokeCertificate(ctx context.Context, req *pb.RevokeCertificateRequest) (*pb.Empty, error) { + user := interceptors.UserIDFromContext(ctx) + role := interceptors.RoleFromContext(ctx) + cert, err := s.store.GetCertificate(req.Serial) + if err != nil { + return nil, status.Error(codes.Internal, "error fetching certificate") + } + + if user == cert.Subject.CommonName || role == pb.User_ADMIN { + if err := s.store.Revoke(req.Serial); err != nil { + s.Logger.Warnw("Error revoking certificate.", "error", err) + return nil, status.Error(codes.Internal, "error revoking certificate") + } + s.Logger.Infow("Revoked certificate.", "serial", req.Serial, "requested_by", user) + return &pb.Empty{}, nil + } + + return nil, status.Error(codes.PermissionDenied, "permission denied") +} diff --git a/store/bolt.go b/store/bolt.go index 5c33ef5..fe44a71 100644 --- a/store/bolt.go +++ b/store/bolt.go @@ -132,12 +132,12 @@ func (s *BoltStore) ListFiles() ([]*pb.ListFilesResponse_ListFileInfo, error) { // Certificate store var _ CertificateStore = &BoltStore{} -func (s *BoltStore) GetCertificate(id string) (*x509.Certificate, error) { +func (s *BoltStore) GetCertificate(serial string) (*x509.Certificate, error) { var raw []byte err := s.db.View(func(t *bolt.Tx) error { bkt := t.Bucket(bktKeyCerts) - raw = bkt.Get([]byte(id)) + raw = bkt.Get([]byte(serial)) return nil }) if err != nil { @@ -155,13 +155,13 @@ func (s *BoltStore) GetCertificate(id string) (*x509.Certificate, error) { return cert, nil } -func (s *BoltStore) StoreCertificate(id string, cert *x509.Certificate) error { +func (s *BoltStore) StoreCertificate(cert *x509.Certificate) error { data := make([]byte, len(cert.Raw)) copy(data, cert.Raw) return s.db.Update(func(t *bolt.Tx) error { bkt := t.Bucket(bktKeyCerts) - return bkt.Put([]byte(id), cert.Raw) + return bkt.Put([]byte(cert.SerialNumber.String()), cert.Raw) }) } diff --git a/store/memory.go b/store/memory.go index eeaa617..9a095fb 100644 --- a/store/memory.go +++ b/store/memory.go @@ -91,11 +91,11 @@ func (s *MemoryStore) ListFiles() ([]*pb.ListFilesResponse_ListFileInfo, error) var _ CertificateStore = &MemoryStore{} -func (s *MemoryStore) GetCertificate(id string) (*x509.Certificate, error) { +func (s *MemoryStore) GetCertificate(serial string) (*x509.Certificate, error) { s.certLock.Lock() defer s.certLock.Unlock() - data, ok := s.certs[id] + data, ok := s.certs[serial] if !ok { // TODO: Make separate error, or rename error return nil, ErrNoSuchItem @@ -104,7 +104,7 @@ func (s *MemoryStore) GetCertificate(id string) (*x509.Certificate, error) { return x509.ParseCertificate(data) } -func (s *MemoryStore) StoreCertificate(id string, cert *x509.Certificate) error { +func (s *MemoryStore) StoreCertificate(cert *x509.Certificate) error { s.certLock.Lock() defer s.certLock.Unlock() @@ -112,7 +112,7 @@ func (s *MemoryStore) StoreCertificate(id string, cert *x509.Certificate) error data := make([]byte, len(cert.Raw)) copy(data, cert.Raw) - s.certs[id] = data + s.certs[cert.SerialNumber.String()] = data return nil } diff --git a/store/store.go b/store/store.go index d2d0873..3ae3ad9 100644 --- a/store/store.go +++ b/store/store.go @@ -18,8 +18,8 @@ type FileStore interface { } type CertificateStore interface { - GetCertificate(id string) (*x509.Certificate, error) - StoreCertificate(id string, cert *x509.Certificate) error + GetCertificate(serial string) (*x509.Certificate, error) + StoreCertificate(cert *x509.Certificate) error GetKey(id string) (*ecdsa.PrivateKey, error) StoreKey(id string, key *ecdsa.PrivateKey) error ListCertificates() ([]string, error) diff --git a/store/store_test.go b/store/store_test.go index 2b5c199..43c1616 100644 --- a/store/store_test.go +++ b/store/store_test.go @@ -106,7 +106,7 @@ func doCertificateStoreTest(s store.CertificateStore, t *testing.T) { } // Store cert - if err := s.StoreCertificate("cert", cert); err != nil { + if err := s.StoreCertificate(cert); err != nil { t.Fatalf("Error storing cert: %s", err) } @@ -123,11 +123,11 @@ func doCertificateStoreTest(s store.CertificateStore, t *testing.T) { if len(ids) != 1 { t.Fatalf("List has wrong length: %s", err) } - if ids[0] != "cert" { + if ids[0] != cert.SerialNumber.String() { t.Fatalf("List has wrong id") } - retrievedCert, err := s.GetCertificate("cert") + retrievedCert, err := s.GetCertificate(cert.SerialNumber.String()) if err != nil { t.Fatalf("Unable to get certificate from store: %s", err) }