Add grpcserver test coverage

- Add comprehensive test file for internal/grpcserver package
- Cover interceptors, system, engine, policy, and auth handlers
- Cover pbToRule/ruleToPB conversion helpers
- 37 tests total; CA/PKI/ACME and Login/Logout skipped (require live deps)

Co-authored-by: Junie <junie@jetbrains.com>
This commit is contained in:
2026-03-15 13:07:42 -07:00
parent ad167aed9b
commit 8215aaccc5
40 changed files with 8865 additions and 519 deletions

View File

@@ -0,0 +1,16 @@
[2026-03-15 11:53] - Updated by Junie
{
"TYPE": "correction",
"CATEGORY": "gRPC config",
"EXPECTATION": "Use only the v2 gRPC server configuration and remove v1 config paths/fields.",
"NEW INSTRUCTION": "WHEN editing gRPC server configuration THEN remove v1 config and use only v2 fields"
}
[2026-03-15 13:02] - Updated by Junie
{
"TYPE": "correction",
"CATEGORY": "gRPC config",
"EXPECTATION": "Use only the v2 gRPC server configuration and remove v1 config paths/fields.",
"NEW INSTRUCTION": "WHEN editing gRPC server configuration THEN remove v1 config and use only v2 fields"
}

View File

@@ -1 +1 @@
[{"lang":"en","usageCount":20}] [{"lang":"en","usageCount":32}]

666
gen/metacrypt/v2/acme.pb.go Normal file
View File

@@ -0,0 +1,666 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc v3.20.3
// source: proto/metacrypt/v2/acme.proto
package metacryptv2
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
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 CreateEABRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
Mount string `protobuf:"bytes,1,opt,name=mount,proto3" json:"mount,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *CreateEABRequest) Reset() {
*x = CreateEABRequest{}
mi := &file_proto_metacrypt_v2_acme_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *CreateEABRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CreateEABRequest) ProtoMessage() {}
func (x *CreateEABRequest) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_acme_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CreateEABRequest.ProtoReflect.Descriptor instead.
func (*CreateEABRequest) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_acme_proto_rawDescGZIP(), []int{0}
}
func (x *CreateEABRequest) GetMount() string {
if x != nil {
return x.Mount
}
return ""
}
type CreateEABResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
// kid is the key identifier to pass to the ACME client.
Kid string `protobuf:"bytes,1,opt,name=kid,proto3" json:"kid,omitempty"`
// hmac_key is the raw 32-byte HMAC-SHA256 key.
// Base64url-encode this value when configuring an ACME client.
HmacKey []byte `protobuf:"bytes,2,opt,name=hmac_key,json=hmacKey,proto3" json:"hmac_key,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *CreateEABResponse) Reset() {
*x = CreateEABResponse{}
mi := &file_proto_metacrypt_v2_acme_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *CreateEABResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CreateEABResponse) ProtoMessage() {}
func (x *CreateEABResponse) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_acme_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CreateEABResponse.ProtoReflect.Descriptor instead.
func (*CreateEABResponse) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_acme_proto_rawDescGZIP(), []int{1}
}
func (x *CreateEABResponse) GetKid() string {
if x != nil {
return x.Kid
}
return ""
}
func (x *CreateEABResponse) GetHmacKey() []byte {
if x != nil {
return x.HmacKey
}
return nil
}
type SetConfigRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
Mount string `protobuf:"bytes,1,opt,name=mount,proto3" json:"mount,omitempty"`
// default_issuer is the name of the CA issuer to use for ACME certificates.
// The issuer must already exist on the CA mount.
DefaultIssuer string `protobuf:"bytes,2,opt,name=default_issuer,json=defaultIssuer,proto3" json:"default_issuer,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *SetConfigRequest) Reset() {
*x = SetConfigRequest{}
mi := &file_proto_metacrypt_v2_acme_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *SetConfigRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SetConfigRequest) ProtoMessage() {}
func (x *SetConfigRequest) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_acme_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use SetConfigRequest.ProtoReflect.Descriptor instead.
func (*SetConfigRequest) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_acme_proto_rawDescGZIP(), []int{2}
}
func (x *SetConfigRequest) GetMount() string {
if x != nil {
return x.Mount
}
return ""
}
func (x *SetConfigRequest) GetDefaultIssuer() string {
if x != nil {
return x.DefaultIssuer
}
return ""
}
type SetConfigResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *SetConfigResponse) Reset() {
*x = SetConfigResponse{}
mi := &file_proto_metacrypt_v2_acme_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *SetConfigResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SetConfigResponse) ProtoMessage() {}
func (x *SetConfigResponse) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_acme_proto_msgTypes[3]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use SetConfigResponse.ProtoReflect.Descriptor instead.
func (*SetConfigResponse) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_acme_proto_rawDescGZIP(), []int{3}
}
type ListAccountsRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
Mount string `protobuf:"bytes,1,opt,name=mount,proto3" json:"mount,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ListAccountsRequest) Reset() {
*x = ListAccountsRequest{}
mi := &file_proto_metacrypt_v2_acme_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListAccountsRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListAccountsRequest) ProtoMessage() {}
func (x *ListAccountsRequest) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_acme_proto_msgTypes[4]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ListAccountsRequest.ProtoReflect.Descriptor instead.
func (*ListAccountsRequest) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_acme_proto_rawDescGZIP(), []int{4}
}
func (x *ListAccountsRequest) GetMount() string {
if x != nil {
return x.Mount
}
return ""
}
type ListAccountsResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
Accounts []*ACMEAccount `protobuf:"bytes,1,rep,name=accounts,proto3" json:"accounts,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ListAccountsResponse) Reset() {
*x = ListAccountsResponse{}
mi := &file_proto_metacrypt_v2_acme_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListAccountsResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListAccountsResponse) ProtoMessage() {}
func (x *ListAccountsResponse) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_acme_proto_msgTypes[5]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ListAccountsResponse.ProtoReflect.Descriptor instead.
func (*ListAccountsResponse) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_acme_proto_rawDescGZIP(), []int{5}
}
func (x *ListAccountsResponse) GetAccounts() []*ACMEAccount {
if x != nil {
return x.Accounts
}
return nil
}
type ACMEAccount struct {
state protoimpl.MessageState `protogen:"open.v1"`
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
Status string `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"`
Contact []string `protobuf:"bytes,3,rep,name=contact,proto3" json:"contact,omitempty"`
MciasUsername string `protobuf:"bytes,4,opt,name=mcias_username,json=mciasUsername,proto3" json:"mcias_username,omitempty"`
CreatedAt *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ACMEAccount) Reset() {
*x = ACMEAccount{}
mi := &file_proto_metacrypt_v2_acme_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ACMEAccount) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ACMEAccount) ProtoMessage() {}
func (x *ACMEAccount) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_acme_proto_msgTypes[6]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ACMEAccount.ProtoReflect.Descriptor instead.
func (*ACMEAccount) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_acme_proto_rawDescGZIP(), []int{6}
}
func (x *ACMEAccount) GetId() string {
if x != nil {
return x.Id
}
return ""
}
func (x *ACMEAccount) GetStatus() string {
if x != nil {
return x.Status
}
return ""
}
func (x *ACMEAccount) GetContact() []string {
if x != nil {
return x.Contact
}
return nil
}
func (x *ACMEAccount) GetMciasUsername() string {
if x != nil {
return x.MciasUsername
}
return ""
}
func (x *ACMEAccount) GetCreatedAt() *timestamppb.Timestamp {
if x != nil {
return x.CreatedAt
}
return nil
}
type ListOrdersRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
Mount string `protobuf:"bytes,1,opt,name=mount,proto3" json:"mount,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ListOrdersRequest) Reset() {
*x = ListOrdersRequest{}
mi := &file_proto_metacrypt_v2_acme_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListOrdersRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListOrdersRequest) ProtoMessage() {}
func (x *ListOrdersRequest) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_acme_proto_msgTypes[7]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ListOrdersRequest.ProtoReflect.Descriptor instead.
func (*ListOrdersRequest) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_acme_proto_rawDescGZIP(), []int{7}
}
func (x *ListOrdersRequest) GetMount() string {
if x != nil {
return x.Mount
}
return ""
}
type ListOrdersResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
Orders []*ACMEOrder `protobuf:"bytes,1,rep,name=orders,proto3" json:"orders,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ListOrdersResponse) Reset() {
*x = ListOrdersResponse{}
mi := &file_proto_metacrypt_v2_acme_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListOrdersResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListOrdersResponse) ProtoMessage() {}
func (x *ListOrdersResponse) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_acme_proto_msgTypes[8]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ListOrdersResponse.ProtoReflect.Descriptor instead.
func (*ListOrdersResponse) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_acme_proto_rawDescGZIP(), []int{8}
}
func (x *ListOrdersResponse) GetOrders() []*ACMEOrder {
if x != nil {
return x.Orders
}
return nil
}
type ACMEOrder struct {
state protoimpl.MessageState `protogen:"open.v1"`
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
AccountId string `protobuf:"bytes,2,opt,name=account_id,json=accountId,proto3" json:"account_id,omitempty"`
Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"`
// identifiers are in "type:value" format, e.g. "dns:example.com".
Identifiers []string `protobuf:"bytes,4,rep,name=identifiers,proto3" json:"identifiers,omitempty"`
CreatedAt *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
ExpiresAt *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=expires_at,json=expiresAt,proto3" json:"expires_at,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ACMEOrder) Reset() {
*x = ACMEOrder{}
mi := &file_proto_metacrypt_v2_acme_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ACMEOrder) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ACMEOrder) ProtoMessage() {}
func (x *ACMEOrder) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_acme_proto_msgTypes[9]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ACMEOrder.ProtoReflect.Descriptor instead.
func (*ACMEOrder) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_acme_proto_rawDescGZIP(), []int{9}
}
func (x *ACMEOrder) GetId() string {
if x != nil {
return x.Id
}
return ""
}
func (x *ACMEOrder) GetAccountId() string {
if x != nil {
return x.AccountId
}
return ""
}
func (x *ACMEOrder) GetStatus() string {
if x != nil {
return x.Status
}
return ""
}
func (x *ACMEOrder) GetIdentifiers() []string {
if x != nil {
return x.Identifiers
}
return nil
}
func (x *ACMEOrder) GetCreatedAt() *timestamppb.Timestamp {
if x != nil {
return x.CreatedAt
}
return nil
}
func (x *ACMEOrder) GetExpiresAt() *timestamppb.Timestamp {
if x != nil {
return x.ExpiresAt
}
return nil
}
var File_proto_metacrypt_v2_acme_proto protoreflect.FileDescriptor
const file_proto_metacrypt_v2_acme_proto_rawDesc = "" +
"\n" +
"\x1dproto/metacrypt/v2/acme.proto\x12\fmetacrypt.v2\x1a\x1fgoogle/protobuf/timestamp.proto\"(\n" +
"\x10CreateEABRequest\x12\x14\n" +
"\x05mount\x18\x01 \x01(\tR\x05mount\"@\n" +
"\x11CreateEABResponse\x12\x10\n" +
"\x03kid\x18\x01 \x01(\tR\x03kid\x12\x19\n" +
"\bhmac_key\x18\x02 \x01(\fR\ahmacKey\"O\n" +
"\x10SetConfigRequest\x12\x14\n" +
"\x05mount\x18\x01 \x01(\tR\x05mount\x12%\n" +
"\x0edefault_issuer\x18\x02 \x01(\tR\rdefaultIssuer\"\x13\n" +
"\x11SetConfigResponse\"+\n" +
"\x13ListAccountsRequest\x12\x14\n" +
"\x05mount\x18\x01 \x01(\tR\x05mount\"M\n" +
"\x14ListAccountsResponse\x125\n" +
"\baccounts\x18\x01 \x03(\v2\x19.metacrypt.v2.ACMEAccountR\baccounts\"\xb1\x01\n" +
"\vACMEAccount\x12\x0e\n" +
"\x02id\x18\x01 \x01(\tR\x02id\x12\x16\n" +
"\x06status\x18\x02 \x01(\tR\x06status\x12\x18\n" +
"\acontact\x18\x03 \x03(\tR\acontact\x12%\n" +
"\x0emcias_username\x18\x04 \x01(\tR\rmciasUsername\x129\n" +
"\n" +
"created_at\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampR\tcreatedAt\")\n" +
"\x11ListOrdersRequest\x12\x14\n" +
"\x05mount\x18\x01 \x01(\tR\x05mount\"E\n" +
"\x12ListOrdersResponse\x12/\n" +
"\x06orders\x18\x01 \x03(\v2\x17.metacrypt.v2.ACMEOrderR\x06orders\"\xea\x01\n" +
"\tACMEOrder\x12\x0e\n" +
"\x02id\x18\x01 \x01(\tR\x02id\x12\x1d\n" +
"\n" +
"account_id\x18\x02 \x01(\tR\taccountId\x12\x16\n" +
"\x06status\x18\x03 \x01(\tR\x06status\x12 \n" +
"\videntifiers\x18\x04 \x03(\tR\videntifiers\x129\n" +
"\n" +
"created_at\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampR\tcreatedAt\x129\n" +
"\n" +
"expires_at\x18\x06 \x01(\v2\x1a.google.protobuf.TimestampR\texpiresAt2\xd1\x02\n" +
"\vACMEService\x12L\n" +
"\tCreateEAB\x12\x1e.metacrypt.v2.CreateEABRequest\x1a\x1f.metacrypt.v2.CreateEABResponse\x12L\n" +
"\tSetConfig\x12\x1e.metacrypt.v2.SetConfigRequest\x1a\x1f.metacrypt.v2.SetConfigResponse\x12U\n" +
"\fListAccounts\x12!.metacrypt.v2.ListAccountsRequest\x1a\".metacrypt.v2.ListAccountsResponse\x12O\n" +
"\n" +
"ListOrders\x12\x1f.metacrypt.v2.ListOrdersRequest\x1a .metacrypt.v2.ListOrdersResponseB>Z<git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v2;metacryptv2b\x06proto3"
var (
file_proto_metacrypt_v2_acme_proto_rawDescOnce sync.Once
file_proto_metacrypt_v2_acme_proto_rawDescData []byte
)
func file_proto_metacrypt_v2_acme_proto_rawDescGZIP() []byte {
file_proto_metacrypt_v2_acme_proto_rawDescOnce.Do(func() {
file_proto_metacrypt_v2_acme_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_proto_metacrypt_v2_acme_proto_rawDesc), len(file_proto_metacrypt_v2_acme_proto_rawDesc)))
})
return file_proto_metacrypt_v2_acme_proto_rawDescData
}
var file_proto_metacrypt_v2_acme_proto_msgTypes = make([]protoimpl.MessageInfo, 10)
var file_proto_metacrypt_v2_acme_proto_goTypes = []any{
(*CreateEABRequest)(nil), // 0: metacrypt.v2.CreateEABRequest
(*CreateEABResponse)(nil), // 1: metacrypt.v2.CreateEABResponse
(*SetConfigRequest)(nil), // 2: metacrypt.v2.SetConfigRequest
(*SetConfigResponse)(nil), // 3: metacrypt.v2.SetConfigResponse
(*ListAccountsRequest)(nil), // 4: metacrypt.v2.ListAccountsRequest
(*ListAccountsResponse)(nil), // 5: metacrypt.v2.ListAccountsResponse
(*ACMEAccount)(nil), // 6: metacrypt.v2.ACMEAccount
(*ListOrdersRequest)(nil), // 7: metacrypt.v2.ListOrdersRequest
(*ListOrdersResponse)(nil), // 8: metacrypt.v2.ListOrdersResponse
(*ACMEOrder)(nil), // 9: metacrypt.v2.ACMEOrder
(*timestamppb.Timestamp)(nil), // 10: google.protobuf.Timestamp
}
var file_proto_metacrypt_v2_acme_proto_depIdxs = []int32{
6, // 0: metacrypt.v2.ListAccountsResponse.accounts:type_name -> metacrypt.v2.ACMEAccount
10, // 1: metacrypt.v2.ACMEAccount.created_at:type_name -> google.protobuf.Timestamp
9, // 2: metacrypt.v2.ListOrdersResponse.orders:type_name -> metacrypt.v2.ACMEOrder
10, // 3: metacrypt.v2.ACMEOrder.created_at:type_name -> google.protobuf.Timestamp
10, // 4: metacrypt.v2.ACMEOrder.expires_at:type_name -> google.protobuf.Timestamp
0, // 5: metacrypt.v2.ACMEService.CreateEAB:input_type -> metacrypt.v2.CreateEABRequest
2, // 6: metacrypt.v2.ACMEService.SetConfig:input_type -> metacrypt.v2.SetConfigRequest
4, // 7: metacrypt.v2.ACMEService.ListAccounts:input_type -> metacrypt.v2.ListAccountsRequest
7, // 8: metacrypt.v2.ACMEService.ListOrders:input_type -> metacrypt.v2.ListOrdersRequest
1, // 9: metacrypt.v2.ACMEService.CreateEAB:output_type -> metacrypt.v2.CreateEABResponse
3, // 10: metacrypt.v2.ACMEService.SetConfig:output_type -> metacrypt.v2.SetConfigResponse
5, // 11: metacrypt.v2.ACMEService.ListAccounts:output_type -> metacrypt.v2.ListAccountsResponse
8, // 12: metacrypt.v2.ACMEService.ListOrders:output_type -> metacrypt.v2.ListOrdersResponse
9, // [9:13] is the sub-list for method output_type
5, // [5:9] is the sub-list for method input_type
5, // [5:5] is the sub-list for extension type_name
5, // [5:5] is the sub-list for extension extendee
0, // [0:5] is the sub-list for field type_name
}
func init() { file_proto_metacrypt_v2_acme_proto_init() }
func file_proto_metacrypt_v2_acme_proto_init() {
if File_proto_metacrypt_v2_acme_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_metacrypt_v2_acme_proto_rawDesc), len(file_proto_metacrypt_v2_acme_proto_rawDesc)),
NumEnums: 0,
NumMessages: 10,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_proto_metacrypt_v2_acme_proto_goTypes,
DependencyIndexes: file_proto_metacrypt_v2_acme_proto_depIdxs,
MessageInfos: file_proto_metacrypt_v2_acme_proto_msgTypes,
}.Build()
File_proto_metacrypt_v2_acme_proto = out.File
file_proto_metacrypt_v2_acme_proto_goTypes = nil
file_proto_metacrypt_v2_acme_proto_depIdxs = nil
}

View File

@@ -0,0 +1,259 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.6.1
// - protoc v3.20.3
// source: proto/metacrypt/v2/acme.proto
package metacryptv2
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.64.0 or later.
const _ = grpc.SupportPackageIsVersion9
const (
ACMEService_CreateEAB_FullMethodName = "/metacrypt.v2.ACMEService/CreateEAB"
ACMEService_SetConfig_FullMethodName = "/metacrypt.v2.ACMEService/SetConfig"
ACMEService_ListAccounts_FullMethodName = "/metacrypt.v2.ACMEService/ListAccounts"
ACMEService_ListOrders_FullMethodName = "/metacrypt.v2.ACMEService/ListOrders"
)
// ACMEServiceClient is the client API for ACMEService 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.
//
// ACMEService provides authenticated management of ACME state.
// These RPCs correspond to the REST management endpoints at /v2/acme/{mount}/.
// The ACME protocol endpoints themselves (/acme/{mount}/...) are HTTP-only
// per RFC 8555 and have no gRPC equivalents.
type ACMEServiceClient interface {
// CreateEAB creates External Account Binding credentials for the
// authenticated MCIAS user. The returned kid and hmac_key are used
// with any RFC 8555-compliant ACME client to register an account.
CreateEAB(ctx context.Context, in *CreateEABRequest, opts ...grpc.CallOption) (*CreateEABResponse, error)
// SetConfig sets the ACME configuration for a CA mount.
// Currently configures the default issuer used for ACME certificate issuance.
SetConfig(ctx context.Context, in *SetConfigRequest, opts ...grpc.CallOption) (*SetConfigResponse, error)
// ListAccounts returns all ACME accounts for a CA mount. Admin only.
ListAccounts(ctx context.Context, in *ListAccountsRequest, opts ...grpc.CallOption) (*ListAccountsResponse, error)
// ListOrders returns all ACME orders for a CA mount. Admin only.
ListOrders(ctx context.Context, in *ListOrdersRequest, opts ...grpc.CallOption) (*ListOrdersResponse, error)
}
type aCMEServiceClient struct {
cc grpc.ClientConnInterface
}
func NewACMEServiceClient(cc grpc.ClientConnInterface) ACMEServiceClient {
return &aCMEServiceClient{cc}
}
func (c *aCMEServiceClient) CreateEAB(ctx context.Context, in *CreateEABRequest, opts ...grpc.CallOption) (*CreateEABResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(CreateEABResponse)
err := c.cc.Invoke(ctx, ACMEService_CreateEAB_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *aCMEServiceClient) SetConfig(ctx context.Context, in *SetConfigRequest, opts ...grpc.CallOption) (*SetConfigResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(SetConfigResponse)
err := c.cc.Invoke(ctx, ACMEService_SetConfig_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *aCMEServiceClient) ListAccounts(ctx context.Context, in *ListAccountsRequest, opts ...grpc.CallOption) (*ListAccountsResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ListAccountsResponse)
err := c.cc.Invoke(ctx, ACMEService_ListAccounts_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *aCMEServiceClient) ListOrders(ctx context.Context, in *ListOrdersRequest, opts ...grpc.CallOption) (*ListOrdersResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ListOrdersResponse)
err := c.cc.Invoke(ctx, ACMEService_ListOrders_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// ACMEServiceServer is the server API for ACMEService service.
// All implementations must embed UnimplementedACMEServiceServer
// for forward compatibility.
//
// ACMEService provides authenticated management of ACME state.
// These RPCs correspond to the REST management endpoints at /v2/acme/{mount}/.
// The ACME protocol endpoints themselves (/acme/{mount}/...) are HTTP-only
// per RFC 8555 and have no gRPC equivalents.
type ACMEServiceServer interface {
// CreateEAB creates External Account Binding credentials for the
// authenticated MCIAS user. The returned kid and hmac_key are used
// with any RFC 8555-compliant ACME client to register an account.
CreateEAB(context.Context, *CreateEABRequest) (*CreateEABResponse, error)
// SetConfig sets the ACME configuration for a CA mount.
// Currently configures the default issuer used for ACME certificate issuance.
SetConfig(context.Context, *SetConfigRequest) (*SetConfigResponse, error)
// ListAccounts returns all ACME accounts for a CA mount. Admin only.
ListAccounts(context.Context, *ListAccountsRequest) (*ListAccountsResponse, error)
// ListOrders returns all ACME orders for a CA mount. Admin only.
ListOrders(context.Context, *ListOrdersRequest) (*ListOrdersResponse, error)
mustEmbedUnimplementedACMEServiceServer()
}
// UnimplementedACMEServiceServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedACMEServiceServer struct{}
func (UnimplementedACMEServiceServer) CreateEAB(context.Context, *CreateEABRequest) (*CreateEABResponse, error) {
return nil, status.Error(codes.Unimplemented, "method CreateEAB not implemented")
}
func (UnimplementedACMEServiceServer) SetConfig(context.Context, *SetConfigRequest) (*SetConfigResponse, error) {
return nil, status.Error(codes.Unimplemented, "method SetConfig not implemented")
}
func (UnimplementedACMEServiceServer) ListAccounts(context.Context, *ListAccountsRequest) (*ListAccountsResponse, error) {
return nil, status.Error(codes.Unimplemented, "method ListAccounts not implemented")
}
func (UnimplementedACMEServiceServer) ListOrders(context.Context, *ListOrdersRequest) (*ListOrdersResponse, error) {
return nil, status.Error(codes.Unimplemented, "method ListOrders not implemented")
}
func (UnimplementedACMEServiceServer) mustEmbedUnimplementedACMEServiceServer() {}
func (UnimplementedACMEServiceServer) testEmbeddedByValue() {}
// UnsafeACMEServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to ACMEServiceServer will
// result in compilation errors.
type UnsafeACMEServiceServer interface {
mustEmbedUnimplementedACMEServiceServer()
}
func RegisterACMEServiceServer(s grpc.ServiceRegistrar, srv ACMEServiceServer) {
// If the following call panics, it indicates UnimplementedACMEServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&ACMEService_ServiceDesc, srv)
}
func _ACMEService_CreateEAB_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CreateEABRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ACMEServiceServer).CreateEAB(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: ACMEService_CreateEAB_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ACMEServiceServer).CreateEAB(ctx, req.(*CreateEABRequest))
}
return interceptor(ctx, in, info, handler)
}
func _ACMEService_SetConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(SetConfigRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ACMEServiceServer).SetConfig(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: ACMEService_SetConfig_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ACMEServiceServer).SetConfig(ctx, req.(*SetConfigRequest))
}
return interceptor(ctx, in, info, handler)
}
func _ACMEService_ListAccounts_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListAccountsRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ACMEServiceServer).ListAccounts(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: ACMEService_ListAccounts_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ACMEServiceServer).ListAccounts(ctx, req.(*ListAccountsRequest))
}
return interceptor(ctx, in, info, handler)
}
func _ACMEService_ListOrders_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListOrdersRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ACMEServiceServer).ListOrders(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: ACMEService_ListOrders_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ACMEServiceServer).ListOrders(ctx, req.(*ListOrdersRequest))
}
return interceptor(ctx, in, info, handler)
}
// ACMEService_ServiceDesc is the grpc.ServiceDesc for ACMEService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var ACMEService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "metacrypt.v2.ACMEService",
HandlerType: (*ACMEServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "CreateEAB",
Handler: _ACMEService_CreateEAB_Handler,
},
{
MethodName: "SetConfig",
Handler: _ACMEService_SetConfig_Handler,
},
{
MethodName: "ListAccounts",
Handler: _ACMEService_ListAccounts_Handler,
},
{
MethodName: "ListOrders",
Handler: _ACMEService_ListOrders_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "proto/metacrypt/v2/acme.proto",
}

389
gen/metacrypt/v2/auth.pb.go Normal file
View File

@@ -0,0 +1,389 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc v3.20.3
// source: proto/metacrypt/v2/auth.proto
package metacryptv2
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
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 LoginRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"`
Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"`
TotpCode string `protobuf:"bytes,3,opt,name=totp_code,json=totpCode,proto3" json:"totp_code,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *LoginRequest) Reset() {
*x = LoginRequest{}
mi := &file_proto_metacrypt_v2_auth_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *LoginRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*LoginRequest) ProtoMessage() {}
func (x *LoginRequest) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_auth_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use LoginRequest.ProtoReflect.Descriptor instead.
func (*LoginRequest) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_auth_proto_rawDescGZIP(), []int{0}
}
func (x *LoginRequest) GetUsername() string {
if x != nil {
return x.Username
}
return ""
}
func (x *LoginRequest) GetPassword() string {
if x != nil {
return x.Password
}
return ""
}
func (x *LoginRequest) GetTotpCode() string {
if x != nil {
return x.TotpCode
}
return ""
}
type LoginResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
Token string `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"`
ExpiresAt *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=expires_at,json=expiresAt,proto3" json:"expires_at,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *LoginResponse) Reset() {
*x = LoginResponse{}
mi := &file_proto_metacrypt_v2_auth_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *LoginResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*LoginResponse) ProtoMessage() {}
func (x *LoginResponse) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_auth_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use LoginResponse.ProtoReflect.Descriptor instead.
func (*LoginResponse) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_auth_proto_rawDescGZIP(), []int{1}
}
func (x *LoginResponse) GetToken() string {
if x != nil {
return x.Token
}
return ""
}
func (x *LoginResponse) GetExpiresAt() *timestamppb.Timestamp {
if x != nil {
return x.ExpiresAt
}
return nil
}
type LogoutRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *LogoutRequest) Reset() {
*x = LogoutRequest{}
mi := &file_proto_metacrypt_v2_auth_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *LogoutRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*LogoutRequest) ProtoMessage() {}
func (x *LogoutRequest) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_auth_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use LogoutRequest.ProtoReflect.Descriptor instead.
func (*LogoutRequest) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_auth_proto_rawDescGZIP(), []int{2}
}
type LogoutResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *LogoutResponse) Reset() {
*x = LogoutResponse{}
mi := &file_proto_metacrypt_v2_auth_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *LogoutResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*LogoutResponse) ProtoMessage() {}
func (x *LogoutResponse) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_auth_proto_msgTypes[3]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use LogoutResponse.ProtoReflect.Descriptor instead.
func (*LogoutResponse) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_auth_proto_rawDescGZIP(), []int{3}
}
type TokenInfoRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *TokenInfoRequest) Reset() {
*x = TokenInfoRequest{}
mi := &file_proto_metacrypt_v2_auth_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *TokenInfoRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*TokenInfoRequest) ProtoMessage() {}
func (x *TokenInfoRequest) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_auth_proto_msgTypes[4]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use TokenInfoRequest.ProtoReflect.Descriptor instead.
func (*TokenInfoRequest) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_auth_proto_rawDescGZIP(), []int{4}
}
type TokenInfoResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"`
Roles []string `protobuf:"bytes,2,rep,name=roles,proto3" json:"roles,omitempty"`
IsAdmin bool `protobuf:"varint,3,opt,name=is_admin,json=isAdmin,proto3" json:"is_admin,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *TokenInfoResponse) Reset() {
*x = TokenInfoResponse{}
mi := &file_proto_metacrypt_v2_auth_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *TokenInfoResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*TokenInfoResponse) ProtoMessage() {}
func (x *TokenInfoResponse) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_auth_proto_msgTypes[5]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use TokenInfoResponse.ProtoReflect.Descriptor instead.
func (*TokenInfoResponse) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_auth_proto_rawDescGZIP(), []int{5}
}
func (x *TokenInfoResponse) GetUsername() string {
if x != nil {
return x.Username
}
return ""
}
func (x *TokenInfoResponse) GetRoles() []string {
if x != nil {
return x.Roles
}
return nil
}
func (x *TokenInfoResponse) GetIsAdmin() bool {
if x != nil {
return x.IsAdmin
}
return false
}
var File_proto_metacrypt_v2_auth_proto protoreflect.FileDescriptor
const file_proto_metacrypt_v2_auth_proto_rawDesc = "" +
"\n" +
"\x1dproto/metacrypt/v2/auth.proto\x12\fmetacrypt.v2\x1a\x1fgoogle/protobuf/timestamp.proto\"c\n" +
"\fLoginRequest\x12\x1a\n" +
"\busername\x18\x01 \x01(\tR\busername\x12\x1a\n" +
"\bpassword\x18\x02 \x01(\tR\bpassword\x12\x1b\n" +
"\ttotp_code\x18\x03 \x01(\tR\btotpCode\"`\n" +
"\rLoginResponse\x12\x14\n" +
"\x05token\x18\x01 \x01(\tR\x05token\x129\n" +
"\n" +
"expires_at\x18\x02 \x01(\v2\x1a.google.protobuf.TimestampR\texpiresAt\"\x0f\n" +
"\rLogoutRequest\"\x10\n" +
"\x0eLogoutResponse\"\x12\n" +
"\x10TokenInfoRequest\"`\n" +
"\x11TokenInfoResponse\x12\x1a\n" +
"\busername\x18\x01 \x01(\tR\busername\x12\x14\n" +
"\x05roles\x18\x02 \x03(\tR\x05roles\x12\x19\n" +
"\bis_admin\x18\x03 \x01(\bR\aisAdmin2\xe2\x01\n" +
"\vAuthService\x12@\n" +
"\x05Login\x12\x1a.metacrypt.v2.LoginRequest\x1a\x1b.metacrypt.v2.LoginResponse\x12C\n" +
"\x06Logout\x12\x1b.metacrypt.v2.LogoutRequest\x1a\x1c.metacrypt.v2.LogoutResponse\x12L\n" +
"\tTokenInfo\x12\x1e.metacrypt.v2.TokenInfoRequest\x1a\x1f.metacrypt.v2.TokenInfoResponseB>Z<git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v2;metacryptv2b\x06proto3"
var (
file_proto_metacrypt_v2_auth_proto_rawDescOnce sync.Once
file_proto_metacrypt_v2_auth_proto_rawDescData []byte
)
func file_proto_metacrypt_v2_auth_proto_rawDescGZIP() []byte {
file_proto_metacrypt_v2_auth_proto_rawDescOnce.Do(func() {
file_proto_metacrypt_v2_auth_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_proto_metacrypt_v2_auth_proto_rawDesc), len(file_proto_metacrypt_v2_auth_proto_rawDesc)))
})
return file_proto_metacrypt_v2_auth_proto_rawDescData
}
var file_proto_metacrypt_v2_auth_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_proto_metacrypt_v2_auth_proto_goTypes = []any{
(*LoginRequest)(nil), // 0: metacrypt.v2.LoginRequest
(*LoginResponse)(nil), // 1: metacrypt.v2.LoginResponse
(*LogoutRequest)(nil), // 2: metacrypt.v2.LogoutRequest
(*LogoutResponse)(nil), // 3: metacrypt.v2.LogoutResponse
(*TokenInfoRequest)(nil), // 4: metacrypt.v2.TokenInfoRequest
(*TokenInfoResponse)(nil), // 5: metacrypt.v2.TokenInfoResponse
(*timestamppb.Timestamp)(nil), // 6: google.protobuf.Timestamp
}
var file_proto_metacrypt_v2_auth_proto_depIdxs = []int32{
6, // 0: metacrypt.v2.LoginResponse.expires_at:type_name -> google.protobuf.Timestamp
0, // 1: metacrypt.v2.AuthService.Login:input_type -> metacrypt.v2.LoginRequest
2, // 2: metacrypt.v2.AuthService.Logout:input_type -> metacrypt.v2.LogoutRequest
4, // 3: metacrypt.v2.AuthService.TokenInfo:input_type -> metacrypt.v2.TokenInfoRequest
1, // 4: metacrypt.v2.AuthService.Login:output_type -> metacrypt.v2.LoginResponse
3, // 5: metacrypt.v2.AuthService.Logout:output_type -> metacrypt.v2.LogoutResponse
5, // 6: metacrypt.v2.AuthService.TokenInfo:output_type -> metacrypt.v2.TokenInfoResponse
4, // [4:7] is the sub-list for method output_type
1, // [1:4] 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_proto_metacrypt_v2_auth_proto_init() }
func file_proto_metacrypt_v2_auth_proto_init() {
if File_proto_metacrypt_v2_auth_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_metacrypt_v2_auth_proto_rawDesc), len(file_proto_metacrypt_v2_auth_proto_rawDesc)),
NumEnums: 0,
NumMessages: 6,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_proto_metacrypt_v2_auth_proto_goTypes,
DependencyIndexes: file_proto_metacrypt_v2_auth_proto_depIdxs,
MessageInfos: file_proto_metacrypt_v2_auth_proto_msgTypes,
}.Build()
File_proto_metacrypt_v2_auth_proto = out.File
file_proto_metacrypt_v2_auth_proto_goTypes = nil
file_proto_metacrypt_v2_auth_proto_depIdxs = nil
}

View File

@@ -0,0 +1,197 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.6.1
// - protoc v3.20.3
// source: proto/metacrypt/v2/auth.proto
package metacryptv2
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.64.0 or later.
const _ = grpc.SupportPackageIsVersion9
const (
AuthService_Login_FullMethodName = "/metacrypt.v2.AuthService/Login"
AuthService_Logout_FullMethodName = "/metacrypt.v2.AuthService/Logout"
AuthService_TokenInfo_FullMethodName = "/metacrypt.v2.AuthService/TokenInfo"
)
// AuthServiceClient is the client API for AuthService 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 AuthServiceClient interface {
Login(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error)
Logout(ctx context.Context, in *LogoutRequest, opts ...grpc.CallOption) (*LogoutResponse, error)
TokenInfo(ctx context.Context, in *TokenInfoRequest, opts ...grpc.CallOption) (*TokenInfoResponse, error)
}
type authServiceClient struct {
cc grpc.ClientConnInterface
}
func NewAuthServiceClient(cc grpc.ClientConnInterface) AuthServiceClient {
return &authServiceClient{cc}
}
func (c *authServiceClient) Login(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(LoginResponse)
err := c.cc.Invoke(ctx, AuthService_Login_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *authServiceClient) Logout(ctx context.Context, in *LogoutRequest, opts ...grpc.CallOption) (*LogoutResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(LogoutResponse)
err := c.cc.Invoke(ctx, AuthService_Logout_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *authServiceClient) TokenInfo(ctx context.Context, in *TokenInfoRequest, opts ...grpc.CallOption) (*TokenInfoResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(TokenInfoResponse)
err := c.cc.Invoke(ctx, AuthService_TokenInfo_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// AuthServiceServer is the server API for AuthService service.
// All implementations must embed UnimplementedAuthServiceServer
// for forward compatibility.
type AuthServiceServer interface {
Login(context.Context, *LoginRequest) (*LoginResponse, error)
Logout(context.Context, *LogoutRequest) (*LogoutResponse, error)
TokenInfo(context.Context, *TokenInfoRequest) (*TokenInfoResponse, error)
mustEmbedUnimplementedAuthServiceServer()
}
// UnimplementedAuthServiceServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedAuthServiceServer struct{}
func (UnimplementedAuthServiceServer) Login(context.Context, *LoginRequest) (*LoginResponse, error) {
return nil, status.Error(codes.Unimplemented, "method Login not implemented")
}
func (UnimplementedAuthServiceServer) Logout(context.Context, *LogoutRequest) (*LogoutResponse, error) {
return nil, status.Error(codes.Unimplemented, "method Logout not implemented")
}
func (UnimplementedAuthServiceServer) TokenInfo(context.Context, *TokenInfoRequest) (*TokenInfoResponse, error) {
return nil, status.Error(codes.Unimplemented, "method TokenInfo not implemented")
}
func (UnimplementedAuthServiceServer) mustEmbedUnimplementedAuthServiceServer() {}
func (UnimplementedAuthServiceServer) testEmbeddedByValue() {}
// UnsafeAuthServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to AuthServiceServer will
// result in compilation errors.
type UnsafeAuthServiceServer interface {
mustEmbedUnimplementedAuthServiceServer()
}
func RegisterAuthServiceServer(s grpc.ServiceRegistrar, srv AuthServiceServer) {
// If the following call panics, it indicates UnimplementedAuthServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&AuthService_ServiceDesc, srv)
}
func _AuthService_Login_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(LoginRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AuthServiceServer).Login(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: AuthService_Login_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AuthServiceServer).Login(ctx, req.(*LoginRequest))
}
return interceptor(ctx, in, info, handler)
}
func _AuthService_Logout_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(LogoutRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AuthServiceServer).Logout(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: AuthService_Logout_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AuthServiceServer).Logout(ctx, req.(*LogoutRequest))
}
return interceptor(ctx, in, info, handler)
}
func _AuthService_TokenInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(TokenInfoRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AuthServiceServer).TokenInfo(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: AuthService_TokenInfo_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AuthServiceServer).TokenInfo(ctx, req.(*TokenInfoRequest))
}
return interceptor(ctx, in, info, handler)
}
// AuthService_ServiceDesc is the grpc.ServiceDesc for AuthService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var AuthService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "metacrypt.v2.AuthService",
HandlerType: (*AuthServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Login",
Handler: _AuthService_Login_Handler,
},
{
MethodName: "Logout",
Handler: _AuthService_Logout_Handler,
},
{
MethodName: "TokenInfo",
Handler: _AuthService_TokenInfo_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "proto/metacrypt/v2/auth.proto",
}

1748
gen/metacrypt/v2/ca.pb.go Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,541 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.6.1
// - protoc v3.20.3
// source: proto/metacrypt/v2/ca.proto
package metacryptv2
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.64.0 or later.
const _ = grpc.SupportPackageIsVersion9
const (
CAService_ImportRoot_FullMethodName = "/metacrypt.v2.CAService/ImportRoot"
CAService_GetRoot_FullMethodName = "/metacrypt.v2.CAService/GetRoot"
CAService_CreateIssuer_FullMethodName = "/metacrypt.v2.CAService/CreateIssuer"
CAService_DeleteIssuer_FullMethodName = "/metacrypt.v2.CAService/DeleteIssuer"
CAService_ListIssuers_FullMethodName = "/metacrypt.v2.CAService/ListIssuers"
CAService_GetIssuer_FullMethodName = "/metacrypt.v2.CAService/GetIssuer"
CAService_GetChain_FullMethodName = "/metacrypt.v2.CAService/GetChain"
CAService_IssueCert_FullMethodName = "/metacrypt.v2.CAService/IssueCert"
CAService_GetCert_FullMethodName = "/metacrypt.v2.CAService/GetCert"
CAService_ListCerts_FullMethodName = "/metacrypt.v2.CAService/ListCerts"
CAService_RenewCert_FullMethodName = "/metacrypt.v2.CAService/RenewCert"
)
// CAServiceClient is the client API for CAService 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.
//
// CAService provides typed, authenticated access to CA engine operations.
// All RPCs require the service to be unsealed. Write operations (CreateIssuer,
// DeleteIssuer, ImportRoot, IssueCert, RenewCert) require authentication.
// Admin-only operations (CreateIssuer, DeleteIssuer, ImportRoot) additionally
// require the caller to have admin privileges.
type CAServiceClient interface {
// ImportRoot imports an existing root CA certificate and private key.
// Admin only. Only allowed when no valid root exists.
ImportRoot(ctx context.Context, in *ImportRootRequest, opts ...grpc.CallOption) (*ImportRootResponse, error)
// GetRoot returns the root CA certificate for a mount.
GetRoot(ctx context.Context, in *GetRootRequest, opts ...grpc.CallOption) (*GetRootResponse, error)
// CreateIssuer creates a new intermediate CA issuer signed by the root.
// Admin only.
CreateIssuer(ctx context.Context, in *CreateIssuerRequest, opts ...grpc.CallOption) (*CreateIssuerResponse, error)
// DeleteIssuer removes an issuer and its key material. Admin only.
DeleteIssuer(ctx context.Context, in *DeleteIssuerRequest, opts ...grpc.CallOption) (*DeleteIssuerResponse, error)
// ListIssuers returns the names of all configured issuers. Auth required.
ListIssuers(ctx context.Context, in *ListIssuersRequest, opts ...grpc.CallOption) (*ListIssuersResponse, error)
// GetIssuer returns the PEM-encoded certificate for a named issuer.
GetIssuer(ctx context.Context, in *GetIssuerRequest, opts ...grpc.CallOption) (*GetIssuerResponse, error)
// GetChain returns the full PEM certificate chain for a named issuer.
GetChain(ctx context.Context, in *CAServiceGetChainRequest, opts ...grpc.CallOption) (*CAServiceGetChainResponse, error)
// IssueCert issues a new leaf certificate from a named issuer. Auth required.
IssueCert(ctx context.Context, in *IssueCertRequest, opts ...grpc.CallOption) (*IssueCertResponse, error)
// GetCert retrieves a certificate record by serial number. Auth required.
GetCert(ctx context.Context, in *GetCertRequest, opts ...grpc.CallOption) (*GetCertResponse, error)
// ListCerts lists all certificate records for a mount. Auth required.
ListCerts(ctx context.Context, in *ListCertsRequest, opts ...grpc.CallOption) (*ListCertsResponse, error)
// RenewCert renews an existing certificate, generating a new key and serial.
// Auth required.
RenewCert(ctx context.Context, in *RenewCertRequest, opts ...grpc.CallOption) (*RenewCertResponse, error)
}
type cAServiceClient struct {
cc grpc.ClientConnInterface
}
func NewCAServiceClient(cc grpc.ClientConnInterface) CAServiceClient {
return &cAServiceClient{cc}
}
func (c *cAServiceClient) ImportRoot(ctx context.Context, in *ImportRootRequest, opts ...grpc.CallOption) (*ImportRootResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ImportRootResponse)
err := c.cc.Invoke(ctx, CAService_ImportRoot_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *cAServiceClient) GetRoot(ctx context.Context, in *GetRootRequest, opts ...grpc.CallOption) (*GetRootResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetRootResponse)
err := c.cc.Invoke(ctx, CAService_GetRoot_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *cAServiceClient) CreateIssuer(ctx context.Context, in *CreateIssuerRequest, opts ...grpc.CallOption) (*CreateIssuerResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(CreateIssuerResponse)
err := c.cc.Invoke(ctx, CAService_CreateIssuer_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *cAServiceClient) DeleteIssuer(ctx context.Context, in *DeleteIssuerRequest, opts ...grpc.CallOption) (*DeleteIssuerResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(DeleteIssuerResponse)
err := c.cc.Invoke(ctx, CAService_DeleteIssuer_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *cAServiceClient) ListIssuers(ctx context.Context, in *ListIssuersRequest, opts ...grpc.CallOption) (*ListIssuersResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ListIssuersResponse)
err := c.cc.Invoke(ctx, CAService_ListIssuers_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *cAServiceClient) GetIssuer(ctx context.Context, in *GetIssuerRequest, opts ...grpc.CallOption) (*GetIssuerResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetIssuerResponse)
err := c.cc.Invoke(ctx, CAService_GetIssuer_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *cAServiceClient) GetChain(ctx context.Context, in *CAServiceGetChainRequest, opts ...grpc.CallOption) (*CAServiceGetChainResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(CAServiceGetChainResponse)
err := c.cc.Invoke(ctx, CAService_GetChain_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *cAServiceClient) IssueCert(ctx context.Context, in *IssueCertRequest, opts ...grpc.CallOption) (*IssueCertResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(IssueCertResponse)
err := c.cc.Invoke(ctx, CAService_IssueCert_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *cAServiceClient) GetCert(ctx context.Context, in *GetCertRequest, opts ...grpc.CallOption) (*GetCertResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetCertResponse)
err := c.cc.Invoke(ctx, CAService_GetCert_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *cAServiceClient) ListCerts(ctx context.Context, in *ListCertsRequest, opts ...grpc.CallOption) (*ListCertsResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ListCertsResponse)
err := c.cc.Invoke(ctx, CAService_ListCerts_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *cAServiceClient) RenewCert(ctx context.Context, in *RenewCertRequest, opts ...grpc.CallOption) (*RenewCertResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(RenewCertResponse)
err := c.cc.Invoke(ctx, CAService_RenewCert_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// CAServiceServer is the server API for CAService service.
// All implementations must embed UnimplementedCAServiceServer
// for forward compatibility.
//
// CAService provides typed, authenticated access to CA engine operations.
// All RPCs require the service to be unsealed. Write operations (CreateIssuer,
// DeleteIssuer, ImportRoot, IssueCert, RenewCert) require authentication.
// Admin-only operations (CreateIssuer, DeleteIssuer, ImportRoot) additionally
// require the caller to have admin privileges.
type CAServiceServer interface {
// ImportRoot imports an existing root CA certificate and private key.
// Admin only. Only allowed when no valid root exists.
ImportRoot(context.Context, *ImportRootRequest) (*ImportRootResponse, error)
// GetRoot returns the root CA certificate for a mount.
GetRoot(context.Context, *GetRootRequest) (*GetRootResponse, error)
// CreateIssuer creates a new intermediate CA issuer signed by the root.
// Admin only.
CreateIssuer(context.Context, *CreateIssuerRequest) (*CreateIssuerResponse, error)
// DeleteIssuer removes an issuer and its key material. Admin only.
DeleteIssuer(context.Context, *DeleteIssuerRequest) (*DeleteIssuerResponse, error)
// ListIssuers returns the names of all configured issuers. Auth required.
ListIssuers(context.Context, *ListIssuersRequest) (*ListIssuersResponse, error)
// GetIssuer returns the PEM-encoded certificate for a named issuer.
GetIssuer(context.Context, *GetIssuerRequest) (*GetIssuerResponse, error)
// GetChain returns the full PEM certificate chain for a named issuer.
GetChain(context.Context, *CAServiceGetChainRequest) (*CAServiceGetChainResponse, error)
// IssueCert issues a new leaf certificate from a named issuer. Auth required.
IssueCert(context.Context, *IssueCertRequest) (*IssueCertResponse, error)
// GetCert retrieves a certificate record by serial number. Auth required.
GetCert(context.Context, *GetCertRequest) (*GetCertResponse, error)
// ListCerts lists all certificate records for a mount. Auth required.
ListCerts(context.Context, *ListCertsRequest) (*ListCertsResponse, error)
// RenewCert renews an existing certificate, generating a new key and serial.
// Auth required.
RenewCert(context.Context, *RenewCertRequest) (*RenewCertResponse, error)
mustEmbedUnimplementedCAServiceServer()
}
// UnimplementedCAServiceServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedCAServiceServer struct{}
func (UnimplementedCAServiceServer) ImportRoot(context.Context, *ImportRootRequest) (*ImportRootResponse, error) {
return nil, status.Error(codes.Unimplemented, "method ImportRoot not implemented")
}
func (UnimplementedCAServiceServer) GetRoot(context.Context, *GetRootRequest) (*GetRootResponse, error) {
return nil, status.Error(codes.Unimplemented, "method GetRoot not implemented")
}
func (UnimplementedCAServiceServer) CreateIssuer(context.Context, *CreateIssuerRequest) (*CreateIssuerResponse, error) {
return nil, status.Error(codes.Unimplemented, "method CreateIssuer not implemented")
}
func (UnimplementedCAServiceServer) DeleteIssuer(context.Context, *DeleteIssuerRequest) (*DeleteIssuerResponse, error) {
return nil, status.Error(codes.Unimplemented, "method DeleteIssuer not implemented")
}
func (UnimplementedCAServiceServer) ListIssuers(context.Context, *ListIssuersRequest) (*ListIssuersResponse, error) {
return nil, status.Error(codes.Unimplemented, "method ListIssuers not implemented")
}
func (UnimplementedCAServiceServer) GetIssuer(context.Context, *GetIssuerRequest) (*GetIssuerResponse, error) {
return nil, status.Error(codes.Unimplemented, "method GetIssuer not implemented")
}
func (UnimplementedCAServiceServer) GetChain(context.Context, *CAServiceGetChainRequest) (*CAServiceGetChainResponse, error) {
return nil, status.Error(codes.Unimplemented, "method GetChain not implemented")
}
func (UnimplementedCAServiceServer) IssueCert(context.Context, *IssueCertRequest) (*IssueCertResponse, error) {
return nil, status.Error(codes.Unimplemented, "method IssueCert not implemented")
}
func (UnimplementedCAServiceServer) GetCert(context.Context, *GetCertRequest) (*GetCertResponse, error) {
return nil, status.Error(codes.Unimplemented, "method GetCert not implemented")
}
func (UnimplementedCAServiceServer) ListCerts(context.Context, *ListCertsRequest) (*ListCertsResponse, error) {
return nil, status.Error(codes.Unimplemented, "method ListCerts not implemented")
}
func (UnimplementedCAServiceServer) RenewCert(context.Context, *RenewCertRequest) (*RenewCertResponse, error) {
return nil, status.Error(codes.Unimplemented, "method RenewCert not implemented")
}
func (UnimplementedCAServiceServer) mustEmbedUnimplementedCAServiceServer() {}
func (UnimplementedCAServiceServer) testEmbeddedByValue() {}
// UnsafeCAServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to CAServiceServer will
// result in compilation errors.
type UnsafeCAServiceServer interface {
mustEmbedUnimplementedCAServiceServer()
}
func RegisterCAServiceServer(s grpc.ServiceRegistrar, srv CAServiceServer) {
// If the following call panics, it indicates UnimplementedCAServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&CAService_ServiceDesc, srv)
}
func _CAService_ImportRoot_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ImportRootRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CAServiceServer).ImportRoot(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: CAService_ImportRoot_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CAServiceServer).ImportRoot(ctx, req.(*ImportRootRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CAService_GetRoot_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetRootRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CAServiceServer).GetRoot(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: CAService_GetRoot_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CAServiceServer).GetRoot(ctx, req.(*GetRootRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CAService_CreateIssuer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CreateIssuerRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CAServiceServer).CreateIssuer(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: CAService_CreateIssuer_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CAServiceServer).CreateIssuer(ctx, req.(*CreateIssuerRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CAService_DeleteIssuer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DeleteIssuerRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CAServiceServer).DeleteIssuer(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: CAService_DeleteIssuer_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CAServiceServer).DeleteIssuer(ctx, req.(*DeleteIssuerRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CAService_ListIssuers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListIssuersRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CAServiceServer).ListIssuers(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: CAService_ListIssuers_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CAServiceServer).ListIssuers(ctx, req.(*ListIssuersRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CAService_GetIssuer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetIssuerRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CAServiceServer).GetIssuer(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: CAService_GetIssuer_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CAServiceServer).GetIssuer(ctx, req.(*GetIssuerRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CAService_GetChain_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CAServiceGetChainRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CAServiceServer).GetChain(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: CAService_GetChain_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CAServiceServer).GetChain(ctx, req.(*CAServiceGetChainRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CAService_IssueCert_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(IssueCertRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CAServiceServer).IssueCert(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: CAService_IssueCert_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CAServiceServer).IssueCert(ctx, req.(*IssueCertRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CAService_GetCert_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetCertRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CAServiceServer).GetCert(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: CAService_GetCert_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CAServiceServer).GetCert(ctx, req.(*GetCertRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CAService_ListCerts_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListCertsRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CAServiceServer).ListCerts(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: CAService_ListCerts_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CAServiceServer).ListCerts(ctx, req.(*ListCertsRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CAService_RenewCert_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(RenewCertRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CAServiceServer).RenewCert(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: CAService_RenewCert_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CAServiceServer).RenewCert(ctx, req.(*RenewCertRequest))
}
return interceptor(ctx, in, info, handler)
}
// CAService_ServiceDesc is the grpc.ServiceDesc for CAService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var CAService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "metacrypt.v2.CAService",
HandlerType: (*CAServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "ImportRoot",
Handler: _CAService_ImportRoot_Handler,
},
{
MethodName: "GetRoot",
Handler: _CAService_GetRoot_Handler,
},
{
MethodName: "CreateIssuer",
Handler: _CAService_CreateIssuer_Handler,
},
{
MethodName: "DeleteIssuer",
Handler: _CAService_DeleteIssuer_Handler,
},
{
MethodName: "ListIssuers",
Handler: _CAService_ListIssuers_Handler,
},
{
MethodName: "GetIssuer",
Handler: _CAService_GetIssuer_Handler,
},
{
MethodName: "GetChain",
Handler: _CAService_GetChain_Handler,
},
{
MethodName: "IssueCert",
Handler: _CAService_IssueCert_Handler,
},
{
MethodName: "GetCert",
Handler: _CAService_GetCert_Handler,
},
{
MethodName: "ListCerts",
Handler: _CAService_ListCerts_Handler,
},
{
MethodName: "RenewCert",
Handler: _CAService_RenewCert_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "proto/metacrypt/v2/ca.proto",
}

View File

@@ -0,0 +1,59 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc v3.20.3
// source: proto/metacrypt/v2/common.proto
package metacryptv2
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
unsafe "unsafe"
)
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)
)
var File_proto_metacrypt_v2_common_proto protoreflect.FileDescriptor
const file_proto_metacrypt_v2_common_proto_rawDesc = "" +
"\n" +
"\x1fproto/metacrypt/v2/common.proto\x12\fmetacrypt.v2B>Z<git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v2;metacryptv2b\x06proto3"
var file_proto_metacrypt_v2_common_proto_goTypes = []any{}
var file_proto_metacrypt_v2_common_proto_depIdxs = []int32{
0, // [0:0] is the sub-list for method output_type
0, // [0:0] 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_proto_metacrypt_v2_common_proto_init() }
func file_proto_metacrypt_v2_common_proto_init() {
if File_proto_metacrypt_v2_common_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_metacrypt_v2_common_proto_rawDesc), len(file_proto_metacrypt_v2_common_proto_rawDesc)),
NumEnums: 0,
NumMessages: 0,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_proto_metacrypt_v2_common_proto_goTypes,
DependencyIndexes: file_proto_metacrypt_v2_common_proto_depIdxs,
}.Build()
File_proto_metacrypt_v2_common_proto = out.File
file_proto_metacrypt_v2_common_proto_goTypes = nil
file_proto_metacrypt_v2_common_proto_depIdxs = nil
}

View File

@@ -0,0 +1,432 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc v3.20.3
// source: proto/metacrypt/v2/engine.proto
package metacryptv2
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
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 MountRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Type string `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"`
// config holds engine-specific configuration as key-value string pairs.
Config map[string]string `protobuf:"bytes,3,rep,name=config,proto3" json:"config,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *MountRequest) Reset() {
*x = MountRequest{}
mi := &file_proto_metacrypt_v2_engine_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *MountRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*MountRequest) ProtoMessage() {}
func (x *MountRequest) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_engine_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use MountRequest.ProtoReflect.Descriptor instead.
func (*MountRequest) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_engine_proto_rawDescGZIP(), []int{0}
}
func (x *MountRequest) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *MountRequest) GetType() string {
if x != nil {
return x.Type
}
return ""
}
func (x *MountRequest) GetConfig() map[string]string {
if x != nil {
return x.Config
}
return nil
}
type MountResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *MountResponse) Reset() {
*x = MountResponse{}
mi := &file_proto_metacrypt_v2_engine_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *MountResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*MountResponse) ProtoMessage() {}
func (x *MountResponse) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_engine_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use MountResponse.ProtoReflect.Descriptor instead.
func (*MountResponse) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_engine_proto_rawDescGZIP(), []int{1}
}
type UnmountRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *UnmountRequest) Reset() {
*x = UnmountRequest{}
mi := &file_proto_metacrypt_v2_engine_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *UnmountRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UnmountRequest) ProtoMessage() {}
func (x *UnmountRequest) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_engine_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use UnmountRequest.ProtoReflect.Descriptor instead.
func (*UnmountRequest) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_engine_proto_rawDescGZIP(), []int{2}
}
func (x *UnmountRequest) GetName() string {
if x != nil {
return x.Name
}
return ""
}
type UnmountResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *UnmountResponse) Reset() {
*x = UnmountResponse{}
mi := &file_proto_metacrypt_v2_engine_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *UnmountResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UnmountResponse) ProtoMessage() {}
func (x *UnmountResponse) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_engine_proto_msgTypes[3]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use UnmountResponse.ProtoReflect.Descriptor instead.
func (*UnmountResponse) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_engine_proto_rawDescGZIP(), []int{3}
}
type ListMountsRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ListMountsRequest) Reset() {
*x = ListMountsRequest{}
mi := &file_proto_metacrypt_v2_engine_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListMountsRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListMountsRequest) ProtoMessage() {}
func (x *ListMountsRequest) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_engine_proto_msgTypes[4]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ListMountsRequest.ProtoReflect.Descriptor instead.
func (*ListMountsRequest) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_engine_proto_rawDescGZIP(), []int{4}
}
type ListMountsResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
Mounts []*MountInfo `protobuf:"bytes,1,rep,name=mounts,proto3" json:"mounts,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ListMountsResponse) Reset() {
*x = ListMountsResponse{}
mi := &file_proto_metacrypt_v2_engine_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListMountsResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListMountsResponse) ProtoMessage() {}
func (x *ListMountsResponse) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_engine_proto_msgTypes[5]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ListMountsResponse.ProtoReflect.Descriptor instead.
func (*ListMountsResponse) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_engine_proto_rawDescGZIP(), []int{5}
}
func (x *ListMountsResponse) GetMounts() []*MountInfo {
if x != nil {
return x.Mounts
}
return nil
}
type MountInfo struct {
state protoimpl.MessageState `protogen:"open.v1"`
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Type string `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"`
MountPath string `protobuf:"bytes,3,opt,name=mount_path,json=mountPath,proto3" json:"mount_path,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *MountInfo) Reset() {
*x = MountInfo{}
mi := &file_proto_metacrypt_v2_engine_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *MountInfo) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*MountInfo) ProtoMessage() {}
func (x *MountInfo) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_engine_proto_msgTypes[6]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use MountInfo.ProtoReflect.Descriptor instead.
func (*MountInfo) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_engine_proto_rawDescGZIP(), []int{6}
}
func (x *MountInfo) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *MountInfo) GetType() string {
if x != nil {
return x.Type
}
return ""
}
func (x *MountInfo) GetMountPath() string {
if x != nil {
return x.MountPath
}
return ""
}
var File_proto_metacrypt_v2_engine_proto protoreflect.FileDescriptor
const file_proto_metacrypt_v2_engine_proto_rawDesc = "" +
"\n" +
"\x1fproto/metacrypt/v2/engine.proto\x12\fmetacrypt.v2\"\xb1\x01\n" +
"\fMountRequest\x12\x12\n" +
"\x04name\x18\x01 \x01(\tR\x04name\x12\x12\n" +
"\x04type\x18\x02 \x01(\tR\x04type\x12>\n" +
"\x06config\x18\x03 \x03(\v2&.metacrypt.v2.MountRequest.ConfigEntryR\x06config\x1a9\n" +
"\vConfigEntry\x12\x10\n" +
"\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" +
"\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"\x0f\n" +
"\rMountResponse\"$\n" +
"\x0eUnmountRequest\x12\x12\n" +
"\x04name\x18\x01 \x01(\tR\x04name\"\x11\n" +
"\x0fUnmountResponse\"\x13\n" +
"\x11ListMountsRequest\"E\n" +
"\x12ListMountsResponse\x12/\n" +
"\x06mounts\x18\x01 \x03(\v2\x17.metacrypt.v2.MountInfoR\x06mounts\"R\n" +
"\tMountInfo\x12\x12\n" +
"\x04name\x18\x01 \x01(\tR\x04name\x12\x12\n" +
"\x04type\x18\x02 \x01(\tR\x04type\x12\x1d\n" +
"\n" +
"mount_path\x18\x03 \x01(\tR\tmountPath2\xea\x01\n" +
"\rEngineService\x12@\n" +
"\x05Mount\x12\x1a.metacrypt.v2.MountRequest\x1a\x1b.metacrypt.v2.MountResponse\x12F\n" +
"\aUnmount\x12\x1c.metacrypt.v2.UnmountRequest\x1a\x1d.metacrypt.v2.UnmountResponse\x12O\n" +
"\n" +
"ListMounts\x12\x1f.metacrypt.v2.ListMountsRequest\x1a .metacrypt.v2.ListMountsResponseB>Z<git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v2;metacryptv2b\x06proto3"
var (
file_proto_metacrypt_v2_engine_proto_rawDescOnce sync.Once
file_proto_metacrypt_v2_engine_proto_rawDescData []byte
)
func file_proto_metacrypt_v2_engine_proto_rawDescGZIP() []byte {
file_proto_metacrypt_v2_engine_proto_rawDescOnce.Do(func() {
file_proto_metacrypt_v2_engine_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_proto_metacrypt_v2_engine_proto_rawDesc), len(file_proto_metacrypt_v2_engine_proto_rawDesc)))
})
return file_proto_metacrypt_v2_engine_proto_rawDescData
}
var file_proto_metacrypt_v2_engine_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
var file_proto_metacrypt_v2_engine_proto_goTypes = []any{
(*MountRequest)(nil), // 0: metacrypt.v2.MountRequest
(*MountResponse)(nil), // 1: metacrypt.v2.MountResponse
(*UnmountRequest)(nil), // 2: metacrypt.v2.UnmountRequest
(*UnmountResponse)(nil), // 3: metacrypt.v2.UnmountResponse
(*ListMountsRequest)(nil), // 4: metacrypt.v2.ListMountsRequest
(*ListMountsResponse)(nil), // 5: metacrypt.v2.ListMountsResponse
(*MountInfo)(nil), // 6: metacrypt.v2.MountInfo
nil, // 7: metacrypt.v2.MountRequest.ConfigEntry
}
var file_proto_metacrypt_v2_engine_proto_depIdxs = []int32{
7, // 0: metacrypt.v2.MountRequest.config:type_name -> metacrypt.v2.MountRequest.ConfigEntry
6, // 1: metacrypt.v2.ListMountsResponse.mounts:type_name -> metacrypt.v2.MountInfo
0, // 2: metacrypt.v2.EngineService.Mount:input_type -> metacrypt.v2.MountRequest
2, // 3: metacrypt.v2.EngineService.Unmount:input_type -> metacrypt.v2.UnmountRequest
4, // 4: metacrypt.v2.EngineService.ListMounts:input_type -> metacrypt.v2.ListMountsRequest
1, // 5: metacrypt.v2.EngineService.Mount:output_type -> metacrypt.v2.MountResponse
3, // 6: metacrypt.v2.EngineService.Unmount:output_type -> metacrypt.v2.UnmountResponse
5, // 7: metacrypt.v2.EngineService.ListMounts:output_type -> metacrypt.v2.ListMountsResponse
5, // [5:8] is the sub-list for method output_type
2, // [2:5] is the sub-list for method input_type
2, // [2:2] is the sub-list for extension type_name
2, // [2:2] is the sub-list for extension extendee
0, // [0:2] is the sub-list for field type_name
}
func init() { file_proto_metacrypt_v2_engine_proto_init() }
func file_proto_metacrypt_v2_engine_proto_init() {
if File_proto_metacrypt_v2_engine_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_metacrypt_v2_engine_proto_rawDesc), len(file_proto_metacrypt_v2_engine_proto_rawDesc)),
NumEnums: 0,
NumMessages: 8,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_proto_metacrypt_v2_engine_proto_goTypes,
DependencyIndexes: file_proto_metacrypt_v2_engine_proto_depIdxs,
MessageInfos: file_proto_metacrypt_v2_engine_proto_msgTypes,
}.Build()
File_proto_metacrypt_v2_engine_proto = out.File
file_proto_metacrypt_v2_engine_proto_goTypes = nil
file_proto_metacrypt_v2_engine_proto_depIdxs = nil
}

View File

@@ -0,0 +1,205 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.6.1
// - protoc v3.20.3
// source: proto/metacrypt/v2/engine.proto
package metacryptv2
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.64.0 or later.
const _ = grpc.SupportPackageIsVersion9
const (
EngineService_Mount_FullMethodName = "/metacrypt.v2.EngineService/Mount"
EngineService_Unmount_FullMethodName = "/metacrypt.v2.EngineService/Unmount"
EngineService_ListMounts_FullMethodName = "/metacrypt.v2.EngineService/ListMounts"
)
// EngineServiceClient is the client API for EngineService 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.
//
// EngineService manages the lifecycle of engine mounts.
// In v2, typed service RPCs (e.g. CAService) replace the generic Execute RPC
// for all engine operations.
type EngineServiceClient interface {
Mount(ctx context.Context, in *MountRequest, opts ...grpc.CallOption) (*MountResponse, error)
Unmount(ctx context.Context, in *UnmountRequest, opts ...grpc.CallOption) (*UnmountResponse, error)
ListMounts(ctx context.Context, in *ListMountsRequest, opts ...grpc.CallOption) (*ListMountsResponse, error)
}
type engineServiceClient struct {
cc grpc.ClientConnInterface
}
func NewEngineServiceClient(cc grpc.ClientConnInterface) EngineServiceClient {
return &engineServiceClient{cc}
}
func (c *engineServiceClient) Mount(ctx context.Context, in *MountRequest, opts ...grpc.CallOption) (*MountResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(MountResponse)
err := c.cc.Invoke(ctx, EngineService_Mount_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *engineServiceClient) Unmount(ctx context.Context, in *UnmountRequest, opts ...grpc.CallOption) (*UnmountResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(UnmountResponse)
err := c.cc.Invoke(ctx, EngineService_Unmount_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *engineServiceClient) ListMounts(ctx context.Context, in *ListMountsRequest, opts ...grpc.CallOption) (*ListMountsResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ListMountsResponse)
err := c.cc.Invoke(ctx, EngineService_ListMounts_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// EngineServiceServer is the server API for EngineService service.
// All implementations must embed UnimplementedEngineServiceServer
// for forward compatibility.
//
// EngineService manages the lifecycle of engine mounts.
// In v2, typed service RPCs (e.g. CAService) replace the generic Execute RPC
// for all engine operations.
type EngineServiceServer interface {
Mount(context.Context, *MountRequest) (*MountResponse, error)
Unmount(context.Context, *UnmountRequest) (*UnmountResponse, error)
ListMounts(context.Context, *ListMountsRequest) (*ListMountsResponse, error)
mustEmbedUnimplementedEngineServiceServer()
}
// UnimplementedEngineServiceServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedEngineServiceServer struct{}
func (UnimplementedEngineServiceServer) Mount(context.Context, *MountRequest) (*MountResponse, error) {
return nil, status.Error(codes.Unimplemented, "method Mount not implemented")
}
func (UnimplementedEngineServiceServer) Unmount(context.Context, *UnmountRequest) (*UnmountResponse, error) {
return nil, status.Error(codes.Unimplemented, "method Unmount not implemented")
}
func (UnimplementedEngineServiceServer) ListMounts(context.Context, *ListMountsRequest) (*ListMountsResponse, error) {
return nil, status.Error(codes.Unimplemented, "method ListMounts not implemented")
}
func (UnimplementedEngineServiceServer) mustEmbedUnimplementedEngineServiceServer() {}
func (UnimplementedEngineServiceServer) testEmbeddedByValue() {}
// UnsafeEngineServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to EngineServiceServer will
// result in compilation errors.
type UnsafeEngineServiceServer interface {
mustEmbedUnimplementedEngineServiceServer()
}
func RegisterEngineServiceServer(s grpc.ServiceRegistrar, srv EngineServiceServer) {
// If the following call panics, it indicates UnimplementedEngineServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&EngineService_ServiceDesc, srv)
}
func _EngineService_Mount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(MountRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(EngineServiceServer).Mount(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: EngineService_Mount_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(EngineServiceServer).Mount(ctx, req.(*MountRequest))
}
return interceptor(ctx, in, info, handler)
}
func _EngineService_Unmount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(UnmountRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(EngineServiceServer).Unmount(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: EngineService_Unmount_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(EngineServiceServer).Unmount(ctx, req.(*UnmountRequest))
}
return interceptor(ctx, in, info, handler)
}
func _EngineService_ListMounts_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListMountsRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(EngineServiceServer).ListMounts(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: EngineService_ListMounts_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(EngineServiceServer).ListMounts(ctx, req.(*ListMountsRequest))
}
return interceptor(ctx, in, info, handler)
}
// EngineService_ServiceDesc is the grpc.ServiceDesc for EngineService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var EngineService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "metacrypt.v2.EngineService",
HandlerType: (*EngineServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Mount",
Handler: _EngineService_Mount_Handler,
},
{
MethodName: "Unmount",
Handler: _EngineService_Unmount_Handler,
},
{
MethodName: "ListMounts",
Handler: _EngineService_ListMounts_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "proto/metacrypt/v2/engine.proto",
}

386
gen/metacrypt/v2/pki.pb.go Normal file
View File

@@ -0,0 +1,386 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc v3.20.3
// source: proto/metacrypt/v2/pki.proto
package metacryptv2
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
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 GetRootCertRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
Mount string `protobuf:"bytes,1,opt,name=mount,proto3" json:"mount,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetRootCertRequest) Reset() {
*x = GetRootCertRequest{}
mi := &file_proto_metacrypt_v2_pki_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetRootCertRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetRootCertRequest) ProtoMessage() {}
func (x *GetRootCertRequest) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_pki_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetRootCertRequest.ProtoReflect.Descriptor instead.
func (*GetRootCertRequest) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_pki_proto_rawDescGZIP(), []int{0}
}
func (x *GetRootCertRequest) GetMount() string {
if x != nil {
return x.Mount
}
return ""
}
type GetRootCertResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
CertPem []byte `protobuf:"bytes,1,opt,name=cert_pem,json=certPem,proto3" json:"cert_pem,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetRootCertResponse) Reset() {
*x = GetRootCertResponse{}
mi := &file_proto_metacrypt_v2_pki_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetRootCertResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetRootCertResponse) ProtoMessage() {}
func (x *GetRootCertResponse) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_pki_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetRootCertResponse.ProtoReflect.Descriptor instead.
func (*GetRootCertResponse) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_pki_proto_rawDescGZIP(), []int{1}
}
func (x *GetRootCertResponse) GetCertPem() []byte {
if x != nil {
return x.CertPem
}
return nil
}
type GetChainRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
Mount string `protobuf:"bytes,1,opt,name=mount,proto3" json:"mount,omitempty"`
Issuer string `protobuf:"bytes,2,opt,name=issuer,proto3" json:"issuer,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetChainRequest) Reset() {
*x = GetChainRequest{}
mi := &file_proto_metacrypt_v2_pki_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetChainRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetChainRequest) ProtoMessage() {}
func (x *GetChainRequest) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_pki_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetChainRequest.ProtoReflect.Descriptor instead.
func (*GetChainRequest) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_pki_proto_rawDescGZIP(), []int{2}
}
func (x *GetChainRequest) GetMount() string {
if x != nil {
return x.Mount
}
return ""
}
func (x *GetChainRequest) GetIssuer() string {
if x != nil {
return x.Issuer
}
return ""
}
type GetChainResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
ChainPem []byte `protobuf:"bytes,1,opt,name=chain_pem,json=chainPem,proto3" json:"chain_pem,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetChainResponse) Reset() {
*x = GetChainResponse{}
mi := &file_proto_metacrypt_v2_pki_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetChainResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetChainResponse) ProtoMessage() {}
func (x *GetChainResponse) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_pki_proto_msgTypes[3]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetChainResponse.ProtoReflect.Descriptor instead.
func (*GetChainResponse) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_pki_proto_rawDescGZIP(), []int{3}
}
func (x *GetChainResponse) GetChainPem() []byte {
if x != nil {
return x.ChainPem
}
return nil
}
type GetIssuerCertRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
Mount string `protobuf:"bytes,1,opt,name=mount,proto3" json:"mount,omitempty"`
Issuer string `protobuf:"bytes,2,opt,name=issuer,proto3" json:"issuer,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetIssuerCertRequest) Reset() {
*x = GetIssuerCertRequest{}
mi := &file_proto_metacrypt_v2_pki_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetIssuerCertRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetIssuerCertRequest) ProtoMessage() {}
func (x *GetIssuerCertRequest) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_pki_proto_msgTypes[4]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetIssuerCertRequest.ProtoReflect.Descriptor instead.
func (*GetIssuerCertRequest) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_pki_proto_rawDescGZIP(), []int{4}
}
func (x *GetIssuerCertRequest) GetMount() string {
if x != nil {
return x.Mount
}
return ""
}
func (x *GetIssuerCertRequest) GetIssuer() string {
if x != nil {
return x.Issuer
}
return ""
}
type GetIssuerCertResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
CertPem []byte `protobuf:"bytes,1,opt,name=cert_pem,json=certPem,proto3" json:"cert_pem,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetIssuerCertResponse) Reset() {
*x = GetIssuerCertResponse{}
mi := &file_proto_metacrypt_v2_pki_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetIssuerCertResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetIssuerCertResponse) ProtoMessage() {}
func (x *GetIssuerCertResponse) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_pki_proto_msgTypes[5]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetIssuerCertResponse.ProtoReflect.Descriptor instead.
func (*GetIssuerCertResponse) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_pki_proto_rawDescGZIP(), []int{5}
}
func (x *GetIssuerCertResponse) GetCertPem() []byte {
if x != nil {
return x.CertPem
}
return nil
}
var File_proto_metacrypt_v2_pki_proto protoreflect.FileDescriptor
const file_proto_metacrypt_v2_pki_proto_rawDesc = "" +
"\n" +
"\x1cproto/metacrypt/v2/pki.proto\x12\fmetacrypt.v2\"*\n" +
"\x12GetRootCertRequest\x12\x14\n" +
"\x05mount\x18\x01 \x01(\tR\x05mount\"0\n" +
"\x13GetRootCertResponse\x12\x19\n" +
"\bcert_pem\x18\x01 \x01(\fR\acertPem\"?\n" +
"\x0fGetChainRequest\x12\x14\n" +
"\x05mount\x18\x01 \x01(\tR\x05mount\x12\x16\n" +
"\x06issuer\x18\x02 \x01(\tR\x06issuer\"/\n" +
"\x10GetChainResponse\x12\x1b\n" +
"\tchain_pem\x18\x01 \x01(\fR\bchainPem\"D\n" +
"\x14GetIssuerCertRequest\x12\x14\n" +
"\x05mount\x18\x01 \x01(\tR\x05mount\x12\x16\n" +
"\x06issuer\x18\x02 \x01(\tR\x06issuer\"2\n" +
"\x15GetIssuerCertResponse\x12\x19\n" +
"\bcert_pem\x18\x01 \x01(\fR\acertPem2\x85\x02\n" +
"\n" +
"PKIService\x12R\n" +
"\vGetRootCert\x12 .metacrypt.v2.GetRootCertRequest\x1a!.metacrypt.v2.GetRootCertResponse\x12I\n" +
"\bGetChain\x12\x1d.metacrypt.v2.GetChainRequest\x1a\x1e.metacrypt.v2.GetChainResponse\x12X\n" +
"\rGetIssuerCert\x12\".metacrypt.v2.GetIssuerCertRequest\x1a#.metacrypt.v2.GetIssuerCertResponseB>Z<git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v2;metacryptv2b\x06proto3"
var (
file_proto_metacrypt_v2_pki_proto_rawDescOnce sync.Once
file_proto_metacrypt_v2_pki_proto_rawDescData []byte
)
func file_proto_metacrypt_v2_pki_proto_rawDescGZIP() []byte {
file_proto_metacrypt_v2_pki_proto_rawDescOnce.Do(func() {
file_proto_metacrypt_v2_pki_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_proto_metacrypt_v2_pki_proto_rawDesc), len(file_proto_metacrypt_v2_pki_proto_rawDesc)))
})
return file_proto_metacrypt_v2_pki_proto_rawDescData
}
var file_proto_metacrypt_v2_pki_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_proto_metacrypt_v2_pki_proto_goTypes = []any{
(*GetRootCertRequest)(nil), // 0: metacrypt.v2.GetRootCertRequest
(*GetRootCertResponse)(nil), // 1: metacrypt.v2.GetRootCertResponse
(*GetChainRequest)(nil), // 2: metacrypt.v2.GetChainRequest
(*GetChainResponse)(nil), // 3: metacrypt.v2.GetChainResponse
(*GetIssuerCertRequest)(nil), // 4: metacrypt.v2.GetIssuerCertRequest
(*GetIssuerCertResponse)(nil), // 5: metacrypt.v2.GetIssuerCertResponse
}
var file_proto_metacrypt_v2_pki_proto_depIdxs = []int32{
0, // 0: metacrypt.v2.PKIService.GetRootCert:input_type -> metacrypt.v2.GetRootCertRequest
2, // 1: metacrypt.v2.PKIService.GetChain:input_type -> metacrypt.v2.GetChainRequest
4, // 2: metacrypt.v2.PKIService.GetIssuerCert:input_type -> metacrypt.v2.GetIssuerCertRequest
1, // 3: metacrypt.v2.PKIService.GetRootCert:output_type -> metacrypt.v2.GetRootCertResponse
3, // 4: metacrypt.v2.PKIService.GetChain:output_type -> metacrypt.v2.GetChainResponse
5, // 5: metacrypt.v2.PKIService.GetIssuerCert:output_type -> metacrypt.v2.GetIssuerCertResponse
3, // [3:6] is the sub-list for method output_type
0, // [0:3] 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_proto_metacrypt_v2_pki_proto_init() }
func file_proto_metacrypt_v2_pki_proto_init() {
if File_proto_metacrypt_v2_pki_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_metacrypt_v2_pki_proto_rawDesc), len(file_proto_metacrypt_v2_pki_proto_rawDesc)),
NumEnums: 0,
NumMessages: 6,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_proto_metacrypt_v2_pki_proto_goTypes,
DependencyIndexes: file_proto_metacrypt_v2_pki_proto_depIdxs,
MessageInfos: file_proto_metacrypt_v2_pki_proto_msgTypes,
}.Build()
File_proto_metacrypt_v2_pki_proto = out.File
file_proto_metacrypt_v2_pki_proto_goTypes = nil
file_proto_metacrypt_v2_pki_proto_depIdxs = nil
}

View File

@@ -0,0 +1,203 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.6.1
// - protoc v3.20.3
// source: proto/metacrypt/v2/pki.proto
package metacryptv2
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.64.0 or later.
const _ = grpc.SupportPackageIsVersion9
const (
PKIService_GetRootCert_FullMethodName = "/metacrypt.v2.PKIService/GetRootCert"
PKIService_GetChain_FullMethodName = "/metacrypt.v2.PKIService/GetChain"
PKIService_GetIssuerCert_FullMethodName = "/metacrypt.v2.PKIService/GetIssuerCert"
)
// PKIServiceClient is the client API for PKIService 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.
//
// PKIService provides unauthenticated access to public CA certificates.
// These endpoints only require the service to be unsealed.
type PKIServiceClient interface {
GetRootCert(ctx context.Context, in *GetRootCertRequest, opts ...grpc.CallOption) (*GetRootCertResponse, error)
GetChain(ctx context.Context, in *GetChainRequest, opts ...grpc.CallOption) (*GetChainResponse, error)
GetIssuerCert(ctx context.Context, in *GetIssuerCertRequest, opts ...grpc.CallOption) (*GetIssuerCertResponse, error)
}
type pKIServiceClient struct {
cc grpc.ClientConnInterface
}
func NewPKIServiceClient(cc grpc.ClientConnInterface) PKIServiceClient {
return &pKIServiceClient{cc}
}
func (c *pKIServiceClient) GetRootCert(ctx context.Context, in *GetRootCertRequest, opts ...grpc.CallOption) (*GetRootCertResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetRootCertResponse)
err := c.cc.Invoke(ctx, PKIService_GetRootCert_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *pKIServiceClient) GetChain(ctx context.Context, in *GetChainRequest, opts ...grpc.CallOption) (*GetChainResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetChainResponse)
err := c.cc.Invoke(ctx, PKIService_GetChain_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *pKIServiceClient) GetIssuerCert(ctx context.Context, in *GetIssuerCertRequest, opts ...grpc.CallOption) (*GetIssuerCertResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetIssuerCertResponse)
err := c.cc.Invoke(ctx, PKIService_GetIssuerCert_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// PKIServiceServer is the server API for PKIService service.
// All implementations must embed UnimplementedPKIServiceServer
// for forward compatibility.
//
// PKIService provides unauthenticated access to public CA certificates.
// These endpoints only require the service to be unsealed.
type PKIServiceServer interface {
GetRootCert(context.Context, *GetRootCertRequest) (*GetRootCertResponse, error)
GetChain(context.Context, *GetChainRequest) (*GetChainResponse, error)
GetIssuerCert(context.Context, *GetIssuerCertRequest) (*GetIssuerCertResponse, error)
mustEmbedUnimplementedPKIServiceServer()
}
// UnimplementedPKIServiceServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedPKIServiceServer struct{}
func (UnimplementedPKIServiceServer) GetRootCert(context.Context, *GetRootCertRequest) (*GetRootCertResponse, error) {
return nil, status.Error(codes.Unimplemented, "method GetRootCert not implemented")
}
func (UnimplementedPKIServiceServer) GetChain(context.Context, *GetChainRequest) (*GetChainResponse, error) {
return nil, status.Error(codes.Unimplemented, "method GetChain not implemented")
}
func (UnimplementedPKIServiceServer) GetIssuerCert(context.Context, *GetIssuerCertRequest) (*GetIssuerCertResponse, error) {
return nil, status.Error(codes.Unimplemented, "method GetIssuerCert not implemented")
}
func (UnimplementedPKIServiceServer) mustEmbedUnimplementedPKIServiceServer() {}
func (UnimplementedPKIServiceServer) testEmbeddedByValue() {}
// UnsafePKIServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to PKIServiceServer will
// result in compilation errors.
type UnsafePKIServiceServer interface {
mustEmbedUnimplementedPKIServiceServer()
}
func RegisterPKIServiceServer(s grpc.ServiceRegistrar, srv PKIServiceServer) {
// If the following call panics, it indicates UnimplementedPKIServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&PKIService_ServiceDesc, srv)
}
func _PKIService_GetRootCert_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetRootCertRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(PKIServiceServer).GetRootCert(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: PKIService_GetRootCert_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(PKIServiceServer).GetRootCert(ctx, req.(*GetRootCertRequest))
}
return interceptor(ctx, in, info, handler)
}
func _PKIService_GetChain_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetChainRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(PKIServiceServer).GetChain(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: PKIService_GetChain_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(PKIServiceServer).GetChain(ctx, req.(*GetChainRequest))
}
return interceptor(ctx, in, info, handler)
}
func _PKIService_GetIssuerCert_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetIssuerCertRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(PKIServiceServer).GetIssuerCert(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: PKIService_GetIssuerCert_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(PKIServiceServer).GetIssuerCert(ctx, req.(*GetIssuerCertRequest))
}
return interceptor(ctx, in, info, handler)
}
// PKIService_ServiceDesc is the grpc.ServiceDesc for PKIService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var PKIService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "metacrypt.v2.PKIService",
HandlerType: (*PKIServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "GetRootCert",
Handler: _PKIService_GetRootCert_Handler,
},
{
MethodName: "GetChain",
Handler: _PKIService_GetChain_Handler,
},
{
MethodName: "GetIssuerCert",
Handler: _PKIService_GetIssuerCert_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "proto/metacrypt/v2/pki.proto",
}

View File

@@ -0,0 +1,552 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc v3.20.3
// source: proto/metacrypt/v2/policy.proto
package metacryptv2
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
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 PolicyRule struct {
state protoimpl.MessageState `protogen:"open.v1"`
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
Priority int32 `protobuf:"varint,2,opt,name=priority,proto3" json:"priority,omitempty"`
Effect string `protobuf:"bytes,3,opt,name=effect,proto3" json:"effect,omitempty"`
Usernames []string `protobuf:"bytes,4,rep,name=usernames,proto3" json:"usernames,omitempty"`
Roles []string `protobuf:"bytes,5,rep,name=roles,proto3" json:"roles,omitempty"`
Resources []string `protobuf:"bytes,6,rep,name=resources,proto3" json:"resources,omitempty"`
Actions []string `protobuf:"bytes,7,rep,name=actions,proto3" json:"actions,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *PolicyRule) Reset() {
*x = PolicyRule{}
mi := &file_proto_metacrypt_v2_policy_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *PolicyRule) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*PolicyRule) ProtoMessage() {}
func (x *PolicyRule) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_policy_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use PolicyRule.ProtoReflect.Descriptor instead.
func (*PolicyRule) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_policy_proto_rawDescGZIP(), []int{0}
}
func (x *PolicyRule) GetId() string {
if x != nil {
return x.Id
}
return ""
}
func (x *PolicyRule) GetPriority() int32 {
if x != nil {
return x.Priority
}
return 0
}
func (x *PolicyRule) GetEffect() string {
if x != nil {
return x.Effect
}
return ""
}
func (x *PolicyRule) GetUsernames() []string {
if x != nil {
return x.Usernames
}
return nil
}
func (x *PolicyRule) GetRoles() []string {
if x != nil {
return x.Roles
}
return nil
}
func (x *PolicyRule) GetResources() []string {
if x != nil {
return x.Resources
}
return nil
}
func (x *PolicyRule) GetActions() []string {
if x != nil {
return x.Actions
}
return nil
}
type CreatePolicyRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
Rule *PolicyRule `protobuf:"bytes,1,opt,name=rule,proto3" json:"rule,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *CreatePolicyRequest) Reset() {
*x = CreatePolicyRequest{}
mi := &file_proto_metacrypt_v2_policy_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *CreatePolicyRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CreatePolicyRequest) ProtoMessage() {}
func (x *CreatePolicyRequest) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_policy_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CreatePolicyRequest.ProtoReflect.Descriptor instead.
func (*CreatePolicyRequest) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_policy_proto_rawDescGZIP(), []int{1}
}
func (x *CreatePolicyRequest) GetRule() *PolicyRule {
if x != nil {
return x.Rule
}
return nil
}
type CreatePolicyResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
Rule *PolicyRule `protobuf:"bytes,1,opt,name=rule,proto3" json:"rule,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *CreatePolicyResponse) Reset() {
*x = CreatePolicyResponse{}
mi := &file_proto_metacrypt_v2_policy_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *CreatePolicyResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CreatePolicyResponse) ProtoMessage() {}
func (x *CreatePolicyResponse) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_policy_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CreatePolicyResponse.ProtoReflect.Descriptor instead.
func (*CreatePolicyResponse) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_policy_proto_rawDescGZIP(), []int{2}
}
func (x *CreatePolicyResponse) GetRule() *PolicyRule {
if x != nil {
return x.Rule
}
return nil
}
type ListPoliciesRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ListPoliciesRequest) Reset() {
*x = ListPoliciesRequest{}
mi := &file_proto_metacrypt_v2_policy_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListPoliciesRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListPoliciesRequest) ProtoMessage() {}
func (x *ListPoliciesRequest) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_policy_proto_msgTypes[3]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ListPoliciesRequest.ProtoReflect.Descriptor instead.
func (*ListPoliciesRequest) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_policy_proto_rawDescGZIP(), []int{3}
}
type ListPoliciesResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
Rules []*PolicyRule `protobuf:"bytes,1,rep,name=rules,proto3" json:"rules,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ListPoliciesResponse) Reset() {
*x = ListPoliciesResponse{}
mi := &file_proto_metacrypt_v2_policy_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListPoliciesResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListPoliciesResponse) ProtoMessage() {}
func (x *ListPoliciesResponse) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_policy_proto_msgTypes[4]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ListPoliciesResponse.ProtoReflect.Descriptor instead.
func (*ListPoliciesResponse) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_policy_proto_rawDescGZIP(), []int{4}
}
func (x *ListPoliciesResponse) GetRules() []*PolicyRule {
if x != nil {
return x.Rules
}
return nil
}
type GetPolicyRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetPolicyRequest) Reset() {
*x = GetPolicyRequest{}
mi := &file_proto_metacrypt_v2_policy_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetPolicyRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetPolicyRequest) ProtoMessage() {}
func (x *GetPolicyRequest) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_policy_proto_msgTypes[5]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetPolicyRequest.ProtoReflect.Descriptor instead.
func (*GetPolicyRequest) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_policy_proto_rawDescGZIP(), []int{5}
}
func (x *GetPolicyRequest) GetId() string {
if x != nil {
return x.Id
}
return ""
}
type GetPolicyResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
Rule *PolicyRule `protobuf:"bytes,1,opt,name=rule,proto3" json:"rule,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetPolicyResponse) Reset() {
*x = GetPolicyResponse{}
mi := &file_proto_metacrypt_v2_policy_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetPolicyResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetPolicyResponse) ProtoMessage() {}
func (x *GetPolicyResponse) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_policy_proto_msgTypes[6]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetPolicyResponse.ProtoReflect.Descriptor instead.
func (*GetPolicyResponse) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_policy_proto_rawDescGZIP(), []int{6}
}
func (x *GetPolicyResponse) GetRule() *PolicyRule {
if x != nil {
return x.Rule
}
return nil
}
type DeletePolicyRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *DeletePolicyRequest) Reset() {
*x = DeletePolicyRequest{}
mi := &file_proto_metacrypt_v2_policy_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *DeletePolicyRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DeletePolicyRequest) ProtoMessage() {}
func (x *DeletePolicyRequest) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_policy_proto_msgTypes[7]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DeletePolicyRequest.ProtoReflect.Descriptor instead.
func (*DeletePolicyRequest) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_policy_proto_rawDescGZIP(), []int{7}
}
func (x *DeletePolicyRequest) GetId() string {
if x != nil {
return x.Id
}
return ""
}
type DeletePolicyResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *DeletePolicyResponse) Reset() {
*x = DeletePolicyResponse{}
mi := &file_proto_metacrypt_v2_policy_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *DeletePolicyResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DeletePolicyResponse) ProtoMessage() {}
func (x *DeletePolicyResponse) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_policy_proto_msgTypes[8]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DeletePolicyResponse.ProtoReflect.Descriptor instead.
func (*DeletePolicyResponse) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_policy_proto_rawDescGZIP(), []int{8}
}
var File_proto_metacrypt_v2_policy_proto protoreflect.FileDescriptor
const file_proto_metacrypt_v2_policy_proto_rawDesc = "" +
"\n" +
"\x1fproto/metacrypt/v2/policy.proto\x12\fmetacrypt.v2\"\xbc\x01\n" +
"\n" +
"PolicyRule\x12\x0e\n" +
"\x02id\x18\x01 \x01(\tR\x02id\x12\x1a\n" +
"\bpriority\x18\x02 \x01(\x05R\bpriority\x12\x16\n" +
"\x06effect\x18\x03 \x01(\tR\x06effect\x12\x1c\n" +
"\tusernames\x18\x04 \x03(\tR\tusernames\x12\x14\n" +
"\x05roles\x18\x05 \x03(\tR\x05roles\x12\x1c\n" +
"\tresources\x18\x06 \x03(\tR\tresources\x12\x18\n" +
"\aactions\x18\a \x03(\tR\aactions\"C\n" +
"\x13CreatePolicyRequest\x12,\n" +
"\x04rule\x18\x01 \x01(\v2\x18.metacrypt.v2.PolicyRuleR\x04rule\"D\n" +
"\x14CreatePolicyResponse\x12,\n" +
"\x04rule\x18\x01 \x01(\v2\x18.metacrypt.v2.PolicyRuleR\x04rule\"\x15\n" +
"\x13ListPoliciesRequest\"F\n" +
"\x14ListPoliciesResponse\x12.\n" +
"\x05rules\x18\x01 \x03(\v2\x18.metacrypt.v2.PolicyRuleR\x05rules\"\"\n" +
"\x10GetPolicyRequest\x12\x0e\n" +
"\x02id\x18\x01 \x01(\tR\x02id\"A\n" +
"\x11GetPolicyResponse\x12,\n" +
"\x04rule\x18\x01 \x01(\v2\x18.metacrypt.v2.PolicyRuleR\x04rule\"%\n" +
"\x13DeletePolicyRequest\x12\x0e\n" +
"\x02id\x18\x01 \x01(\tR\x02id\"\x16\n" +
"\x14DeletePolicyResponse2\xe2\x02\n" +
"\rPolicyService\x12U\n" +
"\fCreatePolicy\x12!.metacrypt.v2.CreatePolicyRequest\x1a\".metacrypt.v2.CreatePolicyResponse\x12U\n" +
"\fListPolicies\x12!.metacrypt.v2.ListPoliciesRequest\x1a\".metacrypt.v2.ListPoliciesResponse\x12L\n" +
"\tGetPolicy\x12\x1e.metacrypt.v2.GetPolicyRequest\x1a\x1f.metacrypt.v2.GetPolicyResponse\x12U\n" +
"\fDeletePolicy\x12!.metacrypt.v2.DeletePolicyRequest\x1a\".metacrypt.v2.DeletePolicyResponseB>Z<git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v2;metacryptv2b\x06proto3"
var (
file_proto_metacrypt_v2_policy_proto_rawDescOnce sync.Once
file_proto_metacrypt_v2_policy_proto_rawDescData []byte
)
func file_proto_metacrypt_v2_policy_proto_rawDescGZIP() []byte {
file_proto_metacrypt_v2_policy_proto_rawDescOnce.Do(func() {
file_proto_metacrypt_v2_policy_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_proto_metacrypt_v2_policy_proto_rawDesc), len(file_proto_metacrypt_v2_policy_proto_rawDesc)))
})
return file_proto_metacrypt_v2_policy_proto_rawDescData
}
var file_proto_metacrypt_v2_policy_proto_msgTypes = make([]protoimpl.MessageInfo, 9)
var file_proto_metacrypt_v2_policy_proto_goTypes = []any{
(*PolicyRule)(nil), // 0: metacrypt.v2.PolicyRule
(*CreatePolicyRequest)(nil), // 1: metacrypt.v2.CreatePolicyRequest
(*CreatePolicyResponse)(nil), // 2: metacrypt.v2.CreatePolicyResponse
(*ListPoliciesRequest)(nil), // 3: metacrypt.v2.ListPoliciesRequest
(*ListPoliciesResponse)(nil), // 4: metacrypt.v2.ListPoliciesResponse
(*GetPolicyRequest)(nil), // 5: metacrypt.v2.GetPolicyRequest
(*GetPolicyResponse)(nil), // 6: metacrypt.v2.GetPolicyResponse
(*DeletePolicyRequest)(nil), // 7: metacrypt.v2.DeletePolicyRequest
(*DeletePolicyResponse)(nil), // 8: metacrypt.v2.DeletePolicyResponse
}
var file_proto_metacrypt_v2_policy_proto_depIdxs = []int32{
0, // 0: metacrypt.v2.CreatePolicyRequest.rule:type_name -> metacrypt.v2.PolicyRule
0, // 1: metacrypt.v2.CreatePolicyResponse.rule:type_name -> metacrypt.v2.PolicyRule
0, // 2: metacrypt.v2.ListPoliciesResponse.rules:type_name -> metacrypt.v2.PolicyRule
0, // 3: metacrypt.v2.GetPolicyResponse.rule:type_name -> metacrypt.v2.PolicyRule
1, // 4: metacrypt.v2.PolicyService.CreatePolicy:input_type -> metacrypt.v2.CreatePolicyRequest
3, // 5: metacrypt.v2.PolicyService.ListPolicies:input_type -> metacrypt.v2.ListPoliciesRequest
5, // 6: metacrypt.v2.PolicyService.GetPolicy:input_type -> metacrypt.v2.GetPolicyRequest
7, // 7: metacrypt.v2.PolicyService.DeletePolicy:input_type -> metacrypt.v2.DeletePolicyRequest
2, // 8: metacrypt.v2.PolicyService.CreatePolicy:output_type -> metacrypt.v2.CreatePolicyResponse
4, // 9: metacrypt.v2.PolicyService.ListPolicies:output_type -> metacrypt.v2.ListPoliciesResponse
6, // 10: metacrypt.v2.PolicyService.GetPolicy:output_type -> metacrypt.v2.GetPolicyResponse
8, // 11: metacrypt.v2.PolicyService.DeletePolicy:output_type -> metacrypt.v2.DeletePolicyResponse
8, // [8:12] is the sub-list for method output_type
4, // [4:8] is the sub-list for method input_type
4, // [4:4] is the sub-list for extension type_name
4, // [4:4] is the sub-list for extension extendee
0, // [0:4] is the sub-list for field type_name
}
func init() { file_proto_metacrypt_v2_policy_proto_init() }
func file_proto_metacrypt_v2_policy_proto_init() {
if File_proto_metacrypt_v2_policy_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_metacrypt_v2_policy_proto_rawDesc), len(file_proto_metacrypt_v2_policy_proto_rawDesc)),
NumEnums: 0,
NumMessages: 9,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_proto_metacrypt_v2_policy_proto_goTypes,
DependencyIndexes: file_proto_metacrypt_v2_policy_proto_depIdxs,
MessageInfos: file_proto_metacrypt_v2_policy_proto_msgTypes,
}.Build()
File_proto_metacrypt_v2_policy_proto = out.File
file_proto_metacrypt_v2_policy_proto_goTypes = nil
file_proto_metacrypt_v2_policy_proto_depIdxs = nil
}

View File

@@ -0,0 +1,235 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.6.1
// - protoc v3.20.3
// source: proto/metacrypt/v2/policy.proto
package metacryptv2
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.64.0 or later.
const _ = grpc.SupportPackageIsVersion9
const (
PolicyService_CreatePolicy_FullMethodName = "/metacrypt.v2.PolicyService/CreatePolicy"
PolicyService_ListPolicies_FullMethodName = "/metacrypt.v2.PolicyService/ListPolicies"
PolicyService_GetPolicy_FullMethodName = "/metacrypt.v2.PolicyService/GetPolicy"
PolicyService_DeletePolicy_FullMethodName = "/metacrypt.v2.PolicyService/DeletePolicy"
)
// PolicyServiceClient is the client API for PolicyService 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 PolicyServiceClient interface {
CreatePolicy(ctx context.Context, in *CreatePolicyRequest, opts ...grpc.CallOption) (*CreatePolicyResponse, error)
ListPolicies(ctx context.Context, in *ListPoliciesRequest, opts ...grpc.CallOption) (*ListPoliciesResponse, error)
GetPolicy(ctx context.Context, in *GetPolicyRequest, opts ...grpc.CallOption) (*GetPolicyResponse, error)
DeletePolicy(ctx context.Context, in *DeletePolicyRequest, opts ...grpc.CallOption) (*DeletePolicyResponse, error)
}
type policyServiceClient struct {
cc grpc.ClientConnInterface
}
func NewPolicyServiceClient(cc grpc.ClientConnInterface) PolicyServiceClient {
return &policyServiceClient{cc}
}
func (c *policyServiceClient) CreatePolicy(ctx context.Context, in *CreatePolicyRequest, opts ...grpc.CallOption) (*CreatePolicyResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(CreatePolicyResponse)
err := c.cc.Invoke(ctx, PolicyService_CreatePolicy_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *policyServiceClient) ListPolicies(ctx context.Context, in *ListPoliciesRequest, opts ...grpc.CallOption) (*ListPoliciesResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ListPoliciesResponse)
err := c.cc.Invoke(ctx, PolicyService_ListPolicies_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *policyServiceClient) GetPolicy(ctx context.Context, in *GetPolicyRequest, opts ...grpc.CallOption) (*GetPolicyResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetPolicyResponse)
err := c.cc.Invoke(ctx, PolicyService_GetPolicy_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *policyServiceClient) DeletePolicy(ctx context.Context, in *DeletePolicyRequest, opts ...grpc.CallOption) (*DeletePolicyResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(DeletePolicyResponse)
err := c.cc.Invoke(ctx, PolicyService_DeletePolicy_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// PolicyServiceServer is the server API for PolicyService service.
// All implementations must embed UnimplementedPolicyServiceServer
// for forward compatibility.
type PolicyServiceServer interface {
CreatePolicy(context.Context, *CreatePolicyRequest) (*CreatePolicyResponse, error)
ListPolicies(context.Context, *ListPoliciesRequest) (*ListPoliciesResponse, error)
GetPolicy(context.Context, *GetPolicyRequest) (*GetPolicyResponse, error)
DeletePolicy(context.Context, *DeletePolicyRequest) (*DeletePolicyResponse, error)
mustEmbedUnimplementedPolicyServiceServer()
}
// UnimplementedPolicyServiceServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedPolicyServiceServer struct{}
func (UnimplementedPolicyServiceServer) CreatePolicy(context.Context, *CreatePolicyRequest) (*CreatePolicyResponse, error) {
return nil, status.Error(codes.Unimplemented, "method CreatePolicy not implemented")
}
func (UnimplementedPolicyServiceServer) ListPolicies(context.Context, *ListPoliciesRequest) (*ListPoliciesResponse, error) {
return nil, status.Error(codes.Unimplemented, "method ListPolicies not implemented")
}
func (UnimplementedPolicyServiceServer) GetPolicy(context.Context, *GetPolicyRequest) (*GetPolicyResponse, error) {
return nil, status.Error(codes.Unimplemented, "method GetPolicy not implemented")
}
func (UnimplementedPolicyServiceServer) DeletePolicy(context.Context, *DeletePolicyRequest) (*DeletePolicyResponse, error) {
return nil, status.Error(codes.Unimplemented, "method DeletePolicy not implemented")
}
func (UnimplementedPolicyServiceServer) mustEmbedUnimplementedPolicyServiceServer() {}
func (UnimplementedPolicyServiceServer) testEmbeddedByValue() {}
// UnsafePolicyServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to PolicyServiceServer will
// result in compilation errors.
type UnsafePolicyServiceServer interface {
mustEmbedUnimplementedPolicyServiceServer()
}
func RegisterPolicyServiceServer(s grpc.ServiceRegistrar, srv PolicyServiceServer) {
// If the following call panics, it indicates UnimplementedPolicyServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&PolicyService_ServiceDesc, srv)
}
func _PolicyService_CreatePolicy_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CreatePolicyRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(PolicyServiceServer).CreatePolicy(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: PolicyService_CreatePolicy_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(PolicyServiceServer).CreatePolicy(ctx, req.(*CreatePolicyRequest))
}
return interceptor(ctx, in, info, handler)
}
func _PolicyService_ListPolicies_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListPoliciesRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(PolicyServiceServer).ListPolicies(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: PolicyService_ListPolicies_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(PolicyServiceServer).ListPolicies(ctx, req.(*ListPoliciesRequest))
}
return interceptor(ctx, in, info, handler)
}
func _PolicyService_GetPolicy_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetPolicyRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(PolicyServiceServer).GetPolicy(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: PolicyService_GetPolicy_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(PolicyServiceServer).GetPolicy(ctx, req.(*GetPolicyRequest))
}
return interceptor(ctx, in, info, handler)
}
func _PolicyService_DeletePolicy_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DeletePolicyRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(PolicyServiceServer).DeletePolicy(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: PolicyService_DeletePolicy_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(PolicyServiceServer).DeletePolicy(ctx, req.(*DeletePolicyRequest))
}
return interceptor(ctx, in, info, handler)
}
// PolicyService_ServiceDesc is the grpc.ServiceDesc for PolicyService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var PolicyService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "metacrypt.v2.PolicyService",
HandlerType: (*PolicyServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "CreatePolicy",
Handler: _PolicyService_CreatePolicy_Handler,
},
{
MethodName: "ListPolicies",
Handler: _PolicyService_ListPolicies_Handler,
},
{
MethodName: "GetPolicy",
Handler: _PolicyService_GetPolicy_Handler,
},
{
MethodName: "DeletePolicy",
Handler: _PolicyService_DeletePolicy_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "proto/metacrypt/v2/policy.proto",
}

View File

@@ -0,0 +1,446 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc v3.20.3
// source: proto/metacrypt/v2/system.proto
package metacryptv2
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
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 StatusRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *StatusRequest) Reset() {
*x = StatusRequest{}
mi := &file_proto_metacrypt_v2_system_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *StatusRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*StatusRequest) ProtoMessage() {}
func (x *StatusRequest) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_system_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use StatusRequest.ProtoReflect.Descriptor instead.
func (*StatusRequest) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_system_proto_rawDescGZIP(), []int{0}
}
type StatusResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
State string `protobuf:"bytes,1,opt,name=state,proto3" json:"state,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *StatusResponse) Reset() {
*x = StatusResponse{}
mi := &file_proto_metacrypt_v2_system_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *StatusResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*StatusResponse) ProtoMessage() {}
func (x *StatusResponse) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_system_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use StatusResponse.ProtoReflect.Descriptor instead.
func (*StatusResponse) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_system_proto_rawDescGZIP(), []int{1}
}
func (x *StatusResponse) GetState() string {
if x != nil {
return x.State
}
return ""
}
type InitRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
Password string `protobuf:"bytes,1,opt,name=password,proto3" json:"password,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *InitRequest) Reset() {
*x = InitRequest{}
mi := &file_proto_metacrypt_v2_system_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *InitRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*InitRequest) ProtoMessage() {}
func (x *InitRequest) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_system_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use InitRequest.ProtoReflect.Descriptor instead.
func (*InitRequest) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_system_proto_rawDescGZIP(), []int{2}
}
func (x *InitRequest) GetPassword() string {
if x != nil {
return x.Password
}
return ""
}
type InitResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
State string `protobuf:"bytes,1,opt,name=state,proto3" json:"state,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *InitResponse) Reset() {
*x = InitResponse{}
mi := &file_proto_metacrypt_v2_system_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *InitResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*InitResponse) ProtoMessage() {}
func (x *InitResponse) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_system_proto_msgTypes[3]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use InitResponse.ProtoReflect.Descriptor instead.
func (*InitResponse) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_system_proto_rawDescGZIP(), []int{3}
}
func (x *InitResponse) GetState() string {
if x != nil {
return x.State
}
return ""
}
type UnsealRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
Password string `protobuf:"bytes,1,opt,name=password,proto3" json:"password,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *UnsealRequest) Reset() {
*x = UnsealRequest{}
mi := &file_proto_metacrypt_v2_system_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *UnsealRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UnsealRequest) ProtoMessage() {}
func (x *UnsealRequest) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_system_proto_msgTypes[4]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use UnsealRequest.ProtoReflect.Descriptor instead.
func (*UnsealRequest) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_system_proto_rawDescGZIP(), []int{4}
}
func (x *UnsealRequest) GetPassword() string {
if x != nil {
return x.Password
}
return ""
}
type UnsealResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
State string `protobuf:"bytes,1,opt,name=state,proto3" json:"state,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *UnsealResponse) Reset() {
*x = UnsealResponse{}
mi := &file_proto_metacrypt_v2_system_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *UnsealResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UnsealResponse) ProtoMessage() {}
func (x *UnsealResponse) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_system_proto_msgTypes[5]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use UnsealResponse.ProtoReflect.Descriptor instead.
func (*UnsealResponse) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_system_proto_rawDescGZIP(), []int{5}
}
func (x *UnsealResponse) GetState() string {
if x != nil {
return x.State
}
return ""
}
type SealRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *SealRequest) Reset() {
*x = SealRequest{}
mi := &file_proto_metacrypt_v2_system_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *SealRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SealRequest) ProtoMessage() {}
func (x *SealRequest) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_system_proto_msgTypes[6]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use SealRequest.ProtoReflect.Descriptor instead.
func (*SealRequest) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_system_proto_rawDescGZIP(), []int{6}
}
type SealResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
State string `protobuf:"bytes,1,opt,name=state,proto3" json:"state,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *SealResponse) Reset() {
*x = SealResponse{}
mi := &file_proto_metacrypt_v2_system_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *SealResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SealResponse) ProtoMessage() {}
func (x *SealResponse) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_system_proto_msgTypes[7]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use SealResponse.ProtoReflect.Descriptor instead.
func (*SealResponse) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_system_proto_rawDescGZIP(), []int{7}
}
func (x *SealResponse) GetState() string {
if x != nil {
return x.State
}
return ""
}
var File_proto_metacrypt_v2_system_proto protoreflect.FileDescriptor
const file_proto_metacrypt_v2_system_proto_rawDesc = "" +
"\n" +
"\x1fproto/metacrypt/v2/system.proto\x12\fmetacrypt.v2\"\x0f\n" +
"\rStatusRequest\"&\n" +
"\x0eStatusResponse\x12\x14\n" +
"\x05state\x18\x01 \x01(\tR\x05state\")\n" +
"\vInitRequest\x12\x1a\n" +
"\bpassword\x18\x01 \x01(\tR\bpassword\"$\n" +
"\fInitResponse\x12\x14\n" +
"\x05state\x18\x01 \x01(\tR\x05state\"+\n" +
"\rUnsealRequest\x12\x1a\n" +
"\bpassword\x18\x01 \x01(\tR\bpassword\"&\n" +
"\x0eUnsealResponse\x12\x14\n" +
"\x05state\x18\x01 \x01(\tR\x05state\"\r\n" +
"\vSealRequest\"$\n" +
"\fSealResponse\x12\x14\n" +
"\x05state\x18\x01 \x01(\tR\x05state2\x97\x02\n" +
"\rSystemService\x12C\n" +
"\x06Status\x12\x1b.metacrypt.v2.StatusRequest\x1a\x1c.metacrypt.v2.StatusResponse\x12=\n" +
"\x04Init\x12\x19.metacrypt.v2.InitRequest\x1a\x1a.metacrypt.v2.InitResponse\x12C\n" +
"\x06Unseal\x12\x1b.metacrypt.v2.UnsealRequest\x1a\x1c.metacrypt.v2.UnsealResponse\x12=\n" +
"\x04Seal\x12\x19.metacrypt.v2.SealRequest\x1a\x1a.metacrypt.v2.SealResponseB>Z<git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v2;metacryptv2b\x06proto3"
var (
file_proto_metacrypt_v2_system_proto_rawDescOnce sync.Once
file_proto_metacrypt_v2_system_proto_rawDescData []byte
)
func file_proto_metacrypt_v2_system_proto_rawDescGZIP() []byte {
file_proto_metacrypt_v2_system_proto_rawDescOnce.Do(func() {
file_proto_metacrypt_v2_system_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_proto_metacrypt_v2_system_proto_rawDesc), len(file_proto_metacrypt_v2_system_proto_rawDesc)))
})
return file_proto_metacrypt_v2_system_proto_rawDescData
}
var file_proto_metacrypt_v2_system_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
var file_proto_metacrypt_v2_system_proto_goTypes = []any{
(*StatusRequest)(nil), // 0: metacrypt.v2.StatusRequest
(*StatusResponse)(nil), // 1: metacrypt.v2.StatusResponse
(*InitRequest)(nil), // 2: metacrypt.v2.InitRequest
(*InitResponse)(nil), // 3: metacrypt.v2.InitResponse
(*UnsealRequest)(nil), // 4: metacrypt.v2.UnsealRequest
(*UnsealResponse)(nil), // 5: metacrypt.v2.UnsealResponse
(*SealRequest)(nil), // 6: metacrypt.v2.SealRequest
(*SealResponse)(nil), // 7: metacrypt.v2.SealResponse
}
var file_proto_metacrypt_v2_system_proto_depIdxs = []int32{
0, // 0: metacrypt.v2.SystemService.Status:input_type -> metacrypt.v2.StatusRequest
2, // 1: metacrypt.v2.SystemService.Init:input_type -> metacrypt.v2.InitRequest
4, // 2: metacrypt.v2.SystemService.Unseal:input_type -> metacrypt.v2.UnsealRequest
6, // 3: metacrypt.v2.SystemService.Seal:input_type -> metacrypt.v2.SealRequest
1, // 4: metacrypt.v2.SystemService.Status:output_type -> metacrypt.v2.StatusResponse
3, // 5: metacrypt.v2.SystemService.Init:output_type -> metacrypt.v2.InitResponse
5, // 6: metacrypt.v2.SystemService.Unseal:output_type -> metacrypt.v2.UnsealResponse
7, // 7: metacrypt.v2.SystemService.Seal:output_type -> metacrypt.v2.SealResponse
4, // [4:8] is the sub-list for method output_type
0, // [0:4] 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_proto_metacrypt_v2_system_proto_init() }
func file_proto_metacrypt_v2_system_proto_init() {
if File_proto_metacrypt_v2_system_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_metacrypt_v2_system_proto_rawDesc), len(file_proto_metacrypt_v2_system_proto_rawDesc)),
NumEnums: 0,
NumMessages: 8,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_proto_metacrypt_v2_system_proto_goTypes,
DependencyIndexes: file_proto_metacrypt_v2_system_proto_depIdxs,
MessageInfos: file_proto_metacrypt_v2_system_proto_msgTypes,
}.Build()
File_proto_metacrypt_v2_system_proto = out.File
file_proto_metacrypt_v2_system_proto_goTypes = nil
file_proto_metacrypt_v2_system_proto_depIdxs = nil
}

View File

@@ -0,0 +1,235 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.6.1
// - protoc v3.20.3
// source: proto/metacrypt/v2/system.proto
package metacryptv2
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.64.0 or later.
const _ = grpc.SupportPackageIsVersion9
const (
SystemService_Status_FullMethodName = "/metacrypt.v2.SystemService/Status"
SystemService_Init_FullMethodName = "/metacrypt.v2.SystemService/Init"
SystemService_Unseal_FullMethodName = "/metacrypt.v2.SystemService/Unseal"
SystemService_Seal_FullMethodName = "/metacrypt.v2.SystemService/Seal"
)
// SystemServiceClient is the client API for SystemService 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 SystemServiceClient interface {
Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (*StatusResponse, error)
Init(ctx context.Context, in *InitRequest, opts ...grpc.CallOption) (*InitResponse, error)
Unseal(ctx context.Context, in *UnsealRequest, opts ...grpc.CallOption) (*UnsealResponse, error)
Seal(ctx context.Context, in *SealRequest, opts ...grpc.CallOption) (*SealResponse, error)
}
type systemServiceClient struct {
cc grpc.ClientConnInterface
}
func NewSystemServiceClient(cc grpc.ClientConnInterface) SystemServiceClient {
return &systemServiceClient{cc}
}
func (c *systemServiceClient) Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (*StatusResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(StatusResponse)
err := c.cc.Invoke(ctx, SystemService_Status_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *systemServiceClient) Init(ctx context.Context, in *InitRequest, opts ...grpc.CallOption) (*InitResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(InitResponse)
err := c.cc.Invoke(ctx, SystemService_Init_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *systemServiceClient) Unseal(ctx context.Context, in *UnsealRequest, opts ...grpc.CallOption) (*UnsealResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(UnsealResponse)
err := c.cc.Invoke(ctx, SystemService_Unseal_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *systemServiceClient) Seal(ctx context.Context, in *SealRequest, opts ...grpc.CallOption) (*SealResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(SealResponse)
err := c.cc.Invoke(ctx, SystemService_Seal_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// SystemServiceServer is the server API for SystemService service.
// All implementations must embed UnimplementedSystemServiceServer
// for forward compatibility.
type SystemServiceServer interface {
Status(context.Context, *StatusRequest) (*StatusResponse, error)
Init(context.Context, *InitRequest) (*InitResponse, error)
Unseal(context.Context, *UnsealRequest) (*UnsealResponse, error)
Seal(context.Context, *SealRequest) (*SealResponse, error)
mustEmbedUnimplementedSystemServiceServer()
}
// UnimplementedSystemServiceServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedSystemServiceServer struct{}
func (UnimplementedSystemServiceServer) Status(context.Context, *StatusRequest) (*StatusResponse, error) {
return nil, status.Error(codes.Unimplemented, "method Status not implemented")
}
func (UnimplementedSystemServiceServer) Init(context.Context, *InitRequest) (*InitResponse, error) {
return nil, status.Error(codes.Unimplemented, "method Init not implemented")
}
func (UnimplementedSystemServiceServer) Unseal(context.Context, *UnsealRequest) (*UnsealResponse, error) {
return nil, status.Error(codes.Unimplemented, "method Unseal not implemented")
}
func (UnimplementedSystemServiceServer) Seal(context.Context, *SealRequest) (*SealResponse, error) {
return nil, status.Error(codes.Unimplemented, "method Seal not implemented")
}
func (UnimplementedSystemServiceServer) mustEmbedUnimplementedSystemServiceServer() {}
func (UnimplementedSystemServiceServer) testEmbeddedByValue() {}
// UnsafeSystemServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to SystemServiceServer will
// result in compilation errors.
type UnsafeSystemServiceServer interface {
mustEmbedUnimplementedSystemServiceServer()
}
func RegisterSystemServiceServer(s grpc.ServiceRegistrar, srv SystemServiceServer) {
// If the following call panics, it indicates UnimplementedSystemServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&SystemService_ServiceDesc, srv)
}
func _SystemService_Status_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(StatusRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(SystemServiceServer).Status(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: SystemService_Status_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(SystemServiceServer).Status(ctx, req.(*StatusRequest))
}
return interceptor(ctx, in, info, handler)
}
func _SystemService_Init_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(InitRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(SystemServiceServer).Init(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: SystemService_Init_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(SystemServiceServer).Init(ctx, req.(*InitRequest))
}
return interceptor(ctx, in, info, handler)
}
func _SystemService_Unseal_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(UnsealRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(SystemServiceServer).Unseal(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: SystemService_Unseal_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(SystemServiceServer).Unseal(ctx, req.(*UnsealRequest))
}
return interceptor(ctx, in, info, handler)
}
func _SystemService_Seal_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(SealRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(SystemServiceServer).Seal(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: SystemService_Seal_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(SystemServiceServer).Seal(ctx, req.(*SealRequest))
}
return interceptor(ctx, in, info, handler)
}
// SystemService_ServiceDesc is the grpc.ServiceDesc for SystemService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var SystemService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "metacrypt.v2.SystemService",
HandlerType: (*SystemServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Status",
Handler: _SystemService_Status_Handler,
},
{
MethodName: "Init",
Handler: _SystemService_Init_Handler,
},
{
MethodName: "Unseal",
Handler: _SystemService_Unseal_Handler,
},
{
MethodName: "Seal",
Handler: _SystemService_Seal_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "proto/metacrypt/v2/system.proto",
}

View File

@@ -6,8 +6,9 @@ import (
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/timestamppb"
pb "git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v1" pb "git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v2"
internacme "git.wntrmute.dev/kyle/metacrypt/internal/acme" internacme "git.wntrmute.dev/kyle/metacrypt/internal/acme"
"git.wntrmute.dev/kyle/metacrypt/internal/engine" "git.wntrmute.dev/kyle/metacrypt/internal/engine"
) )
@@ -46,7 +47,7 @@ func (as *acmeServer) SetConfig(ctx context.Context, req *pb.SetConfigRequest) (
as.s.logger.Error("grpc: acme set config", "error", err) as.s.logger.Error("grpc: acme set config", "error", err)
return nil, status.Error(codes.Internal, "failed to save config") return nil, status.Error(codes.Internal, "failed to save config")
} }
return &pb.SetConfigResponse{Ok: true}, nil return &pb.SetConfigResponse{}, nil
} }
func (as *acmeServer) ListAccounts(ctx context.Context, req *pb.ListAccountsRequest) (*pb.ListAccountsResponse, error) { func (as *acmeServer) ListAccounts(ctx context.Context, req *pb.ListAccountsRequest) (*pb.ListAccountsResponse, error) {
@@ -68,7 +69,7 @@ func (as *acmeServer) ListAccounts(ctx context.Context, req *pb.ListAccountsRequ
Status: a.Status, Status: a.Status,
Contact: contacts, Contact: contacts,
MciasUsername: a.MCIASUsername, MciasUsername: a.MCIASUsername,
CreatedAt: a.CreatedAt.String(), CreatedAt: timestamppb.New(a.CreatedAt),
}) })
} }
return &pb.ListAccountsResponse{Accounts: pbAccounts}, nil return &pb.ListAccountsResponse{Accounts: pbAccounts}, nil
@@ -95,8 +96,8 @@ func (as *acmeServer) ListOrders(ctx context.Context, req *pb.ListOrdersRequest)
AccountId: o.AccountID, AccountId: o.AccountID,
Status: o.Status, Status: o.Status,
Identifiers: identifiers, Identifiers: identifiers,
CreatedAt: o.CreatedAt.String(), CreatedAt: timestamppb.New(o.CreatedAt),
ExpiresAt: o.ExpiresAt.String(), ExpiresAt: timestamppb.New(o.ExpiresAt),
}) })
} }
return &pb.ListOrdersResponse{Orders: pbOrders}, nil return &pb.ListOrdersResponse{Orders: pbOrders}, nil

View File

@@ -2,13 +2,15 @@ package grpcserver
import ( import (
"context" "context"
"time"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/timestamppb"
mcias "git.wntrmute.dev/kyle/mcias/clients/go" mcias "git.wntrmute.dev/kyle/mcias/clients/go"
pb "git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v1" pb "git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v2"
) )
type authServer struct { type authServer struct {
@@ -17,10 +19,14 @@ type authServer struct {
} }
func (as *authServer) Login(_ context.Context, req *pb.LoginRequest) (*pb.LoginResponse, error) { func (as *authServer) Login(_ context.Context, req *pb.LoginRequest) (*pb.LoginResponse, error) {
token, expiresAt, err := as.s.auth.Login(req.Username, req.Password, req.TotpCode) token, expiresAtStr, err := as.s.auth.Login(req.Username, req.Password, req.TotpCode)
if err != nil { if err != nil {
return nil, status.Error(codes.Unauthenticated, "invalid credentials") return nil, status.Error(codes.Unauthenticated, "invalid credentials")
} }
var expiresAt *timestamppb.Timestamp
if t, err := time.Parse(time.RFC3339, expiresAtStr); err == nil {
expiresAt = timestamppb.New(t)
}
return &pb.LoginResponse{Token: token, ExpiresAt: expiresAt}, nil return &pb.LoginResponse{Token: token, ExpiresAt: expiresAt}, nil
} }

432
internal/grpcserver/ca.go Normal file
View File

@@ -0,0 +1,432 @@
package grpcserver
import (
"context"
"errors"
"strings"
"time"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/timestamppb"
pb "git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v2"
"git.wntrmute.dev/kyle/metacrypt/internal/engine"
"git.wntrmute.dev/kyle/metacrypt/internal/engine/ca"
)
type caServer struct {
pb.UnimplementedCAServiceServer
s *GRPCServer
}
// caHandleRequest is a helper that dispatches a CA engine request and maps
// common errors to gRPC status codes.
func (cs *caServer) caHandleRequest(ctx context.Context, mount, operation string, req *engine.Request) (*engine.Response, error) {
resp, err := cs.s.engines.HandleRequest(ctx, mount, req)
if err != nil {
st := codes.Internal
switch {
case errors.Is(err, engine.ErrMountNotFound):
st = codes.NotFound
case errors.Is(err, ca.ErrIssuerNotFound):
st = codes.NotFound
case errors.Is(err, ca.ErrCertNotFound):
st = codes.NotFound
case errors.Is(err, ca.ErrIssuerExists):
st = codes.AlreadyExists
case errors.Is(err, ca.ErrUnauthorized):
st = codes.Unauthenticated
case errors.Is(err, ca.ErrForbidden):
st = codes.PermissionDenied
case strings.Contains(err.Error(), "not found"):
st = codes.NotFound
}
cs.s.logger.Error("grpc: ca "+operation, "mount", mount, "error", err)
return nil, status.Error(st, err.Error())
}
return resp, nil
}
func (cs *caServer) callerInfo(ctx context.Context) *engine.CallerInfo {
ti := tokenInfoFromContext(ctx)
if ti == nil {
return nil
}
return &engine.CallerInfo{
Username: ti.Username,
Roles: ti.Roles,
IsAdmin: ti.IsAdmin,
}
}
func (cs *caServer) ImportRoot(ctx context.Context, req *pb.ImportRootRequest) (*pb.ImportRootResponse, error) {
if req.Mount == "" {
return nil, status.Error(codes.InvalidArgument, "mount is required")
}
resp, err := cs.caHandleRequest(ctx, req.Mount, "import-root", &engine.Request{
Operation: "import-root",
CallerInfo: cs.callerInfo(ctx),
Data: map[string]interface{}{
"cert_pem": string(req.CertPem),
"key_pem": string(req.KeyPem),
},
})
if err != nil {
return nil, err
}
cn, _ := resp.Data["cn"].(string)
var expiresAt *timestamppb.Timestamp
if s, ok := resp.Data["expires_at"].(string); ok {
if t, err := time.Parse(time.RFC3339, s); err == nil {
expiresAt = timestamppb.New(t)
}
}
return &pb.ImportRootResponse{CommonName: cn, ExpiresAt: expiresAt}, nil
}
func (cs *caServer) GetRoot(ctx context.Context, req *pb.GetRootRequest) (*pb.GetRootResponse, error) {
if req.Mount == "" {
return nil, status.Error(codes.InvalidArgument, "mount is required")
}
resp, err := cs.caHandleRequest(ctx, req.Mount, "get-root", &engine.Request{
Operation: "get-root",
})
if err != nil {
return nil, err
}
certPEM, _ := resp.Data["cert_pem"].(string)
return &pb.GetRootResponse{CertPem: []byte(certPEM)}, nil
}
func (cs *caServer) CreateIssuer(ctx context.Context, req *pb.CreateIssuerRequest) (*pb.CreateIssuerResponse, error) {
if req.Mount == "" || req.Name == "" {
return nil, status.Error(codes.InvalidArgument, "mount and name are required")
}
data := map[string]interface{}{
"name": req.Name,
}
if req.KeyAlgorithm != "" {
data["key_algorithm"] = req.KeyAlgorithm
}
if req.KeySize != 0 {
data["key_size"] = float64(req.KeySize)
}
if req.Expiry != "" {
data["expiry"] = req.Expiry
}
if req.MaxTtl != "" {
data["max_ttl"] = req.MaxTtl
}
resp, err := cs.caHandleRequest(ctx, req.Mount, "create-issuer", &engine.Request{
Operation: "create-issuer",
CallerInfo: cs.callerInfo(ctx),
Data: data,
})
if err != nil {
return nil, err
}
name, _ := resp.Data["name"].(string)
certPEM, _ := resp.Data["cert_pem"].(string)
return &pb.CreateIssuerResponse{Name: name, CertPem: []byte(certPEM)}, nil
}
func (cs *caServer) DeleteIssuer(ctx context.Context, req *pb.DeleteIssuerRequest) (*pb.DeleteIssuerResponse, error) {
if req.Mount == "" || req.Name == "" {
return nil, status.Error(codes.InvalidArgument, "mount and name are required")
}
_, err := cs.caHandleRequest(ctx, req.Mount, "delete-issuer", &engine.Request{
Operation: "delete-issuer",
CallerInfo: cs.callerInfo(ctx),
Data: map[string]interface{}{"name": req.Name},
})
if err != nil {
return nil, err
}
return &pb.DeleteIssuerResponse{}, nil
}
func (cs *caServer) ListIssuers(ctx context.Context, req *pb.ListIssuersRequest) (*pb.ListIssuersResponse, error) {
if req.Mount == "" {
return nil, status.Error(codes.InvalidArgument, "mount is required")
}
resp, err := cs.caHandleRequest(ctx, req.Mount, "list-issuers", &engine.Request{
Operation: "list-issuers",
CallerInfo: cs.callerInfo(ctx),
})
if err != nil {
return nil, err
}
raw, _ := resp.Data["issuers"].([]interface{})
issuers := make([]string, 0, len(raw))
for _, v := range raw {
if s, ok := v.(string); ok {
issuers = append(issuers, s)
}
}
return &pb.ListIssuersResponse{Issuers: issuers}, nil
}
func (cs *caServer) GetIssuer(ctx context.Context, req *pb.GetIssuerRequest) (*pb.GetIssuerResponse, error) {
if req.Mount == "" || req.Name == "" {
return nil, status.Error(codes.InvalidArgument, "mount and name are required")
}
resp, err := cs.caHandleRequest(ctx, req.Mount, "get-issuer", &engine.Request{
Operation: "get-issuer",
Path: req.Name,
})
if err != nil {
return nil, err
}
certPEM, _ := resp.Data["cert_pem"].(string)
return &pb.GetIssuerResponse{CertPem: []byte(certPEM)}, nil
}
func (cs *caServer) GetChain(ctx context.Context, req *pb.CAServiceGetChainRequest) (*pb.CAServiceGetChainResponse, error) {
if req.Mount == "" || req.Issuer == "" {
return nil, status.Error(codes.InvalidArgument, "mount and issuer are required")
}
resp, err := cs.caHandleRequest(ctx, req.Mount, "get-chain", &engine.Request{
Operation: "get-chain",
Data: map[string]interface{}{"issuer": req.Issuer},
})
if err != nil {
return nil, err
}
chainPEM, _ := resp.Data["chain_pem"].(string)
return &pb.CAServiceGetChainResponse{ChainPem: []byte(chainPEM)}, nil
}
func (cs *caServer) IssueCert(ctx context.Context, req *pb.IssueCertRequest) (*pb.IssueCertResponse, error) {
if req.Mount == "" || req.Issuer == "" {
return nil, status.Error(codes.InvalidArgument, "mount and issuer are required")
}
data := map[string]interface{}{
"issuer": req.Issuer,
}
if req.Profile != "" {
data["profile"] = req.Profile
}
if req.CommonName != "" {
data["common_name"] = req.CommonName
}
if len(req.DnsNames) > 0 {
dns := make([]interface{}, len(req.DnsNames))
for i, v := range req.DnsNames {
dns[i] = v
}
data["dns_names"] = dns
}
if len(req.IpAddresses) > 0 {
ips := make([]interface{}, len(req.IpAddresses))
for i, v := range req.IpAddresses {
ips[i] = v
}
data["ip_addresses"] = ips
}
if req.Ttl != "" {
data["ttl"] = req.Ttl
}
if req.KeyAlgorithm != "" {
data["key_algorithm"] = req.KeyAlgorithm
}
if req.KeySize != 0 {
data["key_size"] = float64(req.KeySize)
}
if len(req.KeyUsages) > 0 {
ku := make([]interface{}, len(req.KeyUsages))
for i, v := range req.KeyUsages {
ku[i] = v
}
data["key_usages"] = ku
}
if len(req.ExtKeyUsages) > 0 {
eku := make([]interface{}, len(req.ExtKeyUsages))
for i, v := range req.ExtKeyUsages {
eku[i] = v
}
data["ext_key_usages"] = eku
}
resp, err := cs.caHandleRequest(ctx, req.Mount, "issue", &engine.Request{
Operation: "issue",
CallerInfo: cs.callerInfo(ctx),
Data: data,
})
if err != nil {
return nil, err
}
serial, _ := resp.Data["serial"].(string)
cn, _ := resp.Data["cn"].(string)
issuedBy, _ := resp.Data["issued_by"].(string)
certPEM, _ := resp.Data["cert_pem"].(string)
keyPEM, _ := resp.Data["key_pem"].(string)
chainPEM, _ := resp.Data["chain_pem"].(string)
sans := toStringSliceFromInterface(resp.Data["sans"])
var expiresAt *timestamppb.Timestamp
if s, ok := resp.Data["expires_at"].(string); ok {
if t, err := time.Parse(time.RFC3339, s); err == nil {
expiresAt = timestamppb.New(t)
}
}
return &pb.IssueCertResponse{
Serial: serial,
CommonName: cn,
Sans: sans,
IssuedBy: issuedBy,
ExpiresAt: expiresAt,
CertPem: []byte(certPEM),
KeyPem: []byte(keyPEM),
ChainPem: []byte(chainPEM),
}, nil
}
func (cs *caServer) GetCert(ctx context.Context, req *pb.GetCertRequest) (*pb.GetCertResponse, error) {
if req.Mount == "" || req.Serial == "" {
return nil, status.Error(codes.InvalidArgument, "mount and serial are required")
}
resp, err := cs.caHandleRequest(ctx, req.Mount, "get-cert", &engine.Request{
Operation: "get-cert",
CallerInfo: cs.callerInfo(ctx),
Data: map[string]interface{}{"serial": req.Serial},
})
if err != nil {
return nil, err
}
rec := certRecordFromData(resp.Data)
return &pb.GetCertResponse{Cert: rec}, nil
}
func (cs *caServer) ListCerts(ctx context.Context, req *pb.ListCertsRequest) (*pb.ListCertsResponse, error) {
if req.Mount == "" {
return nil, status.Error(codes.InvalidArgument, "mount is required")
}
resp, err := cs.caHandleRequest(ctx, req.Mount, "list-certs", &engine.Request{
Operation: "list-certs",
CallerInfo: cs.callerInfo(ctx),
})
if err != nil {
return nil, err
}
raw, _ := resp.Data["certs"].([]interface{})
summaries := make([]*pb.CertSummary, 0, len(raw))
for _, item := range raw {
m, ok := item.(map[string]interface{})
if !ok {
continue
}
summaries = append(summaries, certSummaryFromData(m))
}
return &pb.ListCertsResponse{Certs: summaries}, nil
}
func (cs *caServer) RenewCert(ctx context.Context, req *pb.RenewCertRequest) (*pb.RenewCertResponse, error) {
if req.Mount == "" || req.Serial == "" {
return nil, status.Error(codes.InvalidArgument, "mount and serial are required")
}
resp, err := cs.caHandleRequest(ctx, req.Mount, "renew", &engine.Request{
Operation: "renew",
CallerInfo: cs.callerInfo(ctx),
Data: map[string]interface{}{"serial": req.Serial},
})
if err != nil {
return nil, err
}
serial, _ := resp.Data["serial"].(string)
cn, _ := resp.Data["cn"].(string)
issuedBy, _ := resp.Data["issued_by"].(string)
certPEM, _ := resp.Data["cert_pem"].(string)
keyPEM, _ := resp.Data["key_pem"].(string)
chainPEM, _ := resp.Data["chain_pem"].(string)
sans := toStringSliceFromInterface(resp.Data["sans"])
var expiresAt *timestamppb.Timestamp
if s, ok := resp.Data["expires_at"].(string); ok {
if t, err := time.Parse(time.RFC3339, s); err == nil {
expiresAt = timestamppb.New(t)
}
}
return &pb.RenewCertResponse{
Serial: serial,
CommonName: cn,
Sans: sans,
IssuedBy: issuedBy,
ExpiresAt: expiresAt,
CertPem: []byte(certPEM),
KeyPem: []byte(keyPEM),
ChainPem: []byte(chainPEM),
}, nil
}
// --- helpers ---
func certRecordFromData(d map[string]interface{}) *pb.CertRecord {
serial, _ := d["serial"].(string)
issuer, _ := d["issuer"].(string)
cn, _ := d["cn"].(string)
profile, _ := d["profile"].(string)
issuedBy, _ := d["issued_by"].(string)
certPEM, _ := d["cert_pem"].(string)
sans := toStringSliceFromInterface(d["sans"])
var issuedAt, expiresAt *timestamppb.Timestamp
if s, ok := d["issued_at"].(string); ok {
if t, err := time.Parse(time.RFC3339, s); err == nil {
issuedAt = timestamppb.New(t)
}
}
if s, ok := d["expires_at"].(string); ok {
if t, err := time.Parse(time.RFC3339, s); err == nil {
expiresAt = timestamppb.New(t)
}
}
return &pb.CertRecord{
Serial: serial,
Issuer: issuer,
CommonName: cn,
Sans: sans,
Profile: profile,
IssuedBy: issuedBy,
IssuedAt: issuedAt,
ExpiresAt: expiresAt,
CertPem: []byte(certPEM),
}
}
func certSummaryFromData(d map[string]interface{}) *pb.CertSummary {
serial, _ := d["serial"].(string)
issuer, _ := d["issuer"].(string)
cn, _ := d["cn"].(string)
profile, _ := d["profile"].(string)
issuedBy, _ := d["issued_by"].(string)
var issuedAt, expiresAt *timestamppb.Timestamp
if s, ok := d["issued_at"].(string); ok {
if t, err := time.Parse(time.RFC3339, s); err == nil {
issuedAt = timestamppb.New(t)
}
}
if s, ok := d["expires_at"].(string); ok {
if t, err := time.Parse(time.RFC3339, s); err == nil {
expiresAt = timestamppb.New(t)
}
}
return &pb.CertSummary{
Serial: serial,
Issuer: issuer,
CommonName: cn,
Profile: profile,
IssuedBy: issuedBy,
IssuedAt: issuedAt,
ExpiresAt: expiresAt,
}
}
func toStringSliceFromInterface(v interface{}) []string {
raw, _ := v.([]interface{})
out := make([]string, 0, len(raw))
for _, item := range raw {
if s, ok := item.(string); ok {
out = append(out, s)
}
}
return out
}

View File

@@ -3,13 +3,11 @@ package grpcserver
import ( import (
"context" "context"
"errors" "errors"
"strings"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/structpb"
pb "git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v1" pb "git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v2"
"git.wntrmute.dev/kyle/metacrypt/internal/engine" "git.wntrmute.dev/kyle/metacrypt/internal/engine"
) )
@@ -24,8 +22,11 @@ func (es *engineServer) Mount(ctx context.Context, req *pb.MountRequest) (*pb.Mo
} }
var config map[string]interface{} var config map[string]interface{}
if req.Config != nil { if len(req.Config) > 0 {
config = req.Config.AsMap() config = make(map[string]interface{}, len(req.Config))
for k, v := range req.Config {
config[k] = v
}
} }
if err := es.s.engines.Mount(ctx, req.Name, engine.EngineType(req.Type), config); err != nil { if err := es.s.engines.Mount(ctx, req.Name, engine.EngineType(req.Type), config); err != nil {
@@ -68,53 +69,3 @@ func (es *engineServer) ListMounts(_ context.Context, _ *pb.ListMountsRequest) (
return &pb.ListMountsResponse{Mounts: pbMounts}, nil return &pb.ListMountsResponse{Mounts: pbMounts}, nil
} }
func (es *engineServer) Execute(ctx context.Context, req *pb.ExecuteRequest) (*pb.ExecuteResponse, error) {
if req.Mount == "" || req.Operation == "" {
return nil, status.Error(codes.InvalidArgument, "mount and operation are required")
}
ti := tokenInfoFromContext(ctx)
engReq := &engine.Request{
Operation: req.Operation,
Path: req.Path,
Data: nil,
}
if req.Data != nil {
engReq.Data = req.Data.AsMap()
}
if ti != nil {
engReq.CallerInfo = &engine.CallerInfo{
Username: ti.Username,
Roles: ti.Roles,
IsAdmin: ti.IsAdmin,
}
}
username := ""
if ti != nil {
username = ti.Username
}
es.s.logger.Info("grpc: engine execute", "mount", req.Mount, "operation", req.Operation, "username", username)
resp, err := es.s.engines.HandleRequest(ctx, req.Mount, engReq)
if err != nil {
st := codes.Internal
switch {
case errors.Is(err, engine.ErrMountNotFound):
st = codes.NotFound
case strings.Contains(err.Error(), "forbidden"):
st = codes.PermissionDenied
case strings.Contains(err.Error(), "not found"):
st = codes.NotFound
}
es.s.logger.Error("grpc: engine execute failed", "mount", req.Mount, "operation", req.Operation, "username", username, "error", err)
return nil, status.Error(st, err.Error())
}
es.s.logger.Info("grpc: engine execute ok", "mount", req.Mount, "operation", req.Operation, "username", username)
pbData, err := structpb.NewStruct(resp.Data)
if err != nil {
return nil, status.Error(codes.Internal, "failed to encode response")
}
return &pb.ExecuteResponse{Data: pbData}, nil
}

View File

@@ -0,0 +1,720 @@
package grpcserver
import (
"context"
"log/slog"
"path/filepath"
"testing"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
pb "git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v2"
"git.wntrmute.dev/kyle/metacrypt/internal/auth"
"git.wntrmute.dev/kyle/metacrypt/internal/barrier"
"git.wntrmute.dev/kyle/metacrypt/internal/config"
"git.wntrmute.dev/kyle/metacrypt/internal/crypto"
"git.wntrmute.dev/kyle/metacrypt/internal/db"
"git.wntrmute.dev/kyle/metacrypt/internal/engine"
"git.wntrmute.dev/kyle/metacrypt/internal/policy"
"git.wntrmute.dev/kyle/metacrypt/internal/seal"
)
// ---- test helpers ----
func fastArgon2Params() crypto.Argon2Params {
return crypto.Argon2Params{Time: 1, Memory: 64 * 1024, Threads: 1}
}
// mockBarrier is a no-op barrier for engine registry tests.
type mockBarrier struct{}
func (m *mockBarrier) Unseal(_ []byte) error { return nil }
func (m *mockBarrier) Seal() error { return nil }
func (m *mockBarrier) IsSealed() bool { return false }
func (m *mockBarrier) Get(_ context.Context, _ string) ([]byte, error) { return nil, barrier.ErrNotFound }
func (m *mockBarrier) Put(_ context.Context, _ string, _ []byte) error { return nil }
func (m *mockBarrier) Delete(_ context.Context, _ string) error { return nil }
func (m *mockBarrier) List(_ context.Context, _ string) ([]string, error) { return nil, nil }
// mockEngine is a minimal engine.Engine for registry tests.
type mockEngine struct{ t engine.EngineType }
func (m *mockEngine) Type() engine.EngineType { return m.t }
func (m *mockEngine) Initialize(_ context.Context, _ barrier.Barrier, _ string, _ map[string]interface{}) error {
return nil
}
func (m *mockEngine) Unseal(_ context.Context, _ barrier.Barrier, _ string) error { return nil }
func (m *mockEngine) Seal() error { return nil }
func (m *mockEngine) HandleRequest(_ context.Context, _ *engine.Request) (*engine.Response, error) {
return &engine.Response{Data: map[string]interface{}{"ok": true}}, nil
}
func newTestRegistry() *engine.Registry {
reg := engine.NewRegistry(&mockBarrier{}, slog.Default())
reg.RegisterFactory(engine.EngineTypeTransit, func() engine.Engine {
return &mockEngine{t: engine.EngineTypeTransit}
})
return reg
}
func newTestGRPCServer(t *testing.T) (*GRPCServer, func()) {
t.Helper()
dir := t.TempDir()
database, err := db.Open(filepath.Join(dir, "test.db"))
if err != nil {
t.Fatalf("open db: %v", err)
}
if err := db.Migrate(database); err != nil {
t.Fatalf("migrate: %v", err)
}
b := barrier.NewAESGCMBarrier(database)
sealMgr := seal.NewManager(database, b, slog.Default())
policyEngine := policy.NewEngine(b)
reg := newTestRegistry()
authenticator := auth.NewAuthenticator(nil, slog.Default())
cfg := &config.Config{
Seal: config.SealConfig{
Argon2Time: 1,
Argon2Memory: 64 * 1024,
Argon2Threads: 1,
},
}
srv := New(cfg, sealMgr, authenticator, policyEngine, reg, slog.Default())
return srv, func() { _ = database.Close() }
}
// okHandler is a grpc.UnaryHandler that always succeeds.
func okHandler(_ context.Context, _ interface{}) (interface{}, error) {
return "ok", nil
}
func methodInfo(name string) *grpc.UnaryServerInfo {
return &grpc.UnaryServerInfo{FullMethod: name}
}
// ---- interceptor tests ----
func TestSealInterceptor_Unsealed(t *testing.T) {
srv, cleanup := newTestGRPCServer(t)
defer cleanup()
// Initialize and unseal so state == StateUnsealed.
if err := srv.sealMgr.Initialize(context.Background(), []byte("pw"), fastArgon2Params()); err != nil {
t.Fatalf("initialize: %v", err)
}
methods := map[string]bool{"/test.Service/Method": true}
interceptor := sealInterceptor(srv.sealMgr, slog.Default(), methods)
resp, err := interceptor(context.Background(), nil, methodInfo("/test.Service/Method"), okHandler)
if err != nil {
t.Fatalf("expected success when unsealed, got: %v", err)
}
if resp != "ok" {
t.Errorf("expected 'ok', got %v", resp)
}
}
func TestSealInterceptor_Sealed(t *testing.T) {
srv, cleanup := newTestGRPCServer(t)
defer cleanup()
// Initialize then seal.
if err := srv.sealMgr.Initialize(context.Background(), []byte("pw"), fastArgon2Params()); err != nil {
t.Fatalf("initialize: %v", err)
}
if err := srv.sealMgr.Seal(); err != nil {
t.Fatalf("seal: %v", err)
}
methods := map[string]bool{"/test.Service/Method": true}
interceptor := sealInterceptor(srv.sealMgr, slog.Default(), methods)
_, err := interceptor(context.Background(), nil, methodInfo("/test.Service/Method"), okHandler)
if err == nil {
t.Fatal("expected error when sealed")
}
if code := status.Code(err); code != codes.FailedPrecondition {
t.Errorf("expected FailedPrecondition, got %v", code)
}
}
func TestSealInterceptor_SkipsUnlistedMethod(t *testing.T) {
srv, cleanup := newTestGRPCServer(t)
defer cleanup()
// State is uninitialized (sealed), but method is not in the list.
methods := map[string]bool{"/test.Service/Other": true}
interceptor := sealInterceptor(srv.sealMgr, slog.Default(), methods)
resp, err := interceptor(context.Background(), nil, methodInfo("/test.Service/Method"), okHandler)
if err != nil {
t.Fatalf("expected pass-through, got: %v", err)
}
if resp != "ok" {
t.Errorf("expected 'ok', got %v", resp)
}
}
func TestAuthInterceptor_MissingToken(t *testing.T) {
authenticator := auth.NewAuthenticator(nil, slog.Default())
methods := map[string]bool{"/test.Service/Method": true}
interceptor := authInterceptor(authenticator, slog.Default(), methods)
_, err := interceptor(context.Background(), nil, methodInfo("/test.Service/Method"), okHandler)
if err == nil {
t.Fatal("expected error for missing token")
}
if code := status.Code(err); code != codes.Unauthenticated {
t.Errorf("expected Unauthenticated, got %v", code)
}
}
func TestAuthInterceptor_SkipsUnlistedMethod(t *testing.T) {
authenticator := auth.NewAuthenticator(nil, slog.Default())
methods := map[string]bool{"/test.Service/Other": true}
interceptor := authInterceptor(authenticator, slog.Default(), methods)
resp, err := interceptor(context.Background(), nil, methodInfo("/test.Service/Method"), okHandler)
if err != nil {
t.Fatalf("expected pass-through, got: %v", err)
}
if resp != "ok" {
t.Errorf("expected 'ok', got %v", resp)
}
}
func TestAdminInterceptor_NoTokenInfo(t *testing.T) {
methods := map[string]bool{"/test.Service/Admin": true}
interceptor := adminInterceptor(slog.Default(), methods)
_, err := interceptor(context.Background(), nil, methodInfo("/test.Service/Admin"), okHandler)
if err == nil {
t.Fatal("expected error when no token info in context")
}
if code := status.Code(err); code != codes.PermissionDenied {
t.Errorf("expected PermissionDenied, got %v", code)
}
}
func TestAdminInterceptor_NonAdmin(t *testing.T) {
methods := map[string]bool{"/test.Service/Admin": true}
interceptor := adminInterceptor(slog.Default(), methods)
ctx := context.WithValue(context.Background(), tokenInfoKey, &auth.TokenInfo{
Username: "user",
IsAdmin: false,
})
_, err := interceptor(ctx, nil, methodInfo("/test.Service/Admin"), okHandler)
if err == nil {
t.Fatal("expected error for non-admin")
}
if code := status.Code(err); code != codes.PermissionDenied {
t.Errorf("expected PermissionDenied, got %v", code)
}
}
func TestAdminInterceptor_Admin(t *testing.T) {
methods := map[string]bool{"/test.Service/Admin": true}
interceptor := adminInterceptor(slog.Default(), methods)
ctx := context.WithValue(context.Background(), tokenInfoKey, &auth.TokenInfo{
Username: "admin",
IsAdmin: true,
})
resp, err := interceptor(ctx, nil, methodInfo("/test.Service/Admin"), okHandler)
if err != nil {
t.Fatalf("expected success for admin, got: %v", err)
}
if resp != "ok" {
t.Errorf("expected 'ok', got %v", resp)
}
}
func TestAdminInterceptor_SkipsUnlistedMethod(t *testing.T) {
methods := map[string]bool{"/test.Service/Other": true}
interceptor := adminInterceptor(slog.Default(), methods)
// No token info in context — but method not listed, so should pass through.
resp, err := interceptor(context.Background(), nil, methodInfo("/test.Service/Method"), okHandler)
if err != nil {
t.Fatalf("expected pass-through, got: %v", err)
}
if resp != "ok" {
t.Errorf("expected 'ok', got %v", resp)
}
}
func TestChainInterceptors(t *testing.T) {
var order []int
makeInterceptor := func(n int) grpc.UnaryServerInterceptor {
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
order = append(order, n)
return handler(ctx, req)
}
}
chained := chainInterceptors(makeInterceptor(1), makeInterceptor(2), makeInterceptor(3))
_, err := chained(context.Background(), nil, methodInfo("/test/Method"), okHandler)
if err != nil {
t.Fatalf("chain: %v", err)
}
if len(order) != 3 || order[0] != 1 || order[1] != 2 || order[2] != 3 {
t.Errorf("expected execution order [1 2 3], got %v", order)
}
}
func TestExtractToken(t *testing.T) {
tests := []struct {
name string
md metadata.MD
expected string
}{
{"no metadata", nil, ""},
{"no authorization", metadata.Pairs("other", "val"), ""},
{"bearer token", metadata.Pairs("authorization", "Bearer mytoken"), "mytoken"},
{"raw token", metadata.Pairs("authorization", "mytoken"), "mytoken"},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
var ctx context.Context
if tc.md != nil {
ctx = metadata.NewIncomingContext(context.Background(), tc.md)
} else {
ctx = context.Background()
}
got := extractToken(ctx)
if got != tc.expected {
t.Errorf("extractToken: got %q, want %q", got, tc.expected)
}
})
}
}
// ---- systemServer tests ----
func TestSystemStatus(t *testing.T) {
srv, cleanup := newTestGRPCServer(t)
defer cleanup()
ss := &systemServer{s: srv}
resp, err := ss.Status(context.Background(), &pb.StatusRequest{})
if err != nil {
t.Fatalf("Status: %v", err)
}
if resp.State != "uninitialized" {
t.Errorf("expected 'uninitialized', got %q", resp.State)
}
}
func TestSystemInit_EmptyPassword(t *testing.T) {
srv, cleanup := newTestGRPCServer(t)
defer cleanup()
ss := &systemServer{s: srv}
_, err := ss.Init(context.Background(), &pb.InitRequest{Password: ""})
if err == nil {
t.Fatal("expected error for empty password")
}
if code := status.Code(err); code != codes.InvalidArgument {
t.Errorf("expected InvalidArgument, got %v", code)
}
}
func TestSystemInit_Success(t *testing.T) {
srv, cleanup := newTestGRPCServer(t)
defer cleanup()
ss := &systemServer{s: srv}
resp, err := ss.Init(context.Background(), &pb.InitRequest{Password: "testpassword"})
if err != nil {
t.Fatalf("Init: %v", err)
}
if resp.State != "unsealed" {
t.Errorf("expected 'unsealed' after init, got %q", resp.State)
}
}
func TestSystemInit_AlreadyInitialized(t *testing.T) {
srv, cleanup := newTestGRPCServer(t)
defer cleanup()
ss := &systemServer{s: srv}
if _, err := ss.Init(context.Background(), &pb.InitRequest{Password: "pw"}); err != nil {
t.Fatalf("first Init: %v", err)
}
_, err := ss.Init(context.Background(), &pb.InitRequest{Password: "pw"})
if err == nil {
t.Fatal("expected error on second Init")
}
if code := status.Code(err); code != codes.AlreadyExists {
t.Errorf("expected AlreadyExists, got %v", code)
}
}
func TestSystemUnseal_NotInitialized(t *testing.T) {
srv, cleanup := newTestGRPCServer(t)
defer cleanup()
ss := &systemServer{s: srv}
_, err := ss.Unseal(context.Background(), &pb.UnsealRequest{Password: "pw"})
if err == nil {
t.Fatal("expected error when not initialized")
}
if code := status.Code(err); code != codes.FailedPrecondition {
t.Errorf("expected FailedPrecondition, got %v", code)
}
}
func TestSystemUnseal_InvalidPassword(t *testing.T) {
srv, cleanup := newTestGRPCServer(t)
defer cleanup()
ss := &systemServer{s: srv}
if _, err := ss.Init(context.Background(), &pb.InitRequest{Password: "correct"}); err != nil {
t.Fatalf("Init: %v", err)
}
if err := srv.sealMgr.Seal(); err != nil {
t.Fatalf("Seal: %v", err)
}
_, err := ss.Unseal(context.Background(), &pb.UnsealRequest{Password: "wrong"})
if err == nil {
t.Fatal("expected error for wrong password")
}
if code := status.Code(err); code != codes.Unauthenticated {
t.Errorf("expected Unauthenticated, got %v", code)
}
}
func TestSystemUnseal_Success(t *testing.T) {
srv, cleanup := newTestGRPCServer(t)
defer cleanup()
ss := &systemServer{s: srv}
if _, err := ss.Init(context.Background(), &pb.InitRequest{Password: "pw"}); err != nil {
t.Fatalf("Init: %v", err)
}
if err := srv.sealMgr.Seal(); err != nil {
t.Fatalf("Seal: %v", err)
}
resp, err := ss.Unseal(context.Background(), &pb.UnsealRequest{Password: "pw"})
if err != nil {
t.Fatalf("Unseal: %v", err)
}
if resp.State != "unsealed" {
t.Errorf("expected 'unsealed', got %q", resp.State)
}
}
func TestSystemSeal_Success(t *testing.T) {
srv, cleanup := newTestGRPCServer(t)
defer cleanup()
ss := &systemServer{s: srv}
if _, err := ss.Init(context.Background(), &pb.InitRequest{Password: "pw"}); err != nil {
t.Fatalf("Init: %v", err)
}
resp, err := ss.Seal(context.Background(), &pb.SealRequest{})
if err != nil {
t.Fatalf("Seal: %v", err)
}
if resp.State != "sealed" {
t.Errorf("expected 'sealed', got %q", resp.State)
}
}
// ---- engineServer tests ----
func TestEngineMount_MissingFields(t *testing.T) {
srv, cleanup := newTestGRPCServer(t)
defer cleanup()
es := &engineServer{s: srv}
_, err := es.Mount(context.Background(), &pb.MountRequest{Name: "", Type: "transit"})
if code := status.Code(err); code != codes.InvalidArgument {
t.Errorf("empty name: expected InvalidArgument, got %v", code)
}
_, err = es.Mount(context.Background(), &pb.MountRequest{Name: "default", Type: ""})
if code := status.Code(err); code != codes.InvalidArgument {
t.Errorf("empty type: expected InvalidArgument, got %v", code)
}
}
func TestEngineMount_UnknownType(t *testing.T) {
srv, cleanup := newTestGRPCServer(t)
defer cleanup()
es := &engineServer{s: srv}
_, err := es.Mount(context.Background(), &pb.MountRequest{Name: "test", Type: "unknown"})
if err == nil {
t.Fatal("expected error for unknown engine type")
}
if code := status.Code(err); code != codes.InvalidArgument {
t.Errorf("expected InvalidArgument, got %v", code)
}
}
func TestEngineMount_Success(t *testing.T) {
srv, cleanup := newTestGRPCServer(t)
defer cleanup()
es := &engineServer{s: srv}
_, err := es.Mount(context.Background(), &pb.MountRequest{Name: "default", Type: "transit"})
if err != nil {
t.Fatalf("Mount: %v", err)
}
}
func TestEngineMount_Duplicate(t *testing.T) {
srv, cleanup := newTestGRPCServer(t)
defer cleanup()
es := &engineServer{s: srv}
if _, err := es.Mount(context.Background(), &pb.MountRequest{Name: "default", Type: "transit"}); err != nil {
t.Fatalf("first Mount: %v", err)
}
_, err := es.Mount(context.Background(), &pb.MountRequest{Name: "default", Type: "transit"})
if err == nil {
t.Fatal("expected error for duplicate mount")
}
if code := status.Code(err); code != codes.AlreadyExists {
t.Errorf("expected AlreadyExists, got %v", code)
}
}
func TestEngineUnmount_MissingName(t *testing.T) {
srv, cleanup := newTestGRPCServer(t)
defer cleanup()
es := &engineServer{s: srv}
_, err := es.Unmount(context.Background(), &pb.UnmountRequest{Name: ""})
if code := status.Code(err); code != codes.InvalidArgument {
t.Errorf("expected InvalidArgument, got %v", code)
}
}
func TestEngineUnmount_NotFound(t *testing.T) {
srv, cleanup := newTestGRPCServer(t)
defer cleanup()
es := &engineServer{s: srv}
_, err := es.Unmount(context.Background(), &pb.UnmountRequest{Name: "nonexistent"})
if code := status.Code(err); code != codes.NotFound {
t.Errorf("expected NotFound, got %v", code)
}
}
func TestEngineUnmount_Success(t *testing.T) {
srv, cleanup := newTestGRPCServer(t)
defer cleanup()
es := &engineServer{s: srv}
if _, err := es.Mount(context.Background(), &pb.MountRequest{Name: "default", Type: "transit"}); err != nil {
t.Fatalf("Mount: %v", err)
}
if _, err := es.Unmount(context.Background(), &pb.UnmountRequest{Name: "default"}); err != nil {
t.Fatalf("Unmount: %v", err)
}
}
func TestEngineListMounts(t *testing.T) {
srv, cleanup := newTestGRPCServer(t)
defer cleanup()
es := &engineServer{s: srv}
resp, err := es.ListMounts(context.Background(), &pb.ListMountsRequest{})
if err != nil {
t.Fatalf("ListMounts: %v", err)
}
if len(resp.Mounts) != 0 {
t.Errorf("expected 0 mounts, got %d", len(resp.Mounts))
}
if _, err := es.Mount(context.Background(), &pb.MountRequest{Name: "eng1", Type: "transit"}); err != nil {
t.Fatalf("Mount: %v", err)
}
resp, err = es.ListMounts(context.Background(), &pb.ListMountsRequest{})
if err != nil {
t.Fatalf("ListMounts after mount: %v", err)
}
if len(resp.Mounts) != 1 {
t.Errorf("expected 1 mount, got %d", len(resp.Mounts))
}
if resp.Mounts[0].Name != "eng1" {
t.Errorf("mount name: got %q, want %q", resp.Mounts[0].Name, "eng1")
}
}
// ---- policyServer tests ----
func TestPolicyCreate_MissingID(t *testing.T) {
srv, cleanup := newTestGRPCServer(t)
defer cleanup()
ps := &policyServer{s: srv}
_, err := ps.CreatePolicy(context.Background(), &pb.CreatePolicyRequest{
Rule: &pb.PolicyRule{Id: ""},
})
if code := status.Code(err); code != codes.InvalidArgument {
t.Errorf("expected InvalidArgument, got %v", code)
}
}
func TestPolicyCreate_NilRule(t *testing.T) {
srv, cleanup := newTestGRPCServer(t)
defer cleanup()
ps := &policyServer{s: srv}
_, err := ps.CreatePolicy(context.Background(), &pb.CreatePolicyRequest{Rule: nil})
if code := status.Code(err); code != codes.InvalidArgument {
t.Errorf("expected InvalidArgument, got %v", code)
}
}
func TestPolicyRoundtrip(t *testing.T) {
srv, cleanup := newTestGRPCServer(t)
defer cleanup()
// Policy engine needs an unsealed barrier; unseal it via the seal manager.
if err := srv.sealMgr.Initialize(context.Background(), []byte("pw"), fastArgon2Params()); err != nil {
t.Fatalf("initialize: %v", err)
}
ps := &policyServer{s: srv}
rule := &pb.PolicyRule{
Id: "rule-1",
Priority: 10,
Effect: "allow",
Usernames: []string{"alice"},
Resources: []string{"/ca/*"},
Actions: []string{"read"},
}
// Create.
createResp, err := ps.CreatePolicy(context.Background(), &pb.CreatePolicyRequest{Rule: rule})
if err != nil {
t.Fatalf("CreatePolicy: %v", err)
}
if createResp.Rule.Id != "rule-1" {
t.Errorf("created rule id: got %q, want %q", createResp.Rule.Id, "rule-1")
}
// Get.
getResp, err := ps.GetPolicy(context.Background(), &pb.GetPolicyRequest{Id: "rule-1"})
if err != nil {
t.Fatalf("GetPolicy: %v", err)
}
if getResp.Rule.Id != "rule-1" {
t.Errorf("get rule id: got %q, want %q", getResp.Rule.Id, "rule-1")
}
// List.
listResp, err := ps.ListPolicies(context.Background(), &pb.ListPoliciesRequest{})
if err != nil {
t.Fatalf("ListPolicies: %v", err)
}
if len(listResp.Rules) != 1 {
t.Errorf("expected 1 rule, got %d", len(listResp.Rules))
}
// Delete.
if _, err := ps.DeletePolicy(context.Background(), &pb.DeletePolicyRequest{Id: "rule-1"}); err != nil {
t.Fatalf("DeletePolicy: %v", err)
}
// Get after delete should fail.
_, err = ps.GetPolicy(context.Background(), &pb.GetPolicyRequest{Id: "rule-1"})
if code := status.Code(err); code != codes.NotFound {
t.Errorf("expected NotFound after delete, got %v", code)
}
}
func TestPolicyGet_MissingID(t *testing.T) {
srv, cleanup := newTestGRPCServer(t)
defer cleanup()
ps := &policyServer{s: srv}
_, err := ps.GetPolicy(context.Background(), &pb.GetPolicyRequest{Id: ""})
if code := status.Code(err); code != codes.InvalidArgument {
t.Errorf("expected InvalidArgument, got %v", code)
}
}
func TestPolicyDelete_MissingID(t *testing.T) {
srv, cleanup := newTestGRPCServer(t)
defer cleanup()
ps := &policyServer{s: srv}
_, err := ps.DeletePolicy(context.Background(), &pb.DeletePolicyRequest{Id: ""})
if code := status.Code(err); code != codes.InvalidArgument {
t.Errorf("expected InvalidArgument, got %v", code)
}
}
// ---- authServer tests ----
func TestAuthTokenInfo_FromContext(t *testing.T) {
srv, cleanup := newTestGRPCServer(t)
defer cleanup()
as := &authServer{s: srv}
ti := &auth.TokenInfo{Username: "alice", Roles: []string{"user"}, IsAdmin: false}
ctx := context.WithValue(context.Background(), tokenInfoKey, ti)
resp, err := as.TokenInfo(ctx, &pb.TokenInfoRequest{})
if err != nil {
t.Fatalf("TokenInfo: %v", err)
}
if resp.Username != "alice" {
t.Errorf("username: got %q, want %q", resp.Username, "alice")
}
if resp.IsAdmin {
t.Error("expected IsAdmin=false")
}
}
// ---- pbToRule / ruleToPB conversion tests ----
func TestPbToRuleRoundtrip(t *testing.T) {
original := &pb.PolicyRule{
Id: "test-rule",
Priority: 5,
Effect: "deny",
Usernames: []string{"bob"},
Roles: []string{"operator"},
Resources: []string{"/pki/*"},
Actions: []string{"write", "delete"},
}
rule := pbToRule(original)
if rule.ID != original.Id {
t.Errorf("ID: got %q, want %q", rule.ID, original.Id)
}
if rule.Priority != int(original.Priority) {
t.Errorf("Priority: got %d, want %d", rule.Priority, original.Priority)
}
if string(rule.Effect) != original.Effect {
t.Errorf("Effect: got %q, want %q", rule.Effect, original.Effect)
}
back := ruleToPB(rule)
if back.Id != original.Id {
t.Errorf("roundtrip Id: got %q, want %q", back.Id, original.Id)
}
if back.Priority != original.Priority {
t.Errorf("roundtrip Priority: got %d, want %d", back.Priority, original.Priority)
}
if back.Effect != original.Effect {
t.Errorf("roundtrip Effect: got %q, want %q", back.Effect, original.Effect)
}
}

View File

@@ -7,7 +7,7 @@ import (
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
pb "git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v1" pb "git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v2"
"git.wntrmute.dev/kyle/metacrypt/internal/engine" "git.wntrmute.dev/kyle/metacrypt/internal/engine"
"git.wntrmute.dev/kyle/metacrypt/internal/engine/ca" "git.wntrmute.dev/kyle/metacrypt/internal/engine/ca"
) )

View File

@@ -6,7 +6,7 @@ import (
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
pb "git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v1" pb "git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v2"
"git.wntrmute.dev/kyle/metacrypt/internal/policy" "git.wntrmute.dev/kyle/metacrypt/internal/policy"
) )

View File

@@ -11,7 +11,7 @@ import (
"google.golang.org/grpc" "google.golang.org/grpc"
"google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials"
pb "git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v1" pb "git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v2"
internacme "git.wntrmute.dev/kyle/metacrypt/internal/acme" internacme "git.wntrmute.dev/kyle/metacrypt/internal/acme"
"git.wntrmute.dev/kyle/metacrypt/internal/auth" "git.wntrmute.dev/kyle/metacrypt/internal/auth"
"git.wntrmute.dev/kyle/metacrypt/internal/config" "git.wntrmute.dev/kyle/metacrypt/internal/config"
@@ -79,6 +79,7 @@ func (s *GRPCServer) Start() error {
pb.RegisterAuthServiceServer(s.srv, &authServer{s: s}) pb.RegisterAuthServiceServer(s.srv, &authServer{s: s})
pb.RegisterEngineServiceServer(s.srv, &engineServer{s: s}) pb.RegisterEngineServiceServer(s.srv, &engineServer{s: s})
pb.RegisterPKIServiceServer(s.srv, &pkiServer{s: s}) pb.RegisterPKIServiceServer(s.srv, &pkiServer{s: s})
pb.RegisterCAServiceServer(s.srv, &caServer{s: s})
pb.RegisterPolicyServiceServer(s.srv, &policyServer{s: s}) pb.RegisterPolicyServiceServer(s.srv, &policyServer{s: s})
pb.RegisterACMEServiceServer(s.srv, &acmeServer{s: s}) pb.RegisterACMEServiceServer(s.srv, &acmeServer{s: s})
@@ -105,57 +106,77 @@ func (s *GRPCServer) Shutdown() {
// to be unsealed. // to be unsealed.
func sealRequiredMethods() map[string]bool { func sealRequiredMethods() map[string]bool {
return map[string]bool{ return map[string]bool{
"/metacrypt.v1.AuthService/Login": true, "/metacrypt.v2.AuthService/Login": true,
"/metacrypt.v1.AuthService/Logout": true, "/metacrypt.v2.AuthService/Logout": true,
"/metacrypt.v1.AuthService/TokenInfo": true, "/metacrypt.v2.AuthService/TokenInfo": true,
"/metacrypt.v1.EngineService/Mount": true, "/metacrypt.v2.EngineService/Mount": true,
"/metacrypt.v1.EngineService/Unmount": true, "/metacrypt.v2.EngineService/Unmount": true,
"/metacrypt.v1.EngineService/ListMounts": true, "/metacrypt.v2.EngineService/ListMounts": true,
"/metacrypt.v1.EngineService/Execute": true, "/metacrypt.v2.PKIService/GetRootCert": true,
"/metacrypt.v1.PKIService/GetRootCert": true, "/metacrypt.v2.PKIService/GetChain": true,
"/metacrypt.v1.PKIService/GetChain": true, "/metacrypt.v2.PKIService/GetIssuerCert": true,
"/metacrypt.v1.PKIService/GetIssuerCert": true, "/metacrypt.v2.CAService/ImportRoot": true,
"/metacrypt.v1.PolicyService/CreatePolicy": true, "/metacrypt.v2.CAService/GetRoot": true,
"/metacrypt.v1.PolicyService/ListPolicies": true, "/metacrypt.v2.CAService/CreateIssuer": true,
"/metacrypt.v1.PolicyService/GetPolicy": true, "/metacrypt.v2.CAService/DeleteIssuer": true,
"/metacrypt.v1.PolicyService/DeletePolicy": true, "/metacrypt.v2.CAService/ListIssuers": true,
"/metacrypt.v1.ACMEService/CreateEAB": true, "/metacrypt.v2.CAService/GetIssuer": true,
"/metacrypt.v1.ACMEService/SetConfig": true, "/metacrypt.v2.CAService/GetChain": true,
"/metacrypt.v1.ACMEService/ListAccounts": true, "/metacrypt.v2.CAService/IssueCert": true,
"/metacrypt.v1.ACMEService/ListOrders": true, "/metacrypt.v2.CAService/GetCert": true,
"/metacrypt.v2.CAService/ListCerts": true,
"/metacrypt.v2.CAService/RenewCert": true,
"/metacrypt.v2.PolicyService/CreatePolicy": true,
"/metacrypt.v2.PolicyService/ListPolicies": true,
"/metacrypt.v2.PolicyService/GetPolicy": true,
"/metacrypt.v2.PolicyService/DeletePolicy": true,
"/metacrypt.v2.ACMEService/CreateEAB": true,
"/metacrypt.v2.ACMEService/SetConfig": true,
"/metacrypt.v2.ACMEService/ListAccounts": true,
"/metacrypt.v2.ACMEService/ListOrders": true,
} }
} }
// authRequiredMethods returns the set of RPC full names that require a valid token. // authRequiredMethods returns the set of RPC full names that require a valid token.
func authRequiredMethods() map[string]bool { func authRequiredMethods() map[string]bool {
return map[string]bool{ return map[string]bool{
"/metacrypt.v1.AuthService/Logout": true, "/metacrypt.v2.AuthService/Logout": true,
"/metacrypt.v1.AuthService/TokenInfo": true, "/metacrypt.v2.AuthService/TokenInfo": true,
"/metacrypt.v1.EngineService/Mount": true, "/metacrypt.v2.EngineService/Mount": true,
"/metacrypt.v1.EngineService/Unmount": true, "/metacrypt.v2.EngineService/Unmount": true,
"/metacrypt.v1.EngineService/ListMounts": true, "/metacrypt.v2.EngineService/ListMounts": true,
"/metacrypt.v1.EngineService/Execute": true, "/metacrypt.v2.CAService/ImportRoot": true,
"/metacrypt.v1.PolicyService/CreatePolicy": true, "/metacrypt.v2.CAService/CreateIssuer": true,
"/metacrypt.v1.PolicyService/ListPolicies": true, "/metacrypt.v2.CAService/DeleteIssuer": true,
"/metacrypt.v1.PolicyService/GetPolicy": true, "/metacrypt.v2.CAService/ListIssuers": true,
"/metacrypt.v1.PolicyService/DeletePolicy": true, "/metacrypt.v2.CAService/IssueCert": true,
"/metacrypt.v1.ACMEService/CreateEAB": true, "/metacrypt.v2.CAService/GetCert": true,
"/metacrypt.v1.ACMEService/SetConfig": true, "/metacrypt.v2.CAService/ListCerts": true,
"/metacrypt.v1.ACMEService/ListAccounts": true, "/metacrypt.v2.CAService/RenewCert": true,
"/metacrypt.v1.ACMEService/ListOrders": true, "/metacrypt.v2.PolicyService/CreatePolicy": true,
"/metacrypt.v2.PolicyService/ListPolicies": true,
"/metacrypt.v2.PolicyService/GetPolicy": true,
"/metacrypt.v2.PolicyService/DeletePolicy": true,
"/metacrypt.v2.ACMEService/CreateEAB": true,
"/metacrypt.v2.ACMEService/SetConfig": true,
"/metacrypt.v2.ACMEService/ListAccounts": true,
"/metacrypt.v2.ACMEService/ListOrders": true,
} }
} }
// adminRequiredMethods returns the set of RPC full names that require admin. // adminRequiredMethods returns the set of RPC full names that require admin.
func adminRequiredMethods() map[string]bool { func adminRequiredMethods() map[string]bool {
return map[string]bool{ return map[string]bool{
"/metacrypt.v1.SystemService/Seal": true, "/metacrypt.v2.SystemService/Seal": true,
"/metacrypt.v1.EngineService/Mount": true, "/metacrypt.v2.EngineService/Mount": true,
"/metacrypt.v1.EngineService/Unmount": true, "/metacrypt.v2.EngineService/Unmount": true,
"/metacrypt.v1.PolicyService/CreatePolicy": true, "/metacrypt.v2.CAService/ImportRoot": true,
"/metacrypt.v1.PolicyService/DeletePolicy": true, "/metacrypt.v2.CAService/CreateIssuer": true,
"/metacrypt.v1.ACMEService/SetConfig": true, "/metacrypt.v2.CAService/DeleteIssuer": true,
"/metacrypt.v1.ACMEService/ListAccounts": true, "/metacrypt.v2.PolicyService/CreatePolicy": true,
"/metacrypt.v1.ACMEService/ListOrders": true, "/metacrypt.v2.PolicyService/DeletePolicy": true,
"/metacrypt.v2.ACMEService/SetConfig": true,
"/metacrypt.v2.ACMEService/ListAccounts": true,
"/metacrypt.v2.ACMEService/ListOrders": true,
} }
} }

View File

@@ -7,7 +7,7 @@ import (
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
pb "git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v1" pb "git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v2"
"git.wntrmute.dev/kyle/metacrypt/internal/crypto" "git.wntrmute.dev/kyle/metacrypt/internal/crypto"
"git.wntrmute.dev/kyle/metacrypt/internal/seal" "git.wntrmute.dev/kyle/metacrypt/internal/seal"
) )

View File

@@ -96,15 +96,19 @@ func (s *Server) handleUnseal(w http.ResponseWriter, r *http.Request) {
if err := s.seal.Unseal([]byte(req.Password)); err != nil { if err := s.seal.Unseal([]byte(req.Password)); err != nil {
if errors.Is(err, seal.ErrNotInitialized) { if errors.Is(err, seal.ErrNotInitialized) {
s.logger.Warn("unseal attempt on uninitialized service", "remote_addr", r.RemoteAddr)
http.Error(w, `{"error":"not initialized"}`, http.StatusPreconditionFailed) http.Error(w, `{"error":"not initialized"}`, http.StatusPreconditionFailed)
} else if errors.Is(err, seal.ErrInvalidPassword) { } else if errors.Is(err, seal.ErrInvalidPassword) {
s.logger.Warn("unseal attempt with invalid password", "remote_addr", r.RemoteAddr)
http.Error(w, `{"error":"invalid password"}`, http.StatusUnauthorized) http.Error(w, `{"error":"invalid password"}`, http.StatusUnauthorized)
} else if errors.Is(err, seal.ErrRateLimited) { } else if errors.Is(err, seal.ErrRateLimited) {
s.logger.Warn("unseal attempt rate limited", "remote_addr", r.RemoteAddr)
http.Error(w, `{"error":"too many attempts, try again later"}`, http.StatusTooManyRequests) http.Error(w, `{"error":"too many attempts, try again later"}`, http.StatusTooManyRequests)
} else if errors.Is(err, seal.ErrNotSealed) { } else if errors.Is(err, seal.ErrNotSealed) {
s.logger.Warn("unseal attempt on already-unsealed service", "remote_addr", r.RemoteAddr)
http.Error(w, `{"error":"already unsealed"}`, http.StatusConflict) http.Error(w, `{"error":"already unsealed"}`, http.StatusConflict)
} else { } else {
s.logger.Error("unseal failed", "error", err) s.logger.Error("unseal failed", "remote_addr", r.RemoteAddr, "error", err)
http.Error(w, `{"error":"unseal failed"}`, http.StatusInternalServerError) http.Error(w, `{"error":"unseal failed"}`, http.StatusInternalServerError)
} }
return return
@@ -116,6 +120,7 @@ func (s *Server) handleUnseal(w http.ResponseWriter, r *http.Request) {
return return
} }
s.logger.Info("service unsealed", "remote_addr", r.RemoteAddr)
writeJSON(w, http.StatusOK, map[string]interface{}{ writeJSON(w, http.StatusOK, map[string]interface{}{
"state": s.seal.State().String(), "state": s.seal.State().String(),
}) })

View File

@@ -12,7 +12,7 @@ import (
"google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials"
"google.golang.org/grpc/metadata" "google.golang.org/grpc/metadata"
pb "git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v1" pb "git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v2"
) )
// VaultClient wraps the gRPC stubs for communicating with the vault. // VaultClient wraps the gRPC stubs for communicating with the vault.
@@ -22,6 +22,7 @@ type VaultClient struct {
auth pb.AuthServiceClient auth pb.AuthServiceClient
engine pb.EngineServiceClient engine pb.EngineServiceClient
pki pb.PKIServiceClient pki pb.PKIServiceClient
ca pb.CAServiceClient
} }
// NewVaultClient dials the vault gRPC server and returns a client. // NewVaultClient dials the vault gRPC server and returns a client.
@@ -58,6 +59,7 @@ func NewVaultClient(addr, caCertPath string, logger *slog.Logger) (*VaultClient,
auth: pb.NewAuthServiceClient(conn), auth: pb.NewAuthServiceClient(conn),
engine: pb.NewEngineServiceClient(conn), engine: pb.NewEngineServiceClient(conn),
pki: pb.NewPKIServiceClient(conn), pki: pb.NewPKIServiceClient(conn),
ca: pb.NewCAServiceClient(conn),
}, nil }, nil
} }
@@ -156,39 +158,16 @@ func (c *VaultClient) Mount(ctx context.Context, token, name, engineType string,
Type: engineType, Type: engineType,
} }
if len(config) > 0 { if len(config) > 0 {
s, err := structFromMap(config) cfg := make(map[string]string, len(config))
if err != nil { for k, v := range config {
return fmt.Errorf("webserver: encode mount config: %w", err) cfg[k] = fmt.Sprintf("%v", v)
} }
req.Config = s req.Config = cfg
} }
_, err := c.engine.Mount(withToken(ctx, token), req) _, err := c.engine.Mount(withToken(ctx, token), req)
return err return err
} }
// EngineRequest sends a generic engine operation to the vault.
func (c *VaultClient) EngineRequest(ctx context.Context, token, mount, operation string, data map[string]interface{}) (map[string]interface{}, error) {
req := &pb.ExecuteRequest{
Mount: mount,
Operation: operation,
}
if len(data) > 0 {
s, err := structFromMap(data)
if err != nil {
return nil, fmt.Errorf("webserver: encode engine request: %w", err)
}
req.Data = s
}
resp, err := c.engine.Execute(withToken(ctx, token), req)
if err != nil {
return nil, err
}
if resp.Data == nil {
return nil, nil
}
return resp.Data.AsMap(), nil
}
// GetRootCert returns the root CA certificate PEM for the given mount. // GetRootCert returns the root CA certificate PEM for the given mount.
func (c *VaultClient) GetRootCert(ctx context.Context, mount string) ([]byte, error) { func (c *VaultClient) GetRootCert(ctx context.Context, mount string) ([]byte, error) {
resp, err := c.pki.GetRootCert(ctx, &pb.GetRootCertRequest{Mount: mount}) resp, err := c.pki.GetRootCert(ctx, &pb.GetRootCertRequest{Mount: mount})
@@ -206,3 +185,126 @@ func (c *VaultClient) GetIssuerCert(ctx context.Context, mount, issuer string) (
} }
return resp.CertPem, nil return resp.CertPem, nil
} }
// ImportRoot imports an existing root CA certificate and key into the given mount.
func (c *VaultClient) ImportRoot(ctx context.Context, token, mount, certPEM, keyPEM string) error {
_, err := c.ca.ImportRoot(withToken(ctx, token), &pb.ImportRootRequest{
Mount: mount,
CertPem: []byte(certPEM),
KeyPem: []byte(keyPEM),
})
return err
}
// CreateIssuerRequest holds parameters for creating an intermediate CA issuer.
type CreateIssuerRequest struct {
Mount string
Name string
KeyAlgorithm string
KeySize int32
Expiry string
MaxTTL string
}
// CreateIssuer creates a new intermediate CA issuer on the given mount.
func (c *VaultClient) CreateIssuer(ctx context.Context, token string, req CreateIssuerRequest) error {
_, err := c.ca.CreateIssuer(withToken(ctx, token), &pb.CreateIssuerRequest{
Mount: req.Mount,
Name: req.Name,
KeyAlgorithm: req.KeyAlgorithm,
KeySize: req.KeySize,
Expiry: req.Expiry,
MaxTtl: req.MaxTTL,
})
return err
}
// ListIssuers returns the names of all issuers for the given mount.
func (c *VaultClient) ListIssuers(ctx context.Context, token, mount string) ([]string, error) {
resp, err := c.ca.ListIssuers(withToken(ctx, token), &pb.ListIssuersRequest{Mount: mount})
if err != nil {
return nil, err
}
return resp.Issuers, nil
}
// IssueCertRequest holds parameters for issuing a leaf certificate.
type IssueCertRequest struct {
Mount string
Issuer string
Profile string
CommonName string
DNSNames []string
IPAddresses []string
TTL string
KeyUsages []string
ExtKeyUsages []string
}
// IssuedCert holds the result of a certificate issuance.
type IssuedCert struct {
Serial string
CertPEM string
KeyPEM string
ChainPEM string
ExpiresAt string
}
// IssueCert issues a new leaf certificate from the named issuer.
func (c *VaultClient) IssueCert(ctx context.Context, token string, req IssueCertRequest) (*IssuedCert, error) {
resp, err := c.ca.IssueCert(withToken(ctx, token), &pb.IssueCertRequest{
Mount: req.Mount,
Issuer: req.Issuer,
Profile: req.Profile,
CommonName: req.CommonName,
DnsNames: req.DNSNames,
IpAddresses: req.IPAddresses,
Ttl: req.TTL,
KeyUsages: req.KeyUsages,
ExtKeyUsages: req.ExtKeyUsages,
})
if err != nil {
return nil, err
}
issued := &IssuedCert{
Serial: resp.Serial,
CertPEM: string(resp.CertPem),
KeyPEM: string(resp.KeyPem),
ChainPEM: string(resp.ChainPem),
}
if resp.ExpiresAt != nil {
issued.ExpiresAt = resp.ExpiresAt.AsTime().Format("2006-01-02T15:04:05Z")
}
return issued, nil
}
// CertSummary holds lightweight certificate metadata for list views.
type CertSummary struct {
Serial string
Issuer string
CommonName string
Profile string
ExpiresAt string
}
// ListCerts returns all certificate summaries for the given mount.
func (c *VaultClient) ListCerts(ctx context.Context, token, mount string) ([]CertSummary, error) {
resp, err := c.ca.ListCerts(withToken(ctx, token), &pb.ListCertsRequest{Mount: mount})
if err != nil {
return nil, err
}
certs := make([]CertSummary, 0, len(resp.Certs))
for _, s := range resp.Certs {
cs := CertSummary{
Serial: s.Serial,
Issuer: s.Issuer,
CommonName: s.CommonName,
Profile: s.Profile,
}
if s.ExpiresAt != nil {
cs.ExpiresAt = s.ExpiresAt.AsTime().Format("2006-01-02T15:04:05Z")
}
certs = append(certs, cs)
}
return certs, nil
}

View File

@@ -280,8 +280,8 @@ func (ws *WebServer) handlePKI(w http.ResponseWriter, r *http.Request) {
} }
} }
if resp, err := ws.vault.EngineRequest(r.Context(), token, mountName, "list-issuers", nil); err == nil { if issuers, err := ws.vault.ListIssuers(r.Context(), token, mountName); err == nil {
data["Issuers"] = resp["issuers"] data["Issuers"] = issuers
} }
ws.renderTemplate(w, "pki.html", data) ws.renderTemplate(w, "pki.html", data)
@@ -329,11 +329,7 @@ func (ws *WebServer) handleImportRoot(w http.ResponseWriter, r *http.Request) {
return return
} }
_, err = ws.vault.EngineRequest(r.Context(), token, mountName, "import-root", map[string]interface{}{ if err = ws.vault.ImportRoot(r.Context(), token, mountName, certPEM, keyPEM); err != nil {
"cert_pem": certPEM,
"key_pem": keyPEM,
})
if err != nil {
ws.renderPKIWithError(w, r, mountName, info, grpcMessage(err)) ws.renderPKIWithError(w, r, mountName, info, grpcMessage(err))
return return
} }
@@ -362,25 +358,27 @@ func (ws *WebServer) handleCreateIssuer(w http.ResponseWriter, r *http.Request)
return return
} }
reqData := map[string]interface{}{"name": name} issuerReq := CreateIssuerRequest{
Mount: mountName,
Name: name,
}
if v := r.FormValue("expiry"); v != "" { if v := r.FormValue("expiry"); v != "" {
reqData["expiry"] = v issuerReq.Expiry = v
} }
if v := r.FormValue("max_ttl"); v != "" { if v := r.FormValue("max_ttl"); v != "" {
reqData["max_ttl"] = v issuerReq.MaxTTL = v
} }
if v := r.FormValue("key_algorithm"); v != "" { if v := r.FormValue("key_algorithm"); v != "" {
reqData["key_algorithm"] = v issuerReq.KeyAlgorithm = v
} }
if v := r.FormValue("key_size"); v != "" { if v := r.FormValue("key_size"); v != "" {
var size float64 var size int32
if _, err := fmt.Sscanf(v, "%f", &size); err == nil { if _, err := fmt.Sscanf(v, "%d", &size); err == nil {
reqData["key_size"] = size issuerReq.KeySize = size
} }
} }
_, err = ws.vault.EngineRequest(r.Context(), token, mountName, "create-issuer", reqData) if err = ws.vault.CreateIssuer(r.Context(), token, issuerReq); err != nil {
if err != nil {
ws.renderPKIWithError(w, r, mountName, info, grpcMessage(err)) ws.renderPKIWithError(w, r, mountName, info, grpcMessage(err))
return return
} }
@@ -419,7 +417,7 @@ func (ws *WebServer) handleIssuerDetail(w http.ResponseWriter, r *http.Request)
issuerName := chi.URLParam(r, "issuer") issuerName := chi.URLParam(r, "issuer")
resp, err := ws.vault.EngineRequest(r.Context(), token, mountName, "list-certs", nil) allCerts, err := ws.vault.ListCerts(r.Context(), token, mountName)
if err != nil { if err != nil {
http.Error(w, "failed to list certificates", http.StatusInternalServerError) http.Error(w, "failed to list certificates", http.StatusInternalServerError)
return return
@@ -431,34 +429,22 @@ func (ws *WebServer) handleIssuerDetail(w http.ResponseWriter, r *http.Request)
sortBy = "cn" sortBy = "cn"
} }
var certs []map[string]interface{} var certs []CertSummary
if raw, ok := resp["certs"]; ok { for _, cs := range allCerts {
if list, ok := raw.([]interface{}); ok { if cs.Issuer != issuerName {
for _, item := range list {
if m, ok := item.(map[string]interface{}); ok {
issuer, _ := m["issuer"].(string)
if issuer != issuerName {
continue continue
} }
if nameFilter != "" { if nameFilter != "" && !strings.Contains(strings.ToLower(cs.CommonName), strings.ToLower(nameFilter)) {
cn, _ := m["cn"].(string)
if !strings.Contains(strings.ToLower(cn), nameFilter) {
continue continue
} }
} certs = append(certs, cs)
certs = append(certs, m)
}
}
}
} }
// Sort: by expiry date or by common name (default). // Sort: by expiry date or by common name (default).
if sortBy == "expiry" { if sortBy == "expiry" {
for i := 1; i < len(certs); i++ { for i := 1; i < len(certs); i++ {
for j := i; j > 0; j-- { for j := i; j > 0; j-- {
a, _ := certs[j-1]["expires_at"].(string) if certs[j-1].ExpiresAt > certs[j].ExpiresAt {
b, _ := certs[j]["expires_at"].(string)
if a > b {
certs[j-1], certs[j] = certs[j], certs[j-1] certs[j-1], certs[j] = certs[j], certs[j-1]
} }
} }
@@ -466,9 +452,7 @@ func (ws *WebServer) handleIssuerDetail(w http.ResponseWriter, r *http.Request)
} else { } else {
for i := 1; i < len(certs); i++ { for i := 1; i < len(certs); i++ {
for j := i; j > 0; j-- { for j := i; j > 0; j-- {
a, _ := certs[j-1]["cn"].(string) if strings.ToLower(certs[j-1].CommonName) > strings.ToLower(certs[j].CommonName) {
b, _ := certs[j]["cn"].(string)
if strings.ToLower(a) > strings.ToLower(b) {
certs[j-1], certs[j] = certs[j], certs[j-1] certs[j-1], certs[j] = certs[j], certs[j-1]
} }
} }
@@ -512,24 +496,31 @@ func (ws *WebServer) handleIssueCert(w http.ResponseWriter, r *http.Request) {
return return
} }
reqData := map[string]interface{}{ certReq := IssueCertRequest{
"common_name": commonName, Mount: mountName,
"issuer": issuer, Issuer: issuer,
CommonName: commonName,
} }
if v := r.FormValue("profile"); v != "" { if v := r.FormValue("profile"); v != "" {
reqData["profile"] = v certReq.Profile = v
} }
if v := r.FormValue("ttl"); v != "" { if v := r.FormValue("ttl"); v != "" {
reqData["ttl"] = v certReq.TTL = v
} }
if lines := splitLines(r.FormValue("dns_names")); len(lines) > 0 { if lines := splitLines(r.FormValue("dns_names")); len(lines) > 0 {
reqData["dns_names"] = lines for _, l := range lines {
certReq.DNSNames = append(certReq.DNSNames, l.(string))
}
} }
if lines := splitLines(r.FormValue("ip_addresses")); len(lines) > 0 { if lines := splitLines(r.FormValue("ip_addresses")); len(lines) > 0 {
reqData["ip_addresses"] = lines for _, l := range lines {
certReq.IPAddresses = append(certReq.IPAddresses, l.(string))
} }
}
certReq.KeyUsages = r.Form["key_usages"]
certReq.ExtKeyUsages = r.Form["ext_key_usages"]
resp, err := ws.vault.EngineRequest(r.Context(), token, mountName, "issue", reqData) issuedCert, err := ws.vault.IssueCert(r.Context(), token, certReq)
if err != nil { if err != nil {
ws.renderPKIWithError(w, r, mountName, info, grpcMessage(err)) ws.renderPKIWithError(w, r, mountName, info, grpcMessage(err))
return return
@@ -540,7 +531,7 @@ func (ws *WebServer) handleIssueCert(w http.ResponseWriter, r *http.Request) {
"Username": info.Username, "Username": info.Username,
"IsAdmin": info.IsAdmin, "IsAdmin": info.IsAdmin,
"MountName": mountName, "MountName": mountName,
"IssuedCert": resp, "IssuedCert": issuedCert,
} }
if rootPEM, err := ws.vault.GetRootCert(r.Context(), mountName); err == nil && len(rootPEM) > 0 { if rootPEM, err := ws.vault.GetRootCert(r.Context(), mountName); err == nil && len(rootPEM) > 0 {
if cert, err := parsePEMCert(rootPEM); err == nil { if cert, err := parsePEMCert(rootPEM); err == nil {
@@ -552,8 +543,8 @@ func (ws *WebServer) handleIssueCert(w http.ResponseWriter, r *http.Request) {
data["HasRoot"] = true data["HasRoot"] = true
} }
} }
if issuerResp, err := ws.vault.EngineRequest(r.Context(), token, mountName, "list-issuers", nil); err == nil { if issuers, err := ws.vault.ListIssuers(r.Context(), token, mountName); err == nil {
data["Issuers"] = issuerResp["issuers"] data["Issuers"] = issuers
} }
ws.renderTemplate(w, "pki.html", data) ws.renderTemplate(w, "pki.html", data)
} }
@@ -577,8 +568,8 @@ func (ws *WebServer) renderPKIWithError(w http.ResponseWriter, r *http.Request,
data["HasRoot"] = true data["HasRoot"] = true
} }
} }
if resp, err := ws.vault.EngineRequest(r.Context(), token, mountName, "list-issuers", nil); err == nil { if issuers, err := ws.vault.ListIssuers(r.Context(), token, mountName); err == nil {
data["Issuers"] = resp["issuers"] data["Issuers"] = issuers
} }
ws.renderTemplate(w, "pki.html", data) ws.renderTemplate(w, "pki.html", data)

View File

@@ -5,8 +5,6 @@ import (
"crypto/x509" "crypto/x509"
"encoding/pem" "encoding/pem"
"errors" "errors"
"google.golang.org/protobuf/types/known/structpb"
) )
type contextKey int type contextKey int
@@ -22,11 +20,6 @@ func tokenInfoFromContext(ctx context.Context) *TokenInfo {
return v return v
} }
// structFromMap converts a map[string]interface{} to a *structpb.Struct.
func structFromMap(m map[string]interface{}) (*structpb.Struct, error) {
return structpb.NewStruct(m)
}
// parsePEMCert decodes the first PEM block and parses it as an x509 certificate. // parsePEMCert decodes the first PEM block and parses it as an x509 certificate.
func parsePEMCert(pemData []byte) (*x509.Certificate, error) { func parsePEMCert(pemData []byte) (*x509.Certificate, error) {
block, _ := pem.Decode(pemData) block, _ := pem.Decode(pemData)

View File

@@ -1,31 +1,456 @@
* { margin: 0; padding: 0; box-sizing: border-box; } /* Metacrypt — Nord dark theme */
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; background: #f5f5f5; color: #333; line-height: 1.6; }
.container { max-width: 800px; margin: 0 auto; padding: 2rem; } /* ===========================
header h1 { margin-bottom: 2rem; } Colour tokens (Nord palette)
header h1 a { color: #333; text-decoration: none; } =========================== */
main { background: #fff; border-radius: 8px; padding: 2rem; box-shadow: 0 1px 3px rgba(0,0,0,0.1); } :root {
h2 { margin-bottom: 1rem; color: #222; } /* Polar Night */
h3 { margin: 1.5rem 0 0.5rem; color: #444; } --n0: #2E3440;
p { margin-bottom: 1rem; } --n1: #3B4252;
--n2: #434C5E;
--n3: #4C566A;
/* Snow Storm */
--s0: #D8DEE9;
--s1: #E5E9F0;
--s2: #ECEFF4;
/* Frost */
--f0: #8FBCBB;
--f1: #88C0D0;
--f2: #81A1C1;
--f3: #5E81AC;
/* Aurora */
--red: #BF616A;
--orange: #D08770;
--yellow: #EBCB8B;
--green: #A3BE8C;
--green-dark: #4C7A4A;
--purple: #B48EAD;
}
/* ===========================
Reset
=========================== */
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
html { font-size: 16px; }
/* ===========================
Base
=========================== */
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
background: var(--n0);
color: var(--s0);
line-height: 1.6;
min-height: 100vh;
}
a { color: var(--f1); text-decoration: none; }
a:hover { color: var(--f0); text-decoration: underline; }
p { margin-bottom: 0.875rem; }
h2 { font-size: 1.375rem; font-weight: 600; color: var(--s2); margin-bottom: 0.25rem; }
h3 { font-size: 1.0625rem; font-weight: 600; color: var(--s1); margin: 0; }
code {
font-family: "SF Mono", "Cascadia Code", "Fira Code", Consolas, monospace;
font-size: 0.8125rem;
color: var(--f0);
background: var(--n2);
padding: 0.125rem 0.375rem;
border-radius: 3px;
}
small { font-size: 0.8125rem; color: var(--s0); }
/* ===========================
Top navigation
=========================== */
.topnav {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 2rem;
height: 52px;
background: var(--n1);
border-bottom: 1px solid var(--n3);
position: sticky;
top: 0;
z-index: 100;
}
.topnav-brand {
font-size: 1rem;
font-weight: 700;
color: var(--s2);
text-decoration: none;
letter-spacing: 0.04em;
}
.topnav-brand:hover { color: var(--f1); text-decoration: none; }
.topnav-right {
display: flex;
align-items: center;
gap: 0.75rem;
}
.topnav-user {
font-size: 0.875rem;
color: var(--s1);
}
/* ===========================
Page containers
=========================== */
.page-container {
max-width: 1100px;
margin: 0 auto;
padding: 2rem;
}
.auth-container {
max-width: 420px;
margin: 5rem auto 2rem;
padding: 0 1rem;
}
/* ===========================
Page header
=========================== */
.page-header {
margin-bottom: 1.5rem;
padding-bottom: 1rem;
border-bottom: 1px solid var(--n2);
}
.page-header h2 { margin-bottom: 0; }
.page-meta {
margin-top: 0.375rem;
display: flex;
align-items: center;
gap: 0.75rem;
font-size: 0.8125rem;
color: var(--n3);
}
.page-meta a { color: var(--f2); font-size: 0.8125rem; }
.page-meta a:hover { color: var(--f1); }
/* ===========================
Auth pages
=========================== */
.auth-header {
text-align: center;
margin-bottom: 1.75rem;
}
.auth-header .brand {
font-size: 1.5rem;
font-weight: 700;
color: var(--s2);
letter-spacing: 0.04em;
}
.auth-header .tagline {
font-size: 0.6875rem;
color: var(--f2);
text-transform: uppercase;
letter-spacing: 0.12em;
margin-top: 0.25rem;
}
/* ===========================
Cards
=========================== */
.card {
background: var(--n1);
border: 1px solid var(--n3);
border-radius: 6px;
padding: 1.5rem;
margin-bottom: 1.25rem;
}
.card:last-child { margin-bottom: 0; }
.card-title {
font-size: 0.6875rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.09em;
color: var(--f2);
margin-bottom: 1rem;
padding-bottom: 0.625rem;
border-bottom: 1px solid var(--n2);
}
.card p:last-child { margin-bottom: 0; }
/* ===========================
State chip
=========================== */
.state-chip {
display: inline-flex;
align-items: center;
gap: 0.4rem;
font-size: 0.8125rem;
color: var(--s0);
}
.state-chip::before {
content: '';
width: 7px;
height: 7px;
border-radius: 50%;
background: var(--n3);
flex-shrink: 0;
}
.state-chip.state-unsealed::before {
background: var(--green);
box-shadow: 0 0 5px rgba(163, 190, 140, 0.55);
}
.state-chip.state-sealed::before { background: var(--red); }
/* ===========================
Badges
=========================== */
.badge {
display: inline-block;
padding: 0.125rem 0.5rem;
border-radius: 3px;
font-size: 0.6875rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.06em;
background: rgba(94, 129, 172, 0.2);
color: var(--f1);
border: 1px solid rgba(94, 129, 172, 0.35);
}
.badge-danger {
background: rgba(191, 97, 106, 0.15);
color: #e07c82;
border-color: rgba(191, 97, 106, 0.35);
}
/* ===========================
Alerts
=========================== */
.error {
background: rgba(191, 97, 106, 0.12);
color: #e07c82;
border: 1px solid rgba(191, 97, 106, 0.3);
padding: 0.75rem 1rem;
border-radius: 4px;
margin-bottom: 1rem;
font-size: 0.875rem;
}
.success {
background: rgba(163, 190, 140, 0.1);
border: 1px solid rgba(163, 190, 140, 0.3);
border-radius: 4px;
padding: 1rem;
margin-bottom: 1rem;
}
.success p { color: var(--green); }
/* ===========================
Buttons
=========================== */
button, .btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.375rem;
padding: 0.5rem 1.25rem;
font-size: 0.875rem;
font-weight: 600;
font-family: inherit;
border: 1px solid var(--f3);
border-radius: 4px;
cursor: pointer;
text-decoration: none;
white-space: nowrap;
transition: background 0.12s, border-color 0.12s, color 0.12s;
line-height: 1.4;
background: var(--f3);
color: var(--s2);
}
button:hover, .btn:hover {
background: var(--f2);
border-color: var(--f2);
text-decoration: none;
color: var(--s2);
}
.btn-danger {
background: var(--red);
color: var(--s2);
border-color: var(--red);
}
.btn-danger:hover {
background: #a8535b;
border-color: #a8535b;
color: var(--s2);
}
.btn-ghost {
background: transparent;
color: var(--s0);
border-color: var(--n3);
}
.btn-ghost:hover {
background: var(--n2);
color: var(--s1);
border-color: var(--n3);
text-decoration: none;
}
.btn-sm {
padding: 0.3125rem 0.875rem;
font-size: 0.8125rem;
}
/* ===========================
Forms
=========================== */
.form-group { margin-bottom: 1rem; } .form-group { margin-bottom: 1rem; }
.form-group label { display: block; margin-bottom: 0.25rem; font-weight: 600; } .form-group label {
.form-group input { width: 100%; padding: 0.5rem; border: 1px solid #ccc; border-radius: 4px; font-size: 1rem; } display: block;
button { padding: 0.5rem 1.5rem; background: #2563eb; color: #fff; border: none; border-radius: 4px; font-size: 1rem; cursor: pointer; } font-size: 0.6875rem;
button:hover { background: #1d4ed8; } font-weight: 700;
.error { background: #fee2e2; color: #991b1b; padding: 0.75rem; border-radius: 4px; margin-bottom: 1rem; } color: var(--s0);
.badge { background: #dbeafe; color: #1e40af; padding: 0.125rem 0.5rem; border-radius: 4px; font-size: 0.875rem; } margin-bottom: 0.375rem;
.status-bar { display: flex; gap: 1rem; align-items: center; padding: 0.75rem; background: #f9fafb; border-radius: 4px; margin-bottom: 1.5rem; flex-wrap: wrap; } text-transform: uppercase;
.status-bar a { margin-left: auto; color: #2563eb; } letter-spacing: 0.06em;
table { width: 100%; border-collapse: collapse; margin: 0.5rem 0; } }
th, td { text-align: left; padding: 0.5rem; border-bottom: 1px solid #e5e7eb; } .form-group input,
th { font-weight: 600; background: #f9fafb; } .form-group select,
.admin-actions { margin-top: 0.5rem; } .form-group textarea {
.admin-actions button { background: #dc2626; } width: 100%;
.admin-actions button:hover { background: #b91c1c; } padding: 0.5rem 0.75rem;
.badge-danger { background: #fee2e2; color: #991b1b; } background: var(--n0);
.form-group textarea, .pem-input { width: 100%; padding: 0.5rem; border: 1px solid #ccc; border-radius: 4px; font-family: monospace; font-size: 0.875rem; resize: vertical; } border: 1px solid var(--n3);
.form-group input[type="file"] { padding: 0.25rem 0; border: none; } border-radius: 4px;
color: var(--s1);
font-size: 0.9375rem;
font-family: inherit;
transition: border-color 0.12s, box-shadow 0.12s;
-webkit-appearance: none;
appearance: none;
}
.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus {
outline: none;
border-color: var(--f3);
box-shadow: 0 0 0 3px rgba(94, 129, 172, 0.2);
}
.form-group input::placeholder,
.form-group textarea::placeholder { color: var(--n3); }
.form-group input[type="file"] {
padding: 0.375rem 0.5rem;
font-size: 0.875rem;
color: var(--s0);
cursor: pointer;
border-style: dashed;
}
.form-group select {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2381A1C1' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 0.75rem center;
padding-right: 2.25rem;
cursor: pointer;
}
.form-row { display: flex; gap: 1rem; } .form-row { display: flex; gap: 1rem; }
.form-row .form-group { flex: 1; } .form-row .form-group { flex: 1; min-width: 0; }
.form-actions { margin-top: 0.25rem; }
.pem-input,
.form-group textarea.pem-input {
font-family: "SF Mono", "Cascadia Code", "Fira Code", Consolas, monospace;
font-size: 0.8125rem;
resize: vertical;
}
/* ===========================
Details / Summary
=========================== */
details { margin: 0.75rem 0; } details { margin: 0.75rem 0; }
details summary { cursor: pointer; color: #2563eb; font-weight: 600; margin-bottom: 0.5rem; } details summary {
cursor: pointer;
color: var(--f2);
font-size: 0.875rem;
font-weight: 600;
padding: 0.375rem 0;
user-select: none;
list-style: none;
}
details summary::-webkit-details-marker { display: none; }
details summary::before {
content: '▸ ';
color: var(--n3);
font-size: 0.75rem;
}
details[open] summary::before { content: '▾ '; }
details summary:hover { color: var(--f1); }
details[open] > summary { margin-bottom: 0.75rem; }
details > :not(summary):first-of-type { margin-top: 0.25rem; }
/* ===========================
Tables
=========================== */
.table-wrapper { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; }
th {
text-align: left;
padding: 0.5rem 0.875rem;
font-size: 0.6875rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.07em;
color: var(--f2);
border-bottom: 1px solid var(--n3);
white-space: nowrap;
}
td {
text-align: left;
padding: 0.625rem 0.875rem;
font-size: 0.875rem;
color: var(--s0);
border-bottom: 1px solid var(--n2);
}
tbody tr:last-child td { border-bottom: none; }
tbody tr:hover td { background: rgba(76, 86, 106, 0.25); }
/* Keyvalue table (cert info) */
.kv-table { border-collapse: collapse; width: 100%; }
.kv-table th {
width: 140px;
font-size: 0.75rem;
font-weight: 700;
color: var(--f2);
text-transform: uppercase;
letter-spacing: 0.05em;
padding: 0.375rem 1rem 0.375rem 0;
border-bottom: none;
vertical-align: top;
white-space: nowrap;
}
.kv-table td {
font-size: 0.9375rem;
color: var(--s1);
padding: 0.375rem 0;
border-bottom: none;
}
.kv-table tbody tr:hover td { background: transparent; }
.checkbox-group {
display: flex;
flex-direction: column;
gap: 0.375rem;
margin-top: 0.25rem;
}
.form-group .checkbox-label {
display: flex;
align-items: center;
gap: 0.5rem;
font-size: 0.9375rem;
font-weight: normal;
text-transform: none;
letter-spacing: 0;
color: var(--s1);
cursor: pointer;
}
.form-group .checkbox-label input[type="checkbox"] {
width: 1rem;
height: 1rem;
padding: 0;
cursor: pointer;
flex-shrink: 0;
accent-color: var(--green-dark);
}
.form-group .checkbox-label input[type="checkbox"]:checked {
outline: 2px solid var(--green-dark);
outline-offset: 1px;
}
.form-group .checkbox-label:has(input[type="checkbox"]:checked) {
color: var(--green);
}

View File

@@ -1,35 +1,52 @@
{{define "title"}} - Dashboard{{end}} {{define "title"}} - Dashboard{{end}}
{{define "content"}} {{define "content"}}
<div class="page-header">
<h2>Dashboard</h2> <h2>Dashboard</h2>
<div class="status-bar"> <div class="page-meta">
<span>Logged in as <strong>{{.Username}}</strong></span> <span class="state-chip state-{{.State}}">{{.State}}</span>
{{if .IsAdmin}}<span class="badge">Admin</span>{{end}} </div>
<span>State: <strong>{{.State}}</strong></span>
<span class="version">v{{.Version}}</span>
<a href="/login" onclick="fetch('/v1/auth/logout',{method:'POST'})">Logout</a>
</div> </div>
<h3>Engine Mounts</h3> <div class="card">
<div class="card-title">Engine Mounts</div>
{{if .Mounts}} {{if .Mounts}}
<div class="table-wrapper">
<table> <table>
<thead><tr><th>Name</th><th>Type</th><th>Path</th></tr></thead> <thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Path</th>
</tr>
</thead>
<tbody> <tbody>
{{range .Mounts}} {{range .Mounts}}
<tr> <tr>
<td>{{if eq (printf "%s" .Type) "ca"}}<a href="/pki">{{.Name}}</a>{{else}}{{.Name}}{{end}}</td> <td>
<td>{{.Type}}</td> {{if eq (printf "%s" .Type) "ca"}}
<td>{{.MountPath}}</td> <a href="/pki">{{.Name}}</a>
{{else}}
{{.Name}}
{{end}}
</td>
<td><code>{{.Type}}</code></td>
<td><code>{{.MountPath}}</code></td>
</tr> </tr>
{{end}} {{end}}
</tbody> </tbody>
</table> </table>
</div>
{{else}} {{else}}
<p>No engines mounted.</p> <p>No engines mounted.</p>
{{end}} {{end}}
</div>
{{if .IsAdmin}} {{if .IsAdmin}}
<h3>Mount CA Engine</h3> <div class="card">
<div class="card-title">Mount Engine</div>
{{if .MountError}}<div class="error">{{.MountError}}</div>{{end}} {{if .MountError}}<div class="error">{{.MountError}}</div>{{end}}
<details>
<summary>Mount a CA engine</summary>
<form method="post" action="/dashboard/mount-ca" enctype="multipart/form-data"> <form method="post" action="/dashboard/mount-ca" enctype="multipart/form-data">
<div class="form-row"> <div class="form-row">
<div class="form-group"> <div class="form-group">
@@ -44,20 +61,25 @@
<details> <details>
<summary>Import existing root CA (optional)</summary> <summary>Import existing root CA (optional)</summary>
<div class="form-group"> <div class="form-group">
<label for="cert_file">Certificate PEM file</label> <label for="cert_file">Certificate PEM</label>
<input type="file" id="cert_file" name="cert_file" accept=".pem,.crt"> <input type="file" id="cert_file" name="cert_file" accept=".pem,.crt">
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="key_file">Private Key PEM file</label> <label for="key_file">Private Key PEM</label>
<input type="file" id="key_file" name="key_file" accept=".pem,.key"> <input type="file" id="key_file" name="key_file" accept=".pem,.key">
</div> </div>
</details> </details>
<div class="form-actions">
<button type="submit">Mount</button> <button type="submit">Mount</button>
</div>
</form> </form>
</details>
</div>
<h3>Admin Actions</h3> <div class="card">
<div class="admin-actions"> <div class="card-title">Administration</div>
<button hx-post="/v1/seal" hx-confirm="Are you sure you want to seal the service?">Seal Service</button> <p>Sealing the service will require the seal password to restore access.</p>
<button class="btn-danger" hx-post="/v1/seal" hx-confirm="Are you sure you want to seal the service?">Seal Service</button>
</div> </div>
{{end}} {{end}}
{{end}} {{end}}

View File

@@ -1,17 +1,26 @@
{{define "title"}} - Initialize{{end}} {{define "title"}} - Initialize{{end}}
{{define "container-class"}}auth-container{{end}}
{{define "content"}} {{define "content"}}
<h2>Initialize Metacrypt</h2> <div class="auth-header">
<p>Set the seal password for this Metacrypt instance. This password will be required to unseal the service after each restart.</p> <div class="brand">Metacrypt</div>
<div class="tagline">Cryptographic Services</div>
</div>
<div class="card">
<div class="card-title">Initialize</div>
<p>Set the seal password for this instance. This password will be required to unseal the service after each restart.</p>
{{if .Error}}<div class="error">{{.Error}}</div>{{end}} {{if .Error}}<div class="error">{{.Error}}</div>{{end}}
<form method="POST" action="/init"> <form method="POST" action="/init">
<div class="form-group"> <div class="form-group">
<label for="password">Seal Password</label> <label for="password">Seal Password</label>
<input type="password" id="password" name="password" required autofocus> <input type="password" id="password" name="password" required autofocus autocomplete="new-password">
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="confirm">Confirm Password</label> <label for="confirm">Confirm Password</label>
<input type="password" id="confirm" name="confirm" required> <input type="password" id="confirm" name="confirm" required autocomplete="new-password">
</div> </div>
<div class="form-actions">
<button type="submit">Initialize</button> <button type="submit">Initialize</button>
</div>
</form> </form>
</div>
{{end}} {{end}}

View File

@@ -1,9 +1,16 @@
{{define "title"}} - Initializing{{end}} {{define "title"}} - Initializing{{end}}
{{define "container-class"}}auth-container{{end}}
{{define "content"}} {{define "content"}}
<h2>Initializing...</h2> <div class="auth-header">
<p>Metacrypt is being initialized. Please wait.</p> <div class="brand">Metacrypt</div>
<div class="tagline">Cryptographic Services</div>
</div>
<div class="card">
<div class="card-title">Initializing</div>
<p>Metacrypt is being initialized. This will only take a moment.</p>
<div hx-get="/v1/status" hx-trigger="every 2s" hx-swap="none" <div hx-get="/v1/status" hx-trigger="every 2s" hx-swap="none"
hx-on::after-request="if(JSON.parse(event.detail.xhr.responseText).state==='unsealed')window.location='/dashboard'"> hx-on::after-request="if(JSON.parse(event.detail.xhr.responseText).state==='unsealed')window.location='/dashboard'">
<p>Checking status...</p> <p style="color: var(--f2); font-size: 0.875rem;">Waiting for service to come online&hellip;</p>
</div>
</div> </div>
{{end}} {{end}}

View File

@@ -1,35 +1,36 @@
{{define "title"}} - Issuer: {{.IssuerName}}{{end}} {{define "title"}} - Issuer: {{.IssuerName}}{{end}}
{{define "content"}} {{define "content"}}
<div class="page-header">
<h2>Issuer: {{.IssuerName}}</h2> <h2>Issuer: {{.IssuerName}}</h2>
<div class="page-meta">
<p>
<a href="/pki">&larr; PKI: {{.MountName}}</a> <a href="/pki">&larr; PKI: {{.MountName}}</a>
&nbsp;&mdash;&nbsp; &ensp;&middot;&ensp;
<a href="/pki/{{.IssuerName}}" download="{{.IssuerName}}.pem">Download Issuer Cert (PEM)</a> <a href="/pki/{{.IssuerName}}" download="{{.IssuerName}}.pem">Download Issuer Cert (PEM)</a>
</p>
<h3>Certificates</h3>
<form method="get" action="/pki/issuer/{{.IssuerName}}" style="margin-bottom: 1rem;">
<div class="form-row">
<div class="form-group">
<label for="name_filter">Filter by name</label>
<input type="text" id="name_filter" name="name" value="{{.NameFilter}}" placeholder="common name contains...">
</div> </div>
<div class="form-group"> </div>
<div class="card">
<div class="card-title">Certificates</div>
<form method="get" action="/pki/issuer/{{.IssuerName}}">
<div class="form-row" style="align-items: flex-end; margin-bottom: 1rem;">
<div class="form-group" style="margin-bottom: 0;">
<label for="name_filter">Filter by name</label>
<input type="text" id="name_filter" name="name" value="{{.NameFilter}}" placeholder="common name contains&hellip;">
</div>
<div class="form-group" style="margin-bottom: 0;">
<label for="sort_by">Sort by</label> <label for="sort_by">Sort by</label>
<select id="sort_by" name="sort"> <select id="sort_by" name="sort">
<option value="cn"{{if eq .SortBy "cn"}} selected{{end}}>Common Name</option> <option value="cn"{{if eq .SortBy "cn"}} selected{{end}}>Common Name</option>
<option value="expiry"{{if eq .SortBy "expiry"}} selected{{end}}>Expiry Date</option> <option value="expiry"{{if eq .SortBy "expiry"}} selected{{end}}>Expiry Date</option>
</select> </select>
</div> </div>
<div class="form-group" style="align-self: flex-end;"> <div style="flex-shrink: 0; padding-bottom: 1px;">
<button type="submit">Apply</button> <button type="submit">Apply</button>
</div> </div>
</div> </div>
</form> </form>
{{if .Certs}} {{if .Certs}}
<div class="table-wrapper">
<table> <table>
<thead> <thead>
<tr> <tr>
@@ -54,7 +55,9 @@
{{end}} {{end}}
</tbody> </tbody>
</table> </table>
</div>
{{else}} {{else}}
<p>No certificates found{{if .NameFilter}} matching &ldquo;{{.NameFilter}}&rdquo;{{end}}.</p> <p>No certificates found{{if .NameFilter}} matching &ldquo;{{.NameFilter}}&rdquo;{{end}}.</p>
{{end}} {{end}}
</div>
{{end}} {{end}}

View File

@@ -8,13 +8,18 @@
<link rel="stylesheet" href="/static/style.css"> <link rel="stylesheet" href="/static/style.css">
</head> </head>
<body> <body>
<div class="container"> <nav class="topnav">
<header> <a class="topnav-brand" href="/">Metacrypt</a>
<h1><a href="/">Metacrypt</a></h1> <div class="topnav-right">
</header> {{if .Username}}
<main> <span class="topnav-user">{{.Username}}</span>
{{if .IsAdmin}}<span class="badge">admin</span>{{end}}
<a href="/login" class="btn btn-ghost btn-sm" onclick="fetch('/v1/auth/logout',{method:'POST'})">Logout</a>
{{end}}
</div>
</nav>
<div class="{{block "container-class" .}}page-container{{end}}">
{{template "content" .}} {{template "content" .}}
</main>
</div> </div>
</body> </body>
</html>{{end}} </html>{{end}}

View File

@@ -1,21 +1,30 @@
{{define "title"}} - Login{{end}} {{define "title"}} - Login{{end}}
{{define "container-class"}}auth-container{{end}}
{{define "content"}} {{define "content"}}
<h2>Login</h2> <div class="auth-header">
<div class="brand">Metacrypt</div>
<div class="tagline">Cryptographic Services</div>
</div>
<div class="card">
<div class="card-title">Sign In</div>
<p>Authenticate with your MCIAS credentials.</p> <p>Authenticate with your MCIAS credentials.</p>
{{if .Error}}<div class="error">{{.Error}}</div>{{end}} {{if .Error}}<div class="error">{{.Error}}</div>{{end}}
<form method="POST" action="/login"> <form method="POST" action="/login">
<div class="form-group"> <div class="form-group">
<label for="username">Username</label> <label for="username">Username</label>
<input type="text" id="username" name="username" required autofocus> <input type="text" id="username" name="username" required autofocus autocomplete="username">
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="password">Password</label> <label for="password">Password</label>
<input type="password" id="password" name="password" required> <input type="password" id="password" name="password" required autocomplete="current-password">
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="totp_code">TOTP Code (if enabled)</label> <label for="totp_code">TOTP Code <small style="text-transform:none;letter-spacing:0;">(if enabled)</small></label>
<input type="text" id="totp_code" name="totp_code" autocomplete="one-time-code"> <input type="text" id="totp_code" name="totp_code" autocomplete="one-time-code" inputmode="numeric">
</div> </div>
<div class="form-actions">
<button type="submit">Login</button> <button type="submit">Login</button>
</div>
</form> </form>
</div>
{{end}} {{end}}

View File

@@ -1,16 +1,19 @@
{{define "title"}} - PKI: {{.MountName}}{{end}} {{define "title"}} - PKI: {{.MountName}}{{end}}
{{define "content"}} {{define "content"}}
<h2>PKI Engine: {{.MountName}}</h2> <div class="page-header">
<h2>PKI: {{.MountName}}</h2>
<div class="page-meta">
<a href="/dashboard">&larr; Dashboard</a>
</div>
</div>
<p><a href="/dashboard">&larr; Dashboard</a></p> {{if .Error}}<div class="error">{{.Error}}</div>{{end}}
{{if .Error}} <div class="card">
<div class="error">{{.Error}}</div> <div class="card-title">Root CA</div>
{{end}}
<h3>Root CA</h3>
{{if .HasRoot}} {{if .HasRoot}}
<table> <table class="kv-table">
<tbody>
<tr><th>Common Name</th><td>{{.RootCN}}</td></tr> <tr><th>Common Name</th><td>{{.RootCN}}</td></tr>
<tr><th>Organization</th><td>{{.RootOrg}}</td></tr> <tr><th>Organization</th><td>{{.RootOrg}}</td></tr>
<tr><th>Valid From</th><td>{{.RootNotBefore}}</td></tr> <tr><th>Valid From</th><td>{{.RootNotBefore}}</td></tr>
@@ -18,47 +21,65 @@
<th>Valid Until</th> <th>Valid Until</th>
<td> <td>
{{.RootNotAfter}} {{.RootNotAfter}}
{{if .RootExpired}} <span class="badge badge-danger">Expired</span>{{end}} {{if .RootExpired}}&ensp;<span class="badge badge-danger">Expired</span>{{end}}
</td> </td>
</tr> </tr>
</tbody>
</table> </table>
<p style="margin-top: 0.5rem;"> <p style="margin-top: 1rem; margin-bottom: 0;">
<a href="/v1/pki/{{.MountName}}/ca" download="root-ca.pem">Download Root CA (PEM)</a> <a href="/v1/pki/{{.MountName}}/ca" download="root-ca.pem">Download Root CA (PEM)</a>
</p> </p>
{{else}} {{else}}
<p>No root CA configured.</p> <p>No root CA configured.</p>
{{end}} {{end}}
</div>
{{if .IsAdmin}} {{if .IsAdmin}}
{{if or (not .HasRoot) .RootExpired}} {{if or (not .HasRoot) .RootExpired}}
<h3>Import Root CA</h3> <div class="card">
<p>{{if .RootExpired}}The current root CA has expired. Import a new one.{{else}}No root CA is present. Import one to get started.{{end}}</p> <div class="card-title">Import Root CA</div>
<p>{{if .RootExpired}}The current root CA has expired. Import a new one to continue issuing certificates.{{else}}No root CA is present. Import one to get started.{{end}}</p>
<form method="post" action="/pki/import-root" enctype="multipart/form-data"> <form method="post" action="/pki/import-root" enctype="multipart/form-data">
<div class="form-row">
<div class="form-group"> <div class="form-group">
<label for="cert_file">Certificate PEM</label> <label for="cert_file">Certificate PEM file</label>
<input type="file" id="cert_file" name="cert_file" accept=".pem,.crt"> <input type="file" id="cert_file" name="cert_file" accept=".pem,.crt">
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="cert_pem">Or paste certificate PEM</label> <label for="key_file">Private Key PEM file</label>
<input type="file" id="key_file" name="key_file" accept=".pem,.key">
</div>
</div>
<details>
<summary>Or paste PEM directly</summary>
<div class="form-group">
<label for="cert_pem">Certificate PEM</label>
<textarea id="cert_pem" name="cert_pem" rows="6" class="pem-input" placeholder="-----BEGIN CERTIFICATE-----"></textarea> <textarea id="cert_pem" name="cert_pem" rows="6" class="pem-input" placeholder="-----BEGIN CERTIFICATE-----"></textarea>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="key_file">Private Key PEM</label> <label for="key_pem">Private Key PEM</label>
<input type="file" id="key_file" name="key_file" accept=".pem,.key">
</div>
<div class="form-group">
<label for="key_pem">Or paste private key PEM</label>
<textarea id="key_pem" name="key_pem" rows="6" class="pem-input" placeholder="-----BEGIN PRIVATE KEY-----"></textarea> <textarea id="key_pem" name="key_pem" rows="6" class="pem-input" placeholder="-----BEGIN PRIVATE KEY-----"></textarea>
</div> </div>
</details>
<div class="form-actions">
<button type="submit">Import Root CA</button> <button type="submit">Import Root CA</button>
</div>
</form> </form>
</div>
{{end}} {{end}}
{{end}} {{end}}
<h3>Issuers</h3> <div class="card">
<div class="card-title">Issuers</div>
{{if .Issuers}} {{if .Issuers}}
<div class="table-wrapper">
<table> <table>
<thead><tr><th>Name</th><th>Actions</th></tr></thead> <thead>
<tr>
<th>Name</th>
<th>Actions</th>
</tr>
</thead>
<tbody> <tbody>
{{range .Issuers}} {{range .Issuers}}
<tr> <tr>
@@ -68,15 +89,27 @@
{{end}} {{end}}
</tbody> </tbody>
</table> </table>
</div>
{{else}} {{else}}
<p>No issuers configured.</p> <p>No issuers configured.</p>
{{end}} {{end}}
</div>
{{if and .HasRoot .Issuers}} {{if and .HasRoot .Issuers}}
<h3>Issue Certificate</h3> <div class="card">
<div class="card-title">Issue Certificate</div>
{{if .IssuedCert}} {{if .IssuedCert}}
<div class="success"> <div class="success">
<p>Certificate issued successfully.</p> <p><strong>Certificate issued successfully.</strong></p>
</div>
<div class="form-group">
<label>Serial</label>
<input type="text" class="pem-input" value="{{index .IssuedCert "serial"}}" readonly>
</div>
<div class="form-group">
<label>Expires</label>
<input type="text" value="{{index .IssuedCert "expires_at"}}" readonly>
</div>
<div class="form-group"> <div class="form-group">
<label>Certificate PEM</label> <label>Certificate PEM</label>
<textarea rows="8" class="pem-input" readonly>{{index .IssuedCert "cert_pem"}}</textarea> <textarea rows="8" class="pem-input" readonly>{{index .IssuedCert "cert_pem"}}</textarea>
@@ -89,8 +122,6 @@
<label>Chain PEM</label> <label>Chain PEM</label>
<textarea rows="8" class="pem-input" readonly>{{index .IssuedCert "chain_pem"}}</textarea> <textarea rows="8" class="pem-input" readonly>{{index .IssuedCert "chain_pem"}}</textarea>
</div> </div>
<p><small>Serial: {{index .IssuedCert "serial"}} &mdash; Expires: {{index .IssuedCert "expires_at"}}</small></p>
</div>
{{else}} {{else}}
<form method="post" action="/pki/issue"> <form method="post" action="/pki/issue">
<div class="form-row"> <div class="form-row">
@@ -101,7 +132,7 @@
<div class="form-group"> <div class="form-group">
<label for="issue_issuer">Issuer</label> <label for="issue_issuer">Issuer</label>
<select id="issue_issuer" name="issuer" required> <select id="issue_issuer" name="issuer" required>
<option value="">-- select issuer --</option> <option value=""> select issuer </option>
{{range .Issuers}}<option value="{{.}}">{{.}}</option>{{end}} {{range .Issuers}}<option value="{{.}}">{{.}}</option>{{end}}
</select> </select>
</div> </div>
@@ -116,31 +147,63 @@
</select> </select>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="issue_ttl">TTL (optional)</label> <label for="issue_ttl">TTL <small style="text-transform:none;letter-spacing:0;">(optional)</small></label>
<input type="text" id="issue_ttl" name="ttl" placeholder="2160h"> <input type="text" id="issue_ttl" name="ttl" placeholder="2160h">
</div> </div>
</div> </div>
<details> <details>
<summary>SANs</summary> <summary>Subject Alternative Names</summary>
<div class="form-row"> <div class="form-row">
<div class="form-group"> <div class="form-group">
<label for="issue_dns">DNS Names (one per line)</label> <label for="issue_dns">DNS Names <small style="text-transform:none;letter-spacing:0;">(one per line)</small></label>
<textarea id="issue_dns" name="dns_names" rows="3" placeholder="example.com&#10;www.example.com"></textarea> <textarea id="issue_dns" name="dns_names" rows="3" placeholder="example.com&#10;www.example.com"></textarea>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="issue_ips">IP Addresses (one per line)</label> <label for="issue_ips">IP Addresses <small style="text-transform:none;letter-spacing:0;">(one per line)</small></label>
<textarea id="issue_ips" name="ip_addresses" rows="3" placeholder="10.0.0.1"></textarea> <textarea id="issue_ips" name="ip_addresses" rows="3" placeholder="10.0.0.1"></textarea>
</div> </div>
</div> </div>
</details> </details>
<details open>
<summary>Key Usages</summary>
<div class="form-row">
<div class="form-group">
<label>Key Usages</label>
<div class="checkbox-group">
<label class="checkbox-label"><input type="checkbox" name="key_usages" value="digital signature"> Digital Signature</label>
<label class="checkbox-label"><input type="checkbox" name="key_usages" value="key encipherment"> Key Encipherment</label>
<label class="checkbox-label"><input type="checkbox" name="key_usages" value="content commitment"> Content Commitment</label>
<label class="checkbox-label"><input type="checkbox" name="key_usages" value="data encipherment"> Data Encipherment</label>
<label class="checkbox-label"><input type="checkbox" name="key_usages" value="key agreement"> Key Agreement</label>
<label class="checkbox-label"><input type="checkbox" name="key_usages" value="cert sign"> Cert Sign</label>
<label class="checkbox-label"><input type="checkbox" name="key_usages" value="crl sign"> CRL Sign</label>
</div>
</div>
<div class="form-group">
<label>Extended Key Usages</label>
<div class="checkbox-group">
<label class="checkbox-label"><input type="checkbox" name="ext_key_usages" value="server auth"> Server Auth</label>
<label class="checkbox-label"><input type="checkbox" name="ext_key_usages" value="client auth"> Client Auth</label>
<label class="checkbox-label"><input type="checkbox" name="ext_key_usages" value="code signing"> Code Signing</label>
<label class="checkbox-label"><input type="checkbox" name="ext_key_usages" value="email protection"> Email Protection</label>
<label class="checkbox-label"><input type="checkbox" name="ext_key_usages" value="time stamping"> Time Stamping</label>
<label class="checkbox-label"><input type="checkbox" name="ext_key_usages" value="ocsp signing"> OCSP Signing</label>
</div>
</div>
</div>
</details>
<div class="form-actions">
<button type="submit">Issue Certificate</button> <button type="submit">Issue Certificate</button>
</div>
</form> </form>
{{end}} {{end}}
</div>
{{end}} {{end}}
{{if .IsAdmin}} {{if .IsAdmin}}
{{if .HasRoot}} {{if .HasRoot}}
<h3>Create Issuer</h3> <div class="card">
<div class="card-title">Create Issuer</div>
{{if .IssuerError}}<div class="error">{{.IssuerError}}</div>{{end}} {{if .IssuerError}}<div class="error">{{.IssuerError}}</div>{{end}}
<form method="post" action="/pki/create-issuer"> <form method="post" action="/pki/create-issuer">
<div class="form-row"> <div class="form-row">
@@ -170,8 +233,11 @@
<input type="text" id="issuer_max_ttl" name="max_ttl" placeholder="2160h (90 days)"> <input type="text" id="issuer_max_ttl" name="max_ttl" placeholder="2160h (90 days)">
</div> </div>
</details> </details>
<div class="form-actions">
<button type="submit">Create Issuer</button> <button type="submit">Create Issuer</button>
</div>
</form> </form>
</div>
{{end}} {{end}}
{{end}} {{end}}
{{end}} {{end}}

View File

@@ -1,13 +1,22 @@
{{define "title"}} - Unseal{{end}} {{define "title"}} - Unseal{{end}}
{{define "container-class"}}auth-container{{end}}
{{define "content"}} {{define "content"}}
<h2>Unseal Metacrypt</h2> <div class="auth-header">
<p>The service is sealed. Enter the seal password to unseal.</p> <div class="brand">Metacrypt</div>
<div class="tagline">Cryptographic Services</div>
</div>
<div class="card">
<div class="card-title">Unseal</div>
<p>The service is sealed. Enter the seal password to restore access.</p>
{{if .Error}}<div class="error">{{.Error}}</div>{{end}} {{if .Error}}<div class="error">{{.Error}}</div>{{end}}
<form method="POST" action="/unseal"> <form method="POST" action="/unseal">
<div class="form-group"> <div class="form-group">
<label for="password">Seal Password</label> <label for="password">Seal Password</label>
<input type="password" id="password" name="password" required autofocus> <input type="password" id="password" name="password" required autofocus autocomplete="current-password">
</div> </div>
<div class="form-actions">
<button type="submit">Unseal</button> <button type="submit">Unseal</button>
</div>
</form> </form>
</div>
{{end}} {{end}}