Separate web UI into standalone metacrypt-web binary

The vault server holds in-memory unsealed state (KEK, engine keys) that
is lost on restart, requiring a full unseal ceremony. Previously the web
UI ran inside the vault process, so any UI change forced a restart and
re-unseal.

This change extracts the web UI into a separate metacrypt-web binary
that communicates with the vault over an authenticated gRPC connection.
The web server carries no sealed state and can be restarted freely.

- gen/metacrypt/v1/: generated Go bindings from proto/metacrypt/v1/
- internal/grpcserver/: full gRPC server implementation (System, Auth,
  Engine, PKI, Policy, ACME services) with seal/auth/admin interceptors
- internal/webserver/: web server with gRPC vault client; templates
  embedded via web/embed.go (no runtime web/ directory needed)
- cmd/metacrypt-web/: standalone binary entry point
- internal/config: added [web] section (listen_addr, vault_grpc, etc.)
- internal/server/routes.go: removed all web UI routes and handlers
- cmd/metacrypt/server.go: starts gRPC server alongside HTTP server
- Deploy: Dockerfile builds both binaries, docker-compose adds
  metacrypt-web service, new metacrypt-web.service systemd unit,
  Makefile gains proto/metacrypt-web targets

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-15 09:07:12 -07:00
parent b8e348db03
commit cc1ac2e255
37 changed files with 5668 additions and 647 deletions

View File

@@ -8,6 +8,7 @@ RUN go mod download
COPY . . COPY . .
RUN CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o /metacrypt ./cmd/metacrypt RUN CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o /metacrypt ./cmd/metacrypt
RUN CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o /metacrypt-web ./cmd/metacrypt-web
FROM alpine:3.21 FROM alpine:3.21
@@ -17,7 +18,7 @@ RUN apk add --no-cache ca-certificates tzdata \
&& mkdir -p /srv/metacrypt && chown metacrypt:metacrypt /srv/metacrypt && mkdir -p /srv/metacrypt && chown metacrypt:metacrypt /srv/metacrypt
COPY --from=builder /metacrypt /usr/local/bin/metacrypt COPY --from=builder /metacrypt /usr/local/bin/metacrypt
COPY web/ /srv/metacrypt/web/ COPY --from=builder /metacrypt-web /usr/local/bin/metacrypt-web
# /srv/metacrypt is the single volume mount point. # /srv/metacrypt is the single volume mount point.
# It must contain: # It must contain:

View File

@@ -1,7 +1,17 @@
.PHONY: build test vet clean docker all devserver metacrypt .PHONY: build test vet clean docker all devserver metacrypt metacrypt-web proto
LDFLAGS := -trimpath -ldflags="-s -w -X main.version=$(shell git describe --tags --always --dirty 2>/dev/null || echo dev)"
proto:
protoc --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
proto/metacrypt/v1/*.proto
metacrypt: metacrypt:
go build -trimpath -ldflags="-s -w -X main.version=$(shell git describe --tags --always --dirty 2>/dev/null || echo dev)" -o metacrypt ./cmd/metacrypt go build $(LDFLAGS) -o metacrypt ./cmd/metacrypt
metacrypt-web:
go build $(LDFLAGS) -o metacrypt-web ./cmd/metacrypt-web
build: build:
go build ./... go build ./...
@@ -13,7 +23,7 @@ vet:
go vet ./... go vet ./...
clean: clean:
rm -f metacrypt rm -f metacrypt metacrypt-web
docker: docker:
docker build -t metacrypt . docker build -t metacrypt .
@@ -21,7 +31,8 @@ docker:
docker-compose: docker-compose:
docker compose -f deploy/docker/docker-compose.yml up --build docker compose -f deploy/docker/docker-compose.yml up --build
devserver: metacrypt devserver: metacrypt metacrypt-web
./metacrypt server --config srv/metacrypt.toml ./metacrypt server --config srv/metacrypt.toml &
./metacrypt-web --config srv/metacrypt.toml
all: vet test metacrypt all: vet test metacrypt metacrypt-web

75
cmd/metacrypt-web/main.go Normal file
View File

@@ -0,0 +1,75 @@
// metacrypt-web is the standalone web UI server for Metacrypt.
// It communicates with the vault over gRPC and can be restarted independently
// without requiring the vault to be re-unsealed.
package main
import (
"context"
"fmt"
"log/slog"
"os"
"os/signal"
"syscall"
"github.com/spf13/cobra"
"git.wntrmute.dev/kyle/metacrypt/internal/config"
"git.wntrmute.dev/kyle/metacrypt/internal/webserver"
)
var cfgFile string
var rootCmd = &cobra.Command{
Use: "metacrypt-web",
Short: "Metacrypt web UI server",
Long: "Standalone web UI server for Metacrypt. Communicates with the vault over gRPC.",
RunE: run,
}
func init() {
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default /srv/metacrypt/metacrypt.toml)")
}
func run(cmd *cobra.Command, args []string) error {
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
configPath := cfgFile
if configPath == "" {
configPath = "/srv/metacrypt/metacrypt.toml"
}
cfg, err := config.Load(configPath)
if err != nil {
return err
}
if cfg.Web.VaultGRPC == "" {
return fmt.Errorf("web.vault_grpc is required in config")
}
ws, err := webserver.New(cfg, logger)
if err != nil {
return err
}
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stop()
go func() {
if err := ws.Start(); err != nil {
logger.Error("web server error", "error", err)
os.Exit(1)
}
}()
<-ctx.Done()
logger.Info("shutting down web server")
return ws.Shutdown(context.Background())
}
func main() {
if err := rootCmd.Execute(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}

View File

@@ -16,6 +16,7 @@ import (
"git.wntrmute.dev/kyle/metacrypt/internal/db" "git.wntrmute.dev/kyle/metacrypt/internal/db"
"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"
"git.wntrmute.dev/kyle/metacrypt/internal/grpcserver"
"git.wntrmute.dev/kyle/metacrypt/internal/policy" "git.wntrmute.dev/kyle/metacrypt/internal/policy"
"git.wntrmute.dev/kyle/metacrypt/internal/seal" "git.wntrmute.dev/kyle/metacrypt/internal/seal"
"git.wntrmute.dev/kyle/metacrypt/internal/server" "git.wntrmute.dev/kyle/metacrypt/internal/server"
@@ -75,10 +76,18 @@ func runServer(cmd *cobra.Command, args []string) error {
engineRegistry.RegisterFactory(engine.EngineTypeCA, ca.NewCAEngine) engineRegistry.RegisterFactory(engine.EngineTypeCA, ca.NewCAEngine)
srv := server.New(cfg, sealMgr, authenticator, policyEngine, engineRegistry, logger, version) srv := server.New(cfg, sealMgr, authenticator, policyEngine, engineRegistry, logger, version)
grpcSrv := grpcserver.New(cfg, sealMgr, authenticator, policyEngine, engineRegistry, logger)
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stop() defer stop()
go func() {
if err := grpcSrv.Start(); err != nil {
logger.Error("gRPC server error", "error", err)
os.Exit(1)
}
}()
go func() { go func() {
if err := srv.Start(); err != nil { if err := srv.Start(); err != nil {
logger.Error("server error", "error", err) logger.Error("server error", "error", err)
@@ -97,6 +106,7 @@ func runServer(cmd *cobra.Command, args []string) error {
<-ctx.Done() <-ctx.Done()
logger.Info("shutting down") logger.Info("shutting down")
grpcSrv.Shutdown()
srv.ShutdownGRPC() srv.ShutdownGRPC()
return srv.Shutdown(context.Background()) return srv.Shutdown(context.Background())
} }

View File

@@ -7,12 +7,9 @@ services:
restart: unless-stopped restart: unless-stopped
ports: ports:
- "8443:8443" - "8443:8443"
- "9443:9443"
volumes: volumes:
- metacrypt-data:/srv/metacrypt - metacrypt-data:/srv/metacrypt
# To populate /srv/metacrypt before first run, use an init container or
# bind-mount a host directory instead of a named volume:
# volumes:
# - ./data:/srv/metacrypt
healthcheck: healthcheck:
test: ["CMD", "metacrypt", "status", "--addr", "https://localhost:8443", "--ca-cert", "/srv/metacrypt/certs/ca.crt"] test: ["CMD", "metacrypt", "status", "--addr", "https://localhost:8443", "--ca-cert", "/srv/metacrypt/certs/ca.crt"]
interval: 30s interval: 30s
@@ -20,5 +17,19 @@ services:
retries: 3 retries: 3
start_period: 10s start_period: 10s
metacrypt-web:
build:
context: ../..
dockerfile: Dockerfile
container_name: metacrypt-web
command: ["/usr/local/bin/metacrypt-web", "--config", "/srv/metacrypt/metacrypt.toml"]
restart: unless-stopped
ports:
- "8080:8080"
volumes:
- metacrypt-data:/srv/metacrypt
depends_on:
- metacrypt
volumes: volumes:
metacrypt-data: metacrypt-data:

View File

@@ -0,0 +1,46 @@
[Unit]
Description=Metacrypt web UI server
Documentation=https://git.wntrmute.dev/kyle/metacrypt
After=network-online.target metacrypt.service
Wants=network-online.target
Requires=metacrypt.service
[Service]
Type=simple
User=metacrypt
Group=metacrypt
ExecStart=/usr/local/bin/metacrypt-web --config /srv/metacrypt/metacrypt.toml
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5
# Security hardening
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
PrivateDevices=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
RestrictSUIDSGID=true
RestrictNamespaces=true
LockPersonality=true
MemoryDenyWriteExecute=true
RestrictRealtime=true
# Allow read access to config and certs
ReadOnlyPaths=/srv/metacrypt
# Limit file descriptor count
LimitNOFILE=65535
# Logging
StandardOutput=journal
StandardError=journal
SyslogIdentifier=metacrypt-web
[Install]
WantedBy=multi-user.target

670
gen/metacrypt/v1/acme.pb.go Normal file
View File

@@ -0,0 +1,670 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc v3.20.3
// source: metacrypt/v1/acme.proto
package metacryptv1
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 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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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 SetACMEConfigRequest 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 *SetACMEConfigRequest) Reset() {
*x = SetACMEConfigRequest{}
mi := &file_metacrypt_v1_acme_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *SetACMEConfigRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SetACMEConfigRequest) ProtoMessage() {}
func (x *SetACMEConfigRequest) ProtoReflect() protoreflect.Message {
mi := &file_metacrypt_v1_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 SetACMEConfigRequest.ProtoReflect.Descriptor instead.
func (*SetACMEConfigRequest) Descriptor() ([]byte, []int) {
return file_metacrypt_v1_acme_proto_rawDescGZIP(), []int{2}
}
func (x *SetACMEConfigRequest) GetMount() string {
if x != nil {
return x.Mount
}
return ""
}
func (x *SetACMEConfigRequest) GetDefaultIssuer() string {
if x != nil {
return x.DefaultIssuer
}
return ""
}
type SetACMEConfigResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
Ok bool `protobuf:"varint,1,opt,name=ok,proto3" json:"ok,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *SetACMEConfigResponse) Reset() {
*x = SetACMEConfigResponse{}
mi := &file_metacrypt_v1_acme_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *SetACMEConfigResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SetACMEConfigResponse) ProtoMessage() {}
func (x *SetACMEConfigResponse) ProtoReflect() protoreflect.Message {
mi := &file_metacrypt_v1_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 SetACMEConfigResponse.ProtoReflect.Descriptor instead.
func (*SetACMEConfigResponse) Descriptor() ([]byte, []int) {
return file_metacrypt_v1_acme_proto_rawDescGZIP(), []int{3}
}
func (x *SetACMEConfigResponse) GetOk() bool {
if x != nil {
return x.Ok
}
return false
}
type ListACMEAccountsRequest 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 *ListACMEAccountsRequest) Reset() {
*x = ListACMEAccountsRequest{}
mi := &file_metacrypt_v1_acme_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListACMEAccountsRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListACMEAccountsRequest) ProtoMessage() {}
func (x *ListACMEAccountsRequest) ProtoReflect() protoreflect.Message {
mi := &file_metacrypt_v1_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 ListACMEAccountsRequest.ProtoReflect.Descriptor instead.
func (*ListACMEAccountsRequest) Descriptor() ([]byte, []int) {
return file_metacrypt_v1_acme_proto_rawDescGZIP(), []int{4}
}
func (x *ListACMEAccountsRequest) GetMount() string {
if x != nil {
return x.Mount
}
return ""
}
type ListACMEAccountsResponse 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 *ListACMEAccountsResponse) Reset() {
*x = ListACMEAccountsResponse{}
mi := &file_metacrypt_v1_acme_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListACMEAccountsResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListACMEAccountsResponse) ProtoMessage() {}
func (x *ListACMEAccountsResponse) ProtoReflect() protoreflect.Message {
mi := &file_metacrypt_v1_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 ListACMEAccountsResponse.ProtoReflect.Descriptor instead.
func (*ListACMEAccountsResponse) Descriptor() ([]byte, []int) {
return file_metacrypt_v1_acme_proto_rawDescGZIP(), []int{5}
}
func (x *ListACMEAccountsResponse) 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 string `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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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() string {
if x != nil {
return x.CreatedAt
}
return ""
}
type ListACMEOrdersRequest 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 *ListACMEOrdersRequest) Reset() {
*x = ListACMEOrdersRequest{}
mi := &file_metacrypt_v1_acme_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListACMEOrdersRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListACMEOrdersRequest) ProtoMessage() {}
func (x *ListACMEOrdersRequest) ProtoReflect() protoreflect.Message {
mi := &file_metacrypt_v1_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 ListACMEOrdersRequest.ProtoReflect.Descriptor instead.
func (*ListACMEOrdersRequest) Descriptor() ([]byte, []int) {
return file_metacrypt_v1_acme_proto_rawDescGZIP(), []int{7}
}
func (x *ListACMEOrdersRequest) GetMount() string {
if x != nil {
return x.Mount
}
return ""
}
type ListACMEOrdersResponse 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 *ListACMEOrdersResponse) Reset() {
*x = ListACMEOrdersResponse{}
mi := &file_metacrypt_v1_acme_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListACMEOrdersResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListACMEOrdersResponse) ProtoMessage() {}
func (x *ListACMEOrdersResponse) ProtoReflect() protoreflect.Message {
mi := &file_metacrypt_v1_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 ListACMEOrdersResponse.ProtoReflect.Descriptor instead.
func (*ListACMEOrdersResponse) Descriptor() ([]byte, []int) {
return file_metacrypt_v1_acme_proto_rawDescGZIP(), []int{8}
}
func (x *ListACMEOrdersResponse) 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 string `protobuf:"bytes,5,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
ExpiresAt string `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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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() string {
if x != nil {
return x.CreatedAt
}
return ""
}
func (x *ACMEOrder) GetExpiresAt() string {
if x != nil {
return x.ExpiresAt
}
return ""
}
var File_metacrypt_v1_acme_proto protoreflect.FileDescriptor
const file_metacrypt_v1_acme_proto_rawDesc = "" +
"\n" +
"\x17metacrypt/v1/acme.proto\x12\fmetacrypt.v1\"(\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\"S\n" +
"\x14SetACMEConfigRequest\x12\x14\n" +
"\x05mount\x18\x01 \x01(\tR\x05mount\x12%\n" +
"\x0edefault_issuer\x18\x02 \x01(\tR\rdefaultIssuer\"'\n" +
"\x15SetACMEConfigResponse\x12\x0e\n" +
"\x02ok\x18\x01 \x01(\bR\x02ok\"/\n" +
"\x17ListACMEAccountsRequest\x12\x14\n" +
"\x05mount\x18\x01 \x01(\tR\x05mount\"Q\n" +
"\x18ListACMEAccountsResponse\x125\n" +
"\baccounts\x18\x01 \x03(\v2\x19.metacrypt.v1.ACMEAccountR\baccounts\"\x95\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\x12\x1d\n" +
"\n" +
"created_at\x18\x05 \x01(\tR\tcreatedAt\"-\n" +
"\x15ListACMEOrdersRequest\x12\x14\n" +
"\x05mount\x18\x01 \x01(\tR\x05mount\"I\n" +
"\x16ListACMEOrdersResponse\x12/\n" +
"\x06orders\x18\x01 \x03(\v2\x17.metacrypt.v1.ACMEOrderR\x06orders\"\xb2\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\x12\x1d\n" +
"\n" +
"created_at\x18\x05 \x01(\tR\tcreatedAt\x12\x1d\n" +
"\n" +
"expires_at\x18\x06 \x01(\tR\texpiresAt2\xe9\x02\n" +
"\vACMEService\x12L\n" +
"\tCreateEAB\x12\x1e.metacrypt.v1.CreateEABRequest\x1a\x1f.metacrypt.v1.CreateEABResponse\x12T\n" +
"\tSetConfig\x12\".metacrypt.v1.SetACMEConfigRequest\x1a#.metacrypt.v1.SetACMEConfigResponse\x12]\n" +
"\fListAccounts\x12%.metacrypt.v1.ListACMEAccountsRequest\x1a&.metacrypt.v1.ListACMEAccountsResponse\x12W\n" +
"\n" +
"ListOrders\x12#.metacrypt.v1.ListACMEOrdersRequest\x1a$.metacrypt.v1.ListACMEOrdersResponseB>Z<git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v1;metacryptv1b\x06proto3"
var (
file_metacrypt_v1_acme_proto_rawDescOnce sync.Once
file_metacrypt_v1_acme_proto_rawDescData []byte
)
func file_metacrypt_v1_acme_proto_rawDescGZIP() []byte {
file_metacrypt_v1_acme_proto_rawDescOnce.Do(func() {
file_metacrypt_v1_acme_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_metacrypt_v1_acme_proto_rawDesc), len(file_metacrypt_v1_acme_proto_rawDesc)))
})
return file_metacrypt_v1_acme_proto_rawDescData
}
var file_metacrypt_v1_acme_proto_msgTypes = make([]protoimpl.MessageInfo, 10)
var file_metacrypt_v1_acme_proto_goTypes = []any{
(*CreateEABRequest)(nil), // 0: metacrypt.v1.CreateEABRequest
(*CreateEABResponse)(nil), // 1: metacrypt.v1.CreateEABResponse
(*SetACMEConfigRequest)(nil), // 2: metacrypt.v1.SetACMEConfigRequest
(*SetACMEConfigResponse)(nil), // 3: metacrypt.v1.SetACMEConfigResponse
(*ListACMEAccountsRequest)(nil), // 4: metacrypt.v1.ListACMEAccountsRequest
(*ListACMEAccountsResponse)(nil), // 5: metacrypt.v1.ListACMEAccountsResponse
(*ACMEAccount)(nil), // 6: metacrypt.v1.ACMEAccount
(*ListACMEOrdersRequest)(nil), // 7: metacrypt.v1.ListACMEOrdersRequest
(*ListACMEOrdersResponse)(nil), // 8: metacrypt.v1.ListACMEOrdersResponse
(*ACMEOrder)(nil), // 9: metacrypt.v1.ACMEOrder
}
var file_metacrypt_v1_acme_proto_depIdxs = []int32{
6, // 0: metacrypt.v1.ListACMEAccountsResponse.accounts:type_name -> metacrypt.v1.ACMEAccount
9, // 1: metacrypt.v1.ListACMEOrdersResponse.orders:type_name -> metacrypt.v1.ACMEOrder
0, // 2: metacrypt.v1.ACMEService.CreateEAB:input_type -> metacrypt.v1.CreateEABRequest
2, // 3: metacrypt.v1.ACMEService.SetConfig:input_type -> metacrypt.v1.SetACMEConfigRequest
4, // 4: metacrypt.v1.ACMEService.ListAccounts:input_type -> metacrypt.v1.ListACMEAccountsRequest
7, // 5: metacrypt.v1.ACMEService.ListOrders:input_type -> metacrypt.v1.ListACMEOrdersRequest
1, // 6: metacrypt.v1.ACMEService.CreateEAB:output_type -> metacrypt.v1.CreateEABResponse
3, // 7: metacrypt.v1.ACMEService.SetConfig:output_type -> metacrypt.v1.SetACMEConfigResponse
5, // 8: metacrypt.v1.ACMEService.ListAccounts:output_type -> metacrypt.v1.ListACMEAccountsResponse
8, // 9: metacrypt.v1.ACMEService.ListOrders:output_type -> metacrypt.v1.ListACMEOrdersResponse
6, // [6:10] is the sub-list for method output_type
2, // [2:6] 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_metacrypt_v1_acme_proto_init() }
func file_metacrypt_v1_acme_proto_init() {
if File_metacrypt_v1_acme_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_metacrypt_v1_acme_proto_rawDesc), len(file_metacrypt_v1_acme_proto_rawDesc)),
NumEnums: 0,
NumMessages: 10,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_metacrypt_v1_acme_proto_goTypes,
DependencyIndexes: file_metacrypt_v1_acme_proto_depIdxs,
MessageInfos: file_metacrypt_v1_acme_proto_msgTypes,
}.Build()
File_metacrypt_v1_acme_proto = out.File
file_metacrypt_v1_acme_proto_goTypes = nil
file_metacrypt_v1_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: metacrypt/v1/acme.proto
package metacryptv1
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.v1.ACMEService/CreateEAB"
ACMEService_SetConfig_FullMethodName = "/metacrypt.v1.ACMEService/SetConfig"
ACMEService_ListAccounts_FullMethodName = "/metacrypt.v1.ACMEService/ListAccounts"
ACMEService_ListOrders_FullMethodName = "/metacrypt.v1.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 /v1/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 *SetACMEConfigRequest, opts ...grpc.CallOption) (*SetACMEConfigResponse, error)
// ListAccounts returns all ACME accounts for a CA mount. Admin only.
ListAccounts(ctx context.Context, in *ListACMEAccountsRequest, opts ...grpc.CallOption) (*ListACMEAccountsResponse, error)
// ListOrders returns all ACME orders for a CA mount. Admin only.
ListOrders(ctx context.Context, in *ListACMEOrdersRequest, opts ...grpc.CallOption) (*ListACMEOrdersResponse, 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 *SetACMEConfigRequest, opts ...grpc.CallOption) (*SetACMEConfigResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(SetACMEConfigResponse)
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 *ListACMEAccountsRequest, opts ...grpc.CallOption) (*ListACMEAccountsResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ListACMEAccountsResponse)
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 *ListACMEOrdersRequest, opts ...grpc.CallOption) (*ListACMEOrdersResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ListACMEOrdersResponse)
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 /v1/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, *SetACMEConfigRequest) (*SetACMEConfigResponse, error)
// ListAccounts returns all ACME accounts for a CA mount. Admin only.
ListAccounts(context.Context, *ListACMEAccountsRequest) (*ListACMEAccountsResponse, error)
// ListOrders returns all ACME orders for a CA mount. Admin only.
ListOrders(context.Context, *ListACMEOrdersRequest) (*ListACMEOrdersResponse, 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, *SetACMEConfigRequest) (*SetACMEConfigResponse, error) {
return nil, status.Error(codes.Unimplemented, "method SetConfig not implemented")
}
func (UnimplementedACMEServiceServer) ListAccounts(context.Context, *ListACMEAccountsRequest) (*ListACMEAccountsResponse, error) {
return nil, status.Error(codes.Unimplemented, "method ListAccounts not implemented")
}
func (UnimplementedACMEServiceServer) ListOrders(context.Context, *ListACMEOrdersRequest) (*ListACMEOrdersResponse, 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(SetACMEConfigRequest)
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.(*SetACMEConfigRequest))
}
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(ListACMEAccountsRequest)
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.(*ListACMEAccountsRequest))
}
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(ListACMEOrdersRequest)
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.(*ListACMEOrdersRequest))
}
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.v1.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: "metacrypt/v1/acme.proto",
}

386
gen/metacrypt/v1/auth.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: metacrypt/v1/auth.proto
package metacryptv1
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 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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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 string `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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_auth_proto_rawDescGZIP(), []int{1}
}
func (x *LoginResponse) GetToken() string {
if x != nil {
return x.Token
}
return ""
}
func (x *LoginResponse) GetExpiresAt() string {
if x != nil {
return x.ExpiresAt
}
return ""
}
type LogoutRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *LogoutRequest) Reset() {
*x = LogoutRequest{}
mi := &file_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_auth_proto protoreflect.FileDescriptor
const file_metacrypt_v1_auth_proto_rawDesc = "" +
"\n" +
"\x17metacrypt/v1/auth.proto\x12\fmetacrypt.v1\"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\"D\n" +
"\rLoginResponse\x12\x14\n" +
"\x05token\x18\x01 \x01(\tR\x05token\x12\x1d\n" +
"\n" +
"expires_at\x18\x02 \x01(\tR\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.v1.LoginRequest\x1a\x1b.metacrypt.v1.LoginResponse\x12C\n" +
"\x06Logout\x12\x1b.metacrypt.v1.LogoutRequest\x1a\x1c.metacrypt.v1.LogoutResponse\x12L\n" +
"\tTokenInfo\x12\x1e.metacrypt.v1.TokenInfoRequest\x1a\x1f.metacrypt.v1.TokenInfoResponseB>Z<git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v1;metacryptv1b\x06proto3"
var (
file_metacrypt_v1_auth_proto_rawDescOnce sync.Once
file_metacrypt_v1_auth_proto_rawDescData []byte
)
func file_metacrypt_v1_auth_proto_rawDescGZIP() []byte {
file_metacrypt_v1_auth_proto_rawDescOnce.Do(func() {
file_metacrypt_v1_auth_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_metacrypt_v1_auth_proto_rawDesc), len(file_metacrypt_v1_auth_proto_rawDesc)))
})
return file_metacrypt_v1_auth_proto_rawDescData
}
var file_metacrypt_v1_auth_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_metacrypt_v1_auth_proto_goTypes = []any{
(*LoginRequest)(nil), // 0: metacrypt.v1.LoginRequest
(*LoginResponse)(nil), // 1: metacrypt.v1.LoginResponse
(*LogoutRequest)(nil), // 2: metacrypt.v1.LogoutRequest
(*LogoutResponse)(nil), // 3: metacrypt.v1.LogoutResponse
(*TokenInfoRequest)(nil), // 4: metacrypt.v1.TokenInfoRequest
(*TokenInfoResponse)(nil), // 5: metacrypt.v1.TokenInfoResponse
}
var file_metacrypt_v1_auth_proto_depIdxs = []int32{
0, // 0: metacrypt.v1.AuthService.Login:input_type -> metacrypt.v1.LoginRequest
2, // 1: metacrypt.v1.AuthService.Logout:input_type -> metacrypt.v1.LogoutRequest
4, // 2: metacrypt.v1.AuthService.TokenInfo:input_type -> metacrypt.v1.TokenInfoRequest
1, // 3: metacrypt.v1.AuthService.Login:output_type -> metacrypt.v1.LoginResponse
3, // 4: metacrypt.v1.AuthService.Logout:output_type -> metacrypt.v1.LogoutResponse
5, // 5: metacrypt.v1.AuthService.TokenInfo:output_type -> metacrypt.v1.TokenInfoResponse
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_metacrypt_v1_auth_proto_init() }
func file_metacrypt_v1_auth_proto_init() {
if File_metacrypt_v1_auth_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_metacrypt_v1_auth_proto_rawDesc), len(file_metacrypt_v1_auth_proto_rawDesc)),
NumEnums: 0,
NumMessages: 6,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_metacrypt_v1_auth_proto_goTypes,
DependencyIndexes: file_metacrypt_v1_auth_proto_depIdxs,
MessageInfos: file_metacrypt_v1_auth_proto_msgTypes,
}.Build()
File_metacrypt_v1_auth_proto = out.File
file_metacrypt_v1_auth_proto_goTypes = nil
file_metacrypt_v1_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: metacrypt/v1/auth.proto
package metacryptv1
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.v1.AuthService/Login"
AuthService_Logout_FullMethodName = "/metacrypt.v1.AuthService/Logout"
AuthService_TokenInfo_FullMethodName = "/metacrypt.v1.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.v1.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: "metacrypt/v1/auth.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: metacrypt/v1/common.proto
package metacryptv1
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_metacrypt_v1_common_proto protoreflect.FileDescriptor
const file_metacrypt_v1_common_proto_rawDesc = "" +
"\n" +
"\x19metacrypt/v1/common.proto\x12\fmetacrypt.v1B>Z<git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v1;metacryptv1b\x06proto3"
var file_metacrypt_v1_common_proto_goTypes = []any{}
var file_metacrypt_v1_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_metacrypt_v1_common_proto_init() }
func file_metacrypt_v1_common_proto_init() {
if File_metacrypt_v1_common_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_metacrypt_v1_common_proto_rawDesc), len(file_metacrypt_v1_common_proto_rawDesc)),
NumEnums: 0,
NumMessages: 0,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_metacrypt_v1_common_proto_goTypes,
DependencyIndexes: file_metacrypt_v1_common_proto_depIdxs,
}.Build()
File_metacrypt_v1_common_proto = out.File
file_metacrypt_v1_common_proto_goTypes = nil
file_metacrypt_v1_common_proto_depIdxs = nil
}

View File

@@ -0,0 +1,555 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc v3.20.3
// source: metacrypt/v1/engine.proto
package metacryptv1
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
structpb "google.golang.org/protobuf/types/known/structpb"
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 *structpb.Struct `protobuf:"bytes,3,opt,name=config,proto3" json:"config,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *MountRequest) Reset() {
*x = MountRequest{}
mi := &file_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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() *structpb.Struct {
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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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 ""
}
type EngineRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
Mount string `protobuf:"bytes,1,opt,name=mount,proto3" json:"mount,omitempty"`
Operation string `protobuf:"bytes,2,opt,name=operation,proto3" json:"operation,omitempty"`
Path string `protobuf:"bytes,3,opt,name=path,proto3" json:"path,omitempty"`
Data *structpb.Struct `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *EngineRequest) Reset() {
*x = EngineRequest{}
mi := &file_metacrypt_v1_engine_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *EngineRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*EngineRequest) ProtoMessage() {}
func (x *EngineRequest) ProtoReflect() protoreflect.Message {
mi := &file_metacrypt_v1_engine_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 EngineRequest.ProtoReflect.Descriptor instead.
func (*EngineRequest) Descriptor() ([]byte, []int) {
return file_metacrypt_v1_engine_proto_rawDescGZIP(), []int{7}
}
func (x *EngineRequest) GetMount() string {
if x != nil {
return x.Mount
}
return ""
}
func (x *EngineRequest) GetOperation() string {
if x != nil {
return x.Operation
}
return ""
}
func (x *EngineRequest) GetPath() string {
if x != nil {
return x.Path
}
return ""
}
func (x *EngineRequest) GetData() *structpb.Struct {
if x != nil {
return x.Data
}
return nil
}
type EngineResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
Data *structpb.Struct `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *EngineResponse) Reset() {
*x = EngineResponse{}
mi := &file_metacrypt_v1_engine_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *EngineResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*EngineResponse) ProtoMessage() {}
func (x *EngineResponse) ProtoReflect() protoreflect.Message {
mi := &file_metacrypt_v1_engine_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 EngineResponse.ProtoReflect.Descriptor instead.
func (*EngineResponse) Descriptor() ([]byte, []int) {
return file_metacrypt_v1_engine_proto_rawDescGZIP(), []int{8}
}
func (x *EngineResponse) GetData() *structpb.Struct {
if x != nil {
return x.Data
}
return nil
}
var File_metacrypt_v1_engine_proto protoreflect.FileDescriptor
const file_metacrypt_v1_engine_proto_rawDesc = "" +
"\n" +
"\x19metacrypt/v1/engine.proto\x12\fmetacrypt.v1\x1a\x1cgoogle/protobuf/struct.proto\"g\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 \x01(\v2\x17.google.protobuf.StructR\x06config\"\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.v1.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\tmountPath\"\x84\x01\n" +
"\rEngineRequest\x12\x14\n" +
"\x05mount\x18\x01 \x01(\tR\x05mount\x12\x1c\n" +
"\toperation\x18\x02 \x01(\tR\toperation\x12\x12\n" +
"\x04path\x18\x03 \x01(\tR\x04path\x12+\n" +
"\x04data\x18\x04 \x01(\v2\x17.google.protobuf.StructR\x04data\"=\n" +
"\x0eEngineResponse\x12+\n" +
"\x04data\x18\x01 \x01(\v2\x17.google.protobuf.StructR\x04data2\xb0\x02\n" +
"\rEngineService\x12@\n" +
"\x05Mount\x12\x1a.metacrypt.v1.MountRequest\x1a\x1b.metacrypt.v1.MountResponse\x12F\n" +
"\aUnmount\x12\x1c.metacrypt.v1.UnmountRequest\x1a\x1d.metacrypt.v1.UnmountResponse\x12O\n" +
"\n" +
"ListMounts\x12\x1f.metacrypt.v1.ListMountsRequest\x1a .metacrypt.v1.ListMountsResponse\x12D\n" +
"\aRequest\x12\x1b.metacrypt.v1.EngineRequest\x1a\x1c.metacrypt.v1.EngineResponseB>Z<git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v1;metacryptv1b\x06proto3"
var (
file_metacrypt_v1_engine_proto_rawDescOnce sync.Once
file_metacrypt_v1_engine_proto_rawDescData []byte
)
func file_metacrypt_v1_engine_proto_rawDescGZIP() []byte {
file_metacrypt_v1_engine_proto_rawDescOnce.Do(func() {
file_metacrypt_v1_engine_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_metacrypt_v1_engine_proto_rawDesc), len(file_metacrypt_v1_engine_proto_rawDesc)))
})
return file_metacrypt_v1_engine_proto_rawDescData
}
var file_metacrypt_v1_engine_proto_msgTypes = make([]protoimpl.MessageInfo, 9)
var file_metacrypt_v1_engine_proto_goTypes = []any{
(*MountRequest)(nil), // 0: metacrypt.v1.MountRequest
(*MountResponse)(nil), // 1: metacrypt.v1.MountResponse
(*UnmountRequest)(nil), // 2: metacrypt.v1.UnmountRequest
(*UnmountResponse)(nil), // 3: metacrypt.v1.UnmountResponse
(*ListMountsRequest)(nil), // 4: metacrypt.v1.ListMountsRequest
(*ListMountsResponse)(nil), // 5: metacrypt.v1.ListMountsResponse
(*MountInfo)(nil), // 6: metacrypt.v1.MountInfo
(*EngineRequest)(nil), // 7: metacrypt.v1.EngineRequest
(*EngineResponse)(nil), // 8: metacrypt.v1.EngineResponse
(*structpb.Struct)(nil), // 9: google.protobuf.Struct
}
var file_metacrypt_v1_engine_proto_depIdxs = []int32{
9, // 0: metacrypt.v1.MountRequest.config:type_name -> google.protobuf.Struct
6, // 1: metacrypt.v1.ListMountsResponse.mounts:type_name -> metacrypt.v1.MountInfo
9, // 2: metacrypt.v1.EngineRequest.data:type_name -> google.protobuf.Struct
9, // 3: metacrypt.v1.EngineResponse.data:type_name -> google.protobuf.Struct
0, // 4: metacrypt.v1.EngineService.Mount:input_type -> metacrypt.v1.MountRequest
2, // 5: metacrypt.v1.EngineService.Unmount:input_type -> metacrypt.v1.UnmountRequest
4, // 6: metacrypt.v1.EngineService.ListMounts:input_type -> metacrypt.v1.ListMountsRequest
7, // 7: metacrypt.v1.EngineService.Request:input_type -> metacrypt.v1.EngineRequest
1, // 8: metacrypt.v1.EngineService.Mount:output_type -> metacrypt.v1.MountResponse
3, // 9: metacrypt.v1.EngineService.Unmount:output_type -> metacrypt.v1.UnmountResponse
5, // 10: metacrypt.v1.EngineService.ListMounts:output_type -> metacrypt.v1.ListMountsResponse
8, // 11: metacrypt.v1.EngineService.Request:output_type -> metacrypt.v1.EngineResponse
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_metacrypt_v1_engine_proto_init() }
func file_metacrypt_v1_engine_proto_init() {
if File_metacrypt_v1_engine_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_metacrypt_v1_engine_proto_rawDesc), len(file_metacrypt_v1_engine_proto_rawDesc)),
NumEnums: 0,
NumMessages: 9,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_metacrypt_v1_engine_proto_goTypes,
DependencyIndexes: file_metacrypt_v1_engine_proto_depIdxs,
MessageInfos: file_metacrypt_v1_engine_proto_msgTypes,
}.Build()
File_metacrypt_v1_engine_proto = out.File
file_metacrypt_v1_engine_proto_goTypes = nil
file_metacrypt_v1_engine_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: metacrypt/v1/engine.proto
package metacryptv1
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.v1.EngineService/Mount"
EngineService_Unmount_FullMethodName = "/metacrypt.v1.EngineService/Unmount"
EngineService_ListMounts_FullMethodName = "/metacrypt.v1.EngineService/ListMounts"
EngineService_Request_FullMethodName = "/metacrypt.v1.EngineService/Request"
)
// 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.
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)
Request(ctx context.Context, in *EngineRequest, opts ...grpc.CallOption) (*EngineResponse, 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
}
func (c *engineServiceClient) Request(ctx context.Context, in *EngineRequest, opts ...grpc.CallOption) (*EngineResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(EngineResponse)
err := c.cc.Invoke(ctx, EngineService_Request_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.
type EngineServiceServer interface {
Mount(context.Context, *MountRequest) (*MountResponse, error)
Unmount(context.Context, *UnmountRequest) (*UnmountResponse, error)
ListMounts(context.Context, *ListMountsRequest) (*ListMountsResponse, error)
Request(context.Context, *EngineRequest) (*EngineResponse, 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) Request(context.Context, *EngineRequest) (*EngineResponse, error) {
return nil, status.Error(codes.Unimplemented, "method Request 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)
}
func _EngineService_Request_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(EngineRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(EngineServiceServer).Request(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: EngineService_Request_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(EngineServiceServer).Request(ctx, req.(*EngineRequest))
}
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.v1.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,
},
{
MethodName: "Request",
Handler: _EngineService_Request_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "metacrypt/v1/engine.proto",
}

386
gen/metacrypt/v1/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: metacrypt/v1/pki.proto
package metacryptv1
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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_pki_proto_rawDescGZIP(), []int{5}
}
func (x *GetIssuerCertResponse) GetCertPem() []byte {
if x != nil {
return x.CertPem
}
return nil
}
var File_metacrypt_v1_pki_proto protoreflect.FileDescriptor
const file_metacrypt_v1_pki_proto_rawDesc = "" +
"\n" +
"\x16metacrypt/v1/pki.proto\x12\fmetacrypt.v1\"*\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.v1.GetRootCertRequest\x1a!.metacrypt.v1.GetRootCertResponse\x12I\n" +
"\bGetChain\x12\x1d.metacrypt.v1.GetChainRequest\x1a\x1e.metacrypt.v1.GetChainResponse\x12X\n" +
"\rGetIssuerCert\x12\".metacrypt.v1.GetIssuerCertRequest\x1a#.metacrypt.v1.GetIssuerCertResponseB>Z<git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v1;metacryptv1b\x06proto3"
var (
file_metacrypt_v1_pki_proto_rawDescOnce sync.Once
file_metacrypt_v1_pki_proto_rawDescData []byte
)
func file_metacrypt_v1_pki_proto_rawDescGZIP() []byte {
file_metacrypt_v1_pki_proto_rawDescOnce.Do(func() {
file_metacrypt_v1_pki_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_metacrypt_v1_pki_proto_rawDesc), len(file_metacrypt_v1_pki_proto_rawDesc)))
})
return file_metacrypt_v1_pki_proto_rawDescData
}
var file_metacrypt_v1_pki_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_metacrypt_v1_pki_proto_goTypes = []any{
(*GetRootCertRequest)(nil), // 0: metacrypt.v1.GetRootCertRequest
(*GetRootCertResponse)(nil), // 1: metacrypt.v1.GetRootCertResponse
(*GetChainRequest)(nil), // 2: metacrypt.v1.GetChainRequest
(*GetChainResponse)(nil), // 3: metacrypt.v1.GetChainResponse
(*GetIssuerCertRequest)(nil), // 4: metacrypt.v1.GetIssuerCertRequest
(*GetIssuerCertResponse)(nil), // 5: metacrypt.v1.GetIssuerCertResponse
}
var file_metacrypt_v1_pki_proto_depIdxs = []int32{
0, // 0: metacrypt.v1.PKIService.GetRootCert:input_type -> metacrypt.v1.GetRootCertRequest
2, // 1: metacrypt.v1.PKIService.GetChain:input_type -> metacrypt.v1.GetChainRequest
4, // 2: metacrypt.v1.PKIService.GetIssuerCert:input_type -> metacrypt.v1.GetIssuerCertRequest
1, // 3: metacrypt.v1.PKIService.GetRootCert:output_type -> metacrypt.v1.GetRootCertResponse
3, // 4: metacrypt.v1.PKIService.GetChain:output_type -> metacrypt.v1.GetChainResponse
5, // 5: metacrypt.v1.PKIService.GetIssuerCert:output_type -> metacrypt.v1.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_metacrypt_v1_pki_proto_init() }
func file_metacrypt_v1_pki_proto_init() {
if File_metacrypt_v1_pki_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_metacrypt_v1_pki_proto_rawDesc), len(file_metacrypt_v1_pki_proto_rawDesc)),
NumEnums: 0,
NumMessages: 6,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_metacrypt_v1_pki_proto_goTypes,
DependencyIndexes: file_metacrypt_v1_pki_proto_depIdxs,
MessageInfos: file_metacrypt_v1_pki_proto_msgTypes,
}.Build()
File_metacrypt_v1_pki_proto = out.File
file_metacrypt_v1_pki_proto_goTypes = nil
file_metacrypt_v1_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: metacrypt/v1/pki.proto
package metacryptv1
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.v1.PKIService/GetRootCert"
PKIService_GetChain_FullMethodName = "/metacrypt.v1.PKIService/GetChain"
PKIService_GetIssuerCert_FullMethodName = "/metacrypt.v1.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.v1.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: "metacrypt/v1/pki.proto",
}

View File

@@ -0,0 +1,456 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc v3.20.3
// source: metacrypt/v1/policy.proto
package metacryptv1
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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_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_metacrypt_v1_policy_proto_rawDescGZIP(), []int{1}
}
func (x *CreatePolicyRequest) 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_metacrypt_v1_policy_proto_msgTypes[2]
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_metacrypt_v1_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 ListPoliciesRequest.ProtoReflect.Descriptor instead.
func (*ListPoliciesRequest) Descriptor() ([]byte, []int) {
return file_metacrypt_v1_policy_proto_rawDescGZIP(), []int{2}
}
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_metacrypt_v1_policy_proto_msgTypes[3]
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_metacrypt_v1_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 ListPoliciesResponse.ProtoReflect.Descriptor instead.
func (*ListPoliciesResponse) Descriptor() ([]byte, []int) {
return file_metacrypt_v1_policy_proto_rawDescGZIP(), []int{3}
}
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_metacrypt_v1_policy_proto_msgTypes[4]
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_metacrypt_v1_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 GetPolicyRequest.ProtoReflect.Descriptor instead.
func (*GetPolicyRequest) Descriptor() ([]byte, []int) {
return file_metacrypt_v1_policy_proto_rawDescGZIP(), []int{4}
}
func (x *GetPolicyRequest) GetId() string {
if x != nil {
return x.Id
}
return ""
}
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_metacrypt_v1_policy_proto_msgTypes[5]
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_metacrypt_v1_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 DeletePolicyRequest.ProtoReflect.Descriptor instead.
func (*DeletePolicyRequest) Descriptor() ([]byte, []int) {
return file_metacrypt_v1_policy_proto_rawDescGZIP(), []int{5}
}
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_metacrypt_v1_policy_proto_msgTypes[6]
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_metacrypt_v1_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 DeletePolicyResponse.ProtoReflect.Descriptor instead.
func (*DeletePolicyResponse) Descriptor() ([]byte, []int) {
return file_metacrypt_v1_policy_proto_rawDescGZIP(), []int{6}
}
var File_metacrypt_v1_policy_proto protoreflect.FileDescriptor
const file_metacrypt_v1_policy_proto_rawDesc = "" +
"\n" +
"\x19metacrypt/v1/policy.proto\x12\fmetacrypt.v1\"\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.v1.PolicyRuleR\x04rule\"\x15\n" +
"\x13ListPoliciesRequest\"F\n" +
"\x14ListPoliciesResponse\x12.\n" +
"\x05rules\x18\x01 \x03(\v2\x18.metacrypt.v1.PolicyRuleR\x05rules\"\"\n" +
"\x10GetPolicyRequest\x12\x0e\n" +
"\x02id\x18\x01 \x01(\tR\x02id\"%\n" +
"\x13DeletePolicyRequest\x12\x0e\n" +
"\x02id\x18\x01 \x01(\tR\x02id\"\x16\n" +
"\x14DeletePolicyResponse2\xd1\x02\n" +
"\rPolicyService\x12K\n" +
"\fCreatePolicy\x12!.metacrypt.v1.CreatePolicyRequest\x1a\x18.metacrypt.v1.PolicyRule\x12U\n" +
"\fListPolicies\x12!.metacrypt.v1.ListPoliciesRequest\x1a\".metacrypt.v1.ListPoliciesResponse\x12E\n" +
"\tGetPolicy\x12\x1e.metacrypt.v1.GetPolicyRequest\x1a\x18.metacrypt.v1.PolicyRule\x12U\n" +
"\fDeletePolicy\x12!.metacrypt.v1.DeletePolicyRequest\x1a\".metacrypt.v1.DeletePolicyResponseB>Z<git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v1;metacryptv1b\x06proto3"
var (
file_metacrypt_v1_policy_proto_rawDescOnce sync.Once
file_metacrypt_v1_policy_proto_rawDescData []byte
)
func file_metacrypt_v1_policy_proto_rawDescGZIP() []byte {
file_metacrypt_v1_policy_proto_rawDescOnce.Do(func() {
file_metacrypt_v1_policy_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_metacrypt_v1_policy_proto_rawDesc), len(file_metacrypt_v1_policy_proto_rawDesc)))
})
return file_metacrypt_v1_policy_proto_rawDescData
}
var file_metacrypt_v1_policy_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
var file_metacrypt_v1_policy_proto_goTypes = []any{
(*PolicyRule)(nil), // 0: metacrypt.v1.PolicyRule
(*CreatePolicyRequest)(nil), // 1: metacrypt.v1.CreatePolicyRequest
(*ListPoliciesRequest)(nil), // 2: metacrypt.v1.ListPoliciesRequest
(*ListPoliciesResponse)(nil), // 3: metacrypt.v1.ListPoliciesResponse
(*GetPolicyRequest)(nil), // 4: metacrypt.v1.GetPolicyRequest
(*DeletePolicyRequest)(nil), // 5: metacrypt.v1.DeletePolicyRequest
(*DeletePolicyResponse)(nil), // 6: metacrypt.v1.DeletePolicyResponse
}
var file_metacrypt_v1_policy_proto_depIdxs = []int32{
0, // 0: metacrypt.v1.CreatePolicyRequest.rule:type_name -> metacrypt.v1.PolicyRule
0, // 1: metacrypt.v1.ListPoliciesResponse.rules:type_name -> metacrypt.v1.PolicyRule
1, // 2: metacrypt.v1.PolicyService.CreatePolicy:input_type -> metacrypt.v1.CreatePolicyRequest
2, // 3: metacrypt.v1.PolicyService.ListPolicies:input_type -> metacrypt.v1.ListPoliciesRequest
4, // 4: metacrypt.v1.PolicyService.GetPolicy:input_type -> metacrypt.v1.GetPolicyRequest
5, // 5: metacrypt.v1.PolicyService.DeletePolicy:input_type -> metacrypt.v1.DeletePolicyRequest
0, // 6: metacrypt.v1.PolicyService.CreatePolicy:output_type -> metacrypt.v1.PolicyRule
3, // 7: metacrypt.v1.PolicyService.ListPolicies:output_type -> metacrypt.v1.ListPoliciesResponse
0, // 8: metacrypt.v1.PolicyService.GetPolicy:output_type -> metacrypt.v1.PolicyRule
6, // 9: metacrypt.v1.PolicyService.DeletePolicy:output_type -> metacrypt.v1.DeletePolicyResponse
6, // [6:10] is the sub-list for method output_type
2, // [2:6] 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_metacrypt_v1_policy_proto_init() }
func file_metacrypt_v1_policy_proto_init() {
if File_metacrypt_v1_policy_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_metacrypt_v1_policy_proto_rawDesc), len(file_metacrypt_v1_policy_proto_rawDesc)),
NumEnums: 0,
NumMessages: 7,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_metacrypt_v1_policy_proto_goTypes,
DependencyIndexes: file_metacrypt_v1_policy_proto_depIdxs,
MessageInfos: file_metacrypt_v1_policy_proto_msgTypes,
}.Build()
File_metacrypt_v1_policy_proto = out.File
file_metacrypt_v1_policy_proto_goTypes = nil
file_metacrypt_v1_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: metacrypt/v1/policy.proto
package metacryptv1
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.v1.PolicyService/CreatePolicy"
PolicyService_ListPolicies_FullMethodName = "/metacrypt.v1.PolicyService/ListPolicies"
PolicyService_GetPolicy_FullMethodName = "/metacrypt.v1.PolicyService/GetPolicy"
PolicyService_DeletePolicy_FullMethodName = "/metacrypt.v1.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) (*PolicyRule, error)
ListPolicies(ctx context.Context, in *ListPoliciesRequest, opts ...grpc.CallOption) (*ListPoliciesResponse, error)
GetPolicy(ctx context.Context, in *GetPolicyRequest, opts ...grpc.CallOption) (*PolicyRule, 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) (*PolicyRule, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(PolicyRule)
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) (*PolicyRule, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(PolicyRule)
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) (*PolicyRule, error)
ListPolicies(context.Context, *ListPoliciesRequest) (*ListPoliciesResponse, error)
GetPolicy(context.Context, *GetPolicyRequest) (*PolicyRule, 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) (*PolicyRule, 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) (*PolicyRule, 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.v1.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: "metacrypt/v1/policy.proto",
}

View File

@@ -1,5 +1,8 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// source: proto/metacrypt/v1/system.proto // versions:
// protoc-gen-go v1.36.11
// protoc v3.20.3
// source: metacrypt/v1/system.proto
package metacryptv1 package metacryptv1
@@ -8,10 +11,13 @@ import (
protoimpl "google.golang.org/protobuf/runtime/protoimpl" protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect" reflect "reflect"
sync "sync" sync "sync"
unsafe "unsafe"
) )
const ( const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
) )
@@ -23,14 +29,19 @@ type StatusRequest struct {
func (x *StatusRequest) Reset() { func (x *StatusRequest) Reset() {
*x = StatusRequest{} *x = StatusRequest{}
mi := &file_system_proto_msgTypes[0] mi := &file_metacrypt_v1_system_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
func (x *StatusRequest) String() string { return protoimpl.X.MessageStringOf(x) }
func (x *StatusRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*StatusRequest) ProtoMessage() {} func (*StatusRequest) ProtoMessage() {}
func (x *StatusRequest) ProtoReflect() protoreflect.Message { func (x *StatusRequest) ProtoReflect() protoreflect.Message {
mi := &file_system_proto_msgTypes[0] mi := &file_metacrypt_v1_system_proto_msgTypes[0]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -41,6 +52,11 @@ func (x *StatusRequest) ProtoReflect() protoreflect.Message {
return mi.MessageOf(x) return mi.MessageOf(x)
} }
// Deprecated: Use StatusRequest.ProtoReflect.Descriptor instead.
func (*StatusRequest) Descriptor() ([]byte, []int) {
return file_metacrypt_v1_system_proto_rawDescGZIP(), []int{0}
}
type StatusResponse struct { type StatusResponse struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState `protogen:"open.v1"`
State string `protobuf:"bytes,1,opt,name=state,proto3" json:"state,omitempty"` State string `protobuf:"bytes,1,opt,name=state,proto3" json:"state,omitempty"`
@@ -50,14 +66,19 @@ type StatusResponse struct {
func (x *StatusResponse) Reset() { func (x *StatusResponse) Reset() {
*x = StatusResponse{} *x = StatusResponse{}
mi := &file_system_proto_msgTypes[1] mi := &file_metacrypt_v1_system_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
func (x *StatusResponse) String() string { return protoimpl.X.MessageStringOf(x) }
func (x *StatusResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*StatusResponse) ProtoMessage() {} func (*StatusResponse) ProtoMessage() {}
func (x *StatusResponse) ProtoReflect() protoreflect.Message { func (x *StatusResponse) ProtoReflect() protoreflect.Message {
mi := &file_system_proto_msgTypes[1] mi := &file_metacrypt_v1_system_proto_msgTypes[1]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -67,6 +88,12 @@ func (x *StatusResponse) ProtoReflect() protoreflect.Message {
} }
return mi.MessageOf(x) return mi.MessageOf(x)
} }
// Deprecated: Use StatusResponse.ProtoReflect.Descriptor instead.
func (*StatusResponse) Descriptor() ([]byte, []int) {
return file_metacrypt_v1_system_proto_rawDescGZIP(), []int{1}
}
func (x *StatusResponse) GetState() string { func (x *StatusResponse) GetState() string {
if x != nil { if x != nil {
return x.State return x.State
@@ -83,14 +110,19 @@ type InitRequest struct {
func (x *InitRequest) Reset() { func (x *InitRequest) Reset() {
*x = InitRequest{} *x = InitRequest{}
mi := &file_system_proto_msgTypes[2] mi := &file_metacrypt_v1_system_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
func (x *InitRequest) String() string { return protoimpl.X.MessageStringOf(x) }
func (x *InitRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*InitRequest) ProtoMessage() {} func (*InitRequest) ProtoMessage() {}
func (x *InitRequest) ProtoReflect() protoreflect.Message { func (x *InitRequest) ProtoReflect() protoreflect.Message {
mi := &file_system_proto_msgTypes[2] mi := &file_metacrypt_v1_system_proto_msgTypes[2]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -100,6 +132,12 @@ func (x *InitRequest) ProtoReflect() protoreflect.Message {
} }
return mi.MessageOf(x) return mi.MessageOf(x)
} }
// Deprecated: Use InitRequest.ProtoReflect.Descriptor instead.
func (*InitRequest) Descriptor() ([]byte, []int) {
return file_metacrypt_v1_system_proto_rawDescGZIP(), []int{2}
}
func (x *InitRequest) GetPassword() string { func (x *InitRequest) GetPassword() string {
if x != nil { if x != nil {
return x.Password return x.Password
@@ -116,14 +154,19 @@ type InitResponse struct {
func (x *InitResponse) Reset() { func (x *InitResponse) Reset() {
*x = InitResponse{} *x = InitResponse{}
mi := &file_system_proto_msgTypes[3] mi := &file_metacrypt_v1_system_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
func (x *InitResponse) String() string { return protoimpl.X.MessageStringOf(x) }
func (x *InitResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*InitResponse) ProtoMessage() {} func (*InitResponse) ProtoMessage() {}
func (x *InitResponse) ProtoReflect() protoreflect.Message { func (x *InitResponse) ProtoReflect() protoreflect.Message {
mi := &file_system_proto_msgTypes[3] mi := &file_metacrypt_v1_system_proto_msgTypes[3]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -133,6 +176,12 @@ func (x *InitResponse) ProtoReflect() protoreflect.Message {
} }
return mi.MessageOf(x) return mi.MessageOf(x)
} }
// Deprecated: Use InitResponse.ProtoReflect.Descriptor instead.
func (*InitResponse) Descriptor() ([]byte, []int) {
return file_metacrypt_v1_system_proto_rawDescGZIP(), []int{3}
}
func (x *InitResponse) GetState() string { func (x *InitResponse) GetState() string {
if x != nil { if x != nil {
return x.State return x.State
@@ -149,14 +198,19 @@ type UnsealRequest struct {
func (x *UnsealRequest) Reset() { func (x *UnsealRequest) Reset() {
*x = UnsealRequest{} *x = UnsealRequest{}
mi := &file_system_proto_msgTypes[4] mi := &file_metacrypt_v1_system_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
func (x *UnsealRequest) String() string { return protoimpl.X.MessageStringOf(x) }
func (x *UnsealRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UnsealRequest) ProtoMessage() {} func (*UnsealRequest) ProtoMessage() {}
func (x *UnsealRequest) ProtoReflect() protoreflect.Message { func (x *UnsealRequest) ProtoReflect() protoreflect.Message {
mi := &file_system_proto_msgTypes[4] mi := &file_metacrypt_v1_system_proto_msgTypes[4]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -166,6 +220,12 @@ func (x *UnsealRequest) ProtoReflect() protoreflect.Message {
} }
return mi.MessageOf(x) return mi.MessageOf(x)
} }
// Deprecated: Use UnsealRequest.ProtoReflect.Descriptor instead.
func (*UnsealRequest) Descriptor() ([]byte, []int) {
return file_metacrypt_v1_system_proto_rawDescGZIP(), []int{4}
}
func (x *UnsealRequest) GetPassword() string { func (x *UnsealRequest) GetPassword() string {
if x != nil { if x != nil {
return x.Password return x.Password
@@ -182,14 +242,19 @@ type UnsealResponse struct {
func (x *UnsealResponse) Reset() { func (x *UnsealResponse) Reset() {
*x = UnsealResponse{} *x = UnsealResponse{}
mi := &file_system_proto_msgTypes[5] mi := &file_metacrypt_v1_system_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
func (x *UnsealResponse) String() string { return protoimpl.X.MessageStringOf(x) }
func (x *UnsealResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UnsealResponse) ProtoMessage() {} func (*UnsealResponse) ProtoMessage() {}
func (x *UnsealResponse) ProtoReflect() protoreflect.Message { func (x *UnsealResponse) ProtoReflect() protoreflect.Message {
mi := &file_system_proto_msgTypes[5] mi := &file_metacrypt_v1_system_proto_msgTypes[5]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -199,6 +264,12 @@ func (x *UnsealResponse) ProtoReflect() protoreflect.Message {
} }
return mi.MessageOf(x) return mi.MessageOf(x)
} }
// Deprecated: Use UnsealResponse.ProtoReflect.Descriptor instead.
func (*UnsealResponse) Descriptor() ([]byte, []int) {
return file_metacrypt_v1_system_proto_rawDescGZIP(), []int{5}
}
func (x *UnsealResponse) GetState() string { func (x *UnsealResponse) GetState() string {
if x != nil { if x != nil {
return x.State return x.State
@@ -214,14 +285,19 @@ type SealRequest struct {
func (x *SealRequest) Reset() { func (x *SealRequest) Reset() {
*x = SealRequest{} *x = SealRequest{}
mi := &file_system_proto_msgTypes[6] mi := &file_metacrypt_v1_system_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
func (x *SealRequest) String() string { return protoimpl.X.MessageStringOf(x) }
func (x *SealRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SealRequest) ProtoMessage() {} func (*SealRequest) ProtoMessage() {}
func (x *SealRequest) ProtoReflect() protoreflect.Message { func (x *SealRequest) ProtoReflect() protoreflect.Message {
mi := &file_system_proto_msgTypes[6] mi := &file_metacrypt_v1_system_proto_msgTypes[6]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -232,6 +308,11 @@ func (x *SealRequest) ProtoReflect() protoreflect.Message {
return mi.MessageOf(x) return mi.MessageOf(x)
} }
// Deprecated: Use SealRequest.ProtoReflect.Descriptor instead.
func (*SealRequest) Descriptor() ([]byte, []int) {
return file_metacrypt_v1_system_proto_rawDescGZIP(), []int{6}
}
type SealResponse struct { type SealResponse struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState `protogen:"open.v1"`
State string `protobuf:"bytes,1,opt,name=state,proto3" json:"state,omitempty"` State string `protobuf:"bytes,1,opt,name=state,proto3" json:"state,omitempty"`
@@ -241,14 +322,19 @@ type SealResponse struct {
func (x *SealResponse) Reset() { func (x *SealResponse) Reset() {
*x = SealResponse{} *x = SealResponse{}
mi := &file_system_proto_msgTypes[7] mi := &file_metacrypt_v1_system_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
func (x *SealResponse) String() string { return protoimpl.X.MessageStringOf(x) }
func (x *SealResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SealResponse) ProtoMessage() {} func (*SealResponse) ProtoMessage() {}
func (x *SealResponse) ProtoReflect() protoreflect.Message { func (x *SealResponse) ProtoReflect() protoreflect.Message {
mi := &file_system_proto_msgTypes[7] mi := &file_metacrypt_v1_system_proto_msgTypes[7]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -258,6 +344,12 @@ func (x *SealResponse) ProtoReflect() protoreflect.Message {
} }
return mi.MessageOf(x) return mi.MessageOf(x)
} }
// Deprecated: Use SealResponse.ProtoReflect.Descriptor instead.
func (*SealResponse) Descriptor() ([]byte, []int) {
return file_metacrypt_v1_system_proto_rawDescGZIP(), []int{7}
}
func (x *SealResponse) GetState() string { func (x *SealResponse) GetState() string {
if x != nil { if x != nil {
return x.State return x.State
@@ -265,77 +357,55 @@ func (x *SealResponse) GetState() string {
return "" return ""
} }
// file descriptor compiled from proto/metacrypt/v1/system.proto var File_metacrypt_v1_system_proto protoreflect.FileDescriptor
var file_system_proto_rawDesc = []byte{
0x0a, 0x1e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x61, 0x63, 0x72, 0x79, 0x70, const file_metacrypt_v1_system_proto_rawDesc = "" +
0x74, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x74, "\n" +
0x6f, 0x12, 0x0c, 0x6d, 0x65, 0x74, 0x61, 0x63, 0x72, 0x79, 0x70, 0x74, 0x2e, 0x76, 0x31, 0x22, "\x19metacrypt/v1/system.proto\x12\fmetacrypt.v1\"\x0f\n" +
0x0f, 0x0a, 0x0d, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, "\rStatusRequest\"&\n" +
0x22, 0x27, 0x0a, 0x0e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, "\x0eStatusResponse\x12\x14\n" +
0x73, 0x65, 0x12, 0x15, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, "\x05state\x18\x01 \x01(\tR\x05state\")\n" +
0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x28, 0x0a, 0x0b, 0x49, 0x6e, 0x69, 0x74, "\vInitRequest\x12\x1a\n" +
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, "\bpassword\x18\x01 \x01(\tR\bpassword\"$\n" +
0x6f, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, "\fInitResponse\x12\x14\n" +
0x6f, 0x72, 0x64, 0x22, 0x25, 0x0a, 0x0c, 0x49, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, "\x05state\x18\x01 \x01(\tR\x05state\"+\n" +
0x6e, 0x73, 0x65, 0x12, 0x15, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, "\rUnsealRequest\x12\x1a\n" +
0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x2a, 0x0a, 0x0d, 0x55, 0x6e, 0x73, "\bpassword\x18\x01 \x01(\tR\bpassword\"&\n" +
0x65, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x70, 0x61, "\x0eUnsealResponse\x12\x14\n" +
0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, "\x05state\x18\x01 \x01(\tR\x05state\"\r\n" +
0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x27, 0x0a, 0x0e, 0x55, 0x6e, 0x73, 0x65, 0x61, 0x6c, "\vSealRequest\"$\n" +
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x15, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, "\fSealResponse\x12\x14\n" +
0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x0d, "\x05state\x18\x01 \x01(\tR\x05state2\x97\x02\n" +
0x0a, 0x0b, 0x53, 0x65, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x25, 0x0a, "\rSystemService\x12C\n" +
0x0c, 0x53, 0x65, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x15, 0x0a, "\x06Status\x12\x1b.metacrypt.v1.StatusRequest\x1a\x1c.metacrypt.v1.StatusResponse\x12=\n" +
0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, "\x04Init\x12\x19.metacrypt.v1.InitRequest\x1a\x1a.metacrypt.v1.InitResponse\x12C\n" +
0x61, 0x74, 0x65, 0x32, 0xc7, 0x01, 0x0a, 0x0d, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x53, 0x65, "\x06Unseal\x12\x1b.metacrypt.v1.UnsealRequest\x1a\x1c.metacrypt.v1.UnsealResponse\x12=\n" +
0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x38, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, "\x04Seal\x12\x19.metacrypt.v1.SealRequest\x1a\x1a.metacrypt.v1.SealResponseB>Z<git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v1;metacryptv1b\x06proto3"
0x1b, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x63, 0x72, 0x79, 0x70, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53,
0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6d,
0x65, 0x74, 0x61, 0x63, 0x72, 0x79, 0x70, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74,
0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x04, 0x49, 0x6e,
0x69, 0x74, 0x12, 0x19, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x63, 0x72, 0x79, 0x70, 0x74, 0x2e, 0x76,
0x31, 0x2e, 0x49, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e,
0x6d, 0x65, 0x74, 0x61, 0x63, 0x72, 0x79, 0x70, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x69,
0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x06, 0x55, 0x6e, 0x73,
0x65, 0x61, 0x6c, 0x12, 0x1b, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x63, 0x72, 0x79, 0x70, 0x74, 0x2e,
0x76, 0x31, 0x2e, 0x55, 0x6e, 0x73, 0x65, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x1c, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x63, 0x72, 0x79, 0x70, 0x74, 0x2e, 0x76, 0x31, 0x2e,
0x55, 0x6e, 0x73, 0x65, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e,
0x0a, 0x04, 0x53, 0x65, 0x61, 0x6c, 0x12, 0x19, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x63, 0x72, 0x79,
0x70, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x1a, 0x2e, 0x6d, 0x65, 0x74, 0x61, 0x63, 0x72, 0x79, 0x70, 0x74, 0x2e, 0x76, 0x31,
0x2e, 0x53, 0x65, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x44, 0x5a,
0x42, 0x67, 0x69, 0x74, 0x2e, 0x77, 0x6e, 0x74, 0x72, 0x6d, 0x75, 0x74, 0x65, 0x2e, 0x64, 0x65,
0x76, 0x2f, 0x6b, 0x79, 0x6c, 0x65, 0x2f, 0x6d, 0x65, 0x74, 0x61, 0x63, 0x72, 0x79, 0x70, 0x74,
0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x6d, 0x65, 0x74, 0x61, 0x63, 0x72, 0x79, 0x70, 0x74, 0x2f, 0x76,
0x31, 0x3b, 0x6d, 0x65, 0x74, 0x61, 0x63, 0x72, 0x79, 0x70, 0x74, 0x76, 0x31, 0x62, 0x06, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var ( var (
file_system_proto_rawDescOnce sync.Once file_metacrypt_v1_system_proto_rawDescOnce sync.Once
file_system_proto_rawDescData []byte file_metacrypt_v1_system_proto_rawDescData []byte
) )
func file_system_proto_rawDescGZIP() []byte { func file_metacrypt_v1_system_proto_rawDescGZIP() []byte {
file_system_proto_rawDescOnce.Do(func() { file_metacrypt_v1_system_proto_rawDescOnce.Do(func() {
file_system_proto_rawDescData = file_system_proto_rawDesc file_metacrypt_v1_system_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_metacrypt_v1_system_proto_rawDesc), len(file_metacrypt_v1_system_proto_rawDesc)))
}) })
return file_system_proto_rawDescData return file_metacrypt_v1_system_proto_rawDescData
} }
var file_system_proto_msgTypes = make([]protoimpl.MessageInfo, 8) var file_metacrypt_v1_system_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
var file_system_proto_goTypes = []any{ var file_metacrypt_v1_system_proto_goTypes = []any{
(*StatusRequest)(nil), // 0 (*StatusRequest)(nil), // 0: metacrypt.v1.StatusRequest
(*StatusResponse)(nil), // 1 (*StatusResponse)(nil), // 1: metacrypt.v1.StatusResponse
(*InitRequest)(nil), // 2 (*InitRequest)(nil), // 2: metacrypt.v1.InitRequest
(*InitResponse)(nil), // 3 (*InitResponse)(nil), // 3: metacrypt.v1.InitResponse
(*UnsealRequest)(nil), // 4 (*UnsealRequest)(nil), // 4: metacrypt.v1.UnsealRequest
(*UnsealResponse)(nil), // 5 (*UnsealResponse)(nil), // 5: metacrypt.v1.UnsealResponse
(*SealRequest)(nil), // 6 (*SealRequest)(nil), // 6: metacrypt.v1.SealRequest
(*SealResponse)(nil), // 7 (*SealResponse)(nil), // 7: metacrypt.v1.SealResponse
} }
var file_system_proto_depIdxs = []int32{ var file_metacrypt_v1_system_proto_depIdxs = []int32{
0, // 0: metacrypt.v1.SystemService.Status:input_type -> metacrypt.v1.StatusRequest 0, // 0: metacrypt.v1.SystemService.Status:input_type -> metacrypt.v1.StatusRequest
2, // 1: metacrypt.v1.SystemService.Init:input_type -> metacrypt.v1.InitRequest 2, // 1: metacrypt.v1.SystemService.Init:input_type -> metacrypt.v1.InitRequest
4, // 2: metacrypt.v1.SystemService.Unseal:input_type -> metacrypt.v1.UnsealRequest 4, // 2: metacrypt.v1.SystemService.Unseal:input_type -> metacrypt.v1.UnsealRequest
@@ -351,31 +421,26 @@ var file_system_proto_depIdxs = []int32{
0, // [0:0] is the sub-list for field type_name 0, // [0:0] is the sub-list for field type_name
} }
func init() { file_system_proto_init() } func init() { file_metacrypt_v1_system_proto_init() }
func file_metacrypt_v1_system_proto_init() {
func file_system_proto_init() { if File_metacrypt_v1_system_proto != nil {
if File_system_proto != nil {
return return
} }
type x struct{} type x struct{}
out := protoimpl.TypeBuilder{ out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{ File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_system_proto_rawDesc, RawDescriptor: unsafe.Slice(unsafe.StringData(file_metacrypt_v1_system_proto_rawDesc), len(file_metacrypt_v1_system_proto_rawDesc)),
NumEnums: 0, NumEnums: 0,
NumMessages: 8, NumMessages: 8,
NumExtensions: 0, NumExtensions: 0,
NumServices: 1, NumServices: 1,
}, },
GoTypes: file_system_proto_goTypes, GoTypes: file_metacrypt_v1_system_proto_goTypes,
DependencyIndexes: file_system_proto_depIdxs, DependencyIndexes: file_metacrypt_v1_system_proto_depIdxs,
MessageInfos: file_system_proto_msgTypes, MessageInfos: file_metacrypt_v1_system_proto_msgTypes,
}.Build() }.Build()
File_system_proto = out.File File_metacrypt_v1_system_proto = out.File
file_system_proto_rawDescData = nil file_metacrypt_v1_system_proto_goTypes = nil
file_system_proto_goTypes = nil file_metacrypt_v1_system_proto_depIdxs = nil
file_system_proto_depIdxs = nil
} }
// File_system_proto is the protoreflect.FileDescriptor for proto/metacrypt/v1/system.proto.
var File_system_proto protoreflect.FileDescriptor

View File

@@ -1,17 +1,33 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT. // Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// source: proto/metacrypt/v1/system.proto // versions:
// - protoc-gen-go-grpc v1.6.1
// - protoc v3.20.3
// source: metacrypt/v1/system.proto
package metacryptv1 package metacryptv1
import ( import (
context "context" context "context"
grpc "google.golang.org/grpc" grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes" codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status" status "google.golang.org/grpc/status"
) )
// SystemServiceClient is the client API for SystemService. // 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.v1.SystemService/Status"
SystemService_Init_FullMethodName = "/metacrypt.v1.SystemService/Init"
SystemService_Unseal_FullMethodName = "/metacrypt.v1.SystemService/Unseal"
SystemService_Seal_FullMethodName = "/metacrypt.v1.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 { type SystemServiceClient interface {
Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (*StatusResponse, error) Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (*StatusResponse, error)
Init(ctx context.Context, in *InitRequest, opts ...grpc.CallOption) (*InitResponse, error) Init(ctx context.Context, in *InitRequest, opts ...grpc.CallOption) (*InitResponse, error)
@@ -67,7 +83,9 @@ func (c *systemServiceClient) Seal(ctx context.Context, in *SealRequest, opts ..
return out, nil return out, nil
} }
// SystemServiceServer is the server API for SystemService. // SystemServiceServer is the server API for SystemService service.
// All implementations must embed UnimplementedSystemServiceServer
// for forward compatibility.
type SystemServiceServer interface { type SystemServiceServer interface {
Status(context.Context, *StatusRequest) (*StatusResponse, error) Status(context.Context, *StatusRequest) (*StatusResponse, error)
Init(context.Context, *InitRequest) (*InitResponse, error) Init(context.Context, *InitRequest) (*InitResponse, error)
@@ -76,36 +94,43 @@ type SystemServiceServer interface {
mustEmbedUnimplementedSystemServiceServer() mustEmbedUnimplementedSystemServiceServer()
} }
// UnimplementedSystemServiceServer must be embedded to have forward-compatible implementations. // 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{} type UnimplementedSystemServiceServer struct{}
func (UnimplementedSystemServiceServer) Status(context.Context, *StatusRequest) (*StatusResponse, error) { func (UnimplementedSystemServiceServer) Status(context.Context, *StatusRequest) (*StatusResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Status not implemented") return nil, status.Error(codes.Unimplemented, "method Status not implemented")
} }
func (UnimplementedSystemServiceServer) Init(context.Context, *InitRequest) (*InitResponse, error) { func (UnimplementedSystemServiceServer) Init(context.Context, *InitRequest) (*InitResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Init not implemented") return nil, status.Error(codes.Unimplemented, "method Init not implemented")
} }
func (UnimplementedSystemServiceServer) Unseal(context.Context, *UnsealRequest) (*UnsealResponse, error) { func (UnimplementedSystemServiceServer) Unseal(context.Context, *UnsealRequest) (*UnsealResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Unseal not implemented") return nil, status.Error(codes.Unimplemented, "method Unseal not implemented")
} }
func (UnimplementedSystemServiceServer) Seal(context.Context, *SealRequest) (*SealResponse, error) { func (UnimplementedSystemServiceServer) Seal(context.Context, *SealRequest) (*SealResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Seal not implemented") return nil, status.Error(codes.Unimplemented, "method Seal not implemented")
} }
func (UnimplementedSystemServiceServer) mustEmbedUnimplementedSystemServiceServer() {} func (UnimplementedSystemServiceServer) mustEmbedUnimplementedSystemServiceServer() {}
func (UnimplementedSystemServiceServer) testEmbeddedByValue() {}
// UnsafeSystemServiceServer may be embedded to opt out of forward compatibility. // 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 { type UnsafeSystemServiceServer interface {
mustEmbedUnimplementedSystemServiceServer() mustEmbedUnimplementedSystemServiceServer()
} }
const (
SystemService_Status_FullMethodName = "/metacrypt.v1.SystemService/Status"
SystemService_Init_FullMethodName = "/metacrypt.v1.SystemService/Init"
SystemService_Unseal_FullMethodName = "/metacrypt.v1.SystemService/Unseal"
SystemService_Seal_FullMethodName = "/metacrypt.v1.SystemService/Seal"
)
func RegisterSystemServiceServer(s grpc.ServiceRegistrar, srv SystemServiceServer) { 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) s.RegisterService(&SystemService_ServiceDesc, srv)
} }
@@ -182,6 +207,8 @@ func _SystemService_Seal_Handler(srv interface{}, ctx context.Context, dec func(
} }
// SystemService_ServiceDesc is the grpc.ServiceDesc for SystemService service. // 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{ var SystemService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "metacrypt.v1.SystemService", ServiceName: "metacrypt.v1.SystemService",
HandlerType: (*SystemServiceServer)(nil), HandlerType: (*SystemServiceServer)(nil),
@@ -204,5 +231,5 @@ var SystemService_ServiceDesc = grpc.ServiceDesc{
}, },
}, },
Streams: []grpc.StreamDesc{}, Streams: []grpc.StreamDesc{},
Metadata: "proto/metacrypt/v1/system.proto", Metadata: "metacrypt/v1/system.proto",
} }

8
go.mod
View File

@@ -15,8 +15,8 @@ require (
github.com/spf13/viper v1.21.0 github.com/spf13/viper v1.21.0
golang.org/x/crypto v0.49.0 golang.org/x/crypto v0.49.0
golang.org/x/term v0.41.0 golang.org/x/term v0.41.0
google.golang.org/grpc v1.71.1 google.golang.org/grpc v1.79.2
google.golang.org/protobuf v1.36.5 google.golang.org/protobuf v1.36.11
modernc.org/sqlite v1.46.1 modernc.org/sqlite v1.46.1
) )
@@ -37,10 +37,10 @@ require (
github.com/subosito/gotenv v1.6.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect
golang.org/x/net v0.40.0 // indirect golang.org/x/net v0.51.0 // indirect
golang.org/x/sys v0.42.0 // indirect golang.org/x/sys v0.42.0 // indirect
golang.org/x/text v0.35.0 // indirect golang.org/x/text v0.35.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect
modernc.org/libc v1.67.6 // indirect modernc.org/libc v1.67.6 // indirect
modernc.org/mathutil v1.7.1 // indirect modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.11.0 // indirect modernc.org/memory v1.11.0 // indirect

9
go.sum
View File

@@ -13,6 +13,7 @@ github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9L
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs= github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
@@ -65,6 +66,8 @@ golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70= golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70=
golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8= golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8=
golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w= golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w=
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo=
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -76,6 +79,12 @@ golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA= golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k= golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k=
golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0= golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0=
google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 h1:gRkg/vSppuSQoDjxyiGfN4Upv/h/DQmIR10ZU8dh4Ww=
google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
google.golang.org/grpc v1.79.2 h1:fRMD94s2tITpyJGtBBn7MkMseNpOZU8ZxgC3MMBaXRU=
google.golang.org/grpc v1.79.2/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@@ -11,6 +11,7 @@ import (
// Config is the top-level configuration for Metacrypt. // Config is the top-level configuration for Metacrypt.
type Config struct { type Config struct {
Server ServerConfig `toml:"server"` Server ServerConfig `toml:"server"`
Web WebConfig `toml:"web"`
Database DatabaseConfig `toml:"database"` Database DatabaseConfig `toml:"database"`
MCIAS MCIASConfig `toml:"mcias"` MCIAS MCIASConfig `toml:"mcias"`
Seal SealConfig `toml:"seal"` Seal SealConfig `toml:"seal"`
@@ -26,6 +27,20 @@ type ServerConfig struct {
ExternalURL string `toml:"external_url"` // public base URL for ACME directory, e.g. "https://metacrypt.example.com" ExternalURL string `toml:"external_url"` // public base URL for ACME directory, e.g. "https://metacrypt.example.com"
} }
// WebConfig holds settings for the standalone web UI server (metacrypt-web).
type WebConfig struct {
// ListenAddr is the address the web server listens on (default: 127.0.0.1:8080).
ListenAddr string `toml:"listen_addr"`
// VaultGRPC is the gRPC address of the vault server (e.g. "127.0.0.1:9443").
VaultGRPC string `toml:"vault_grpc"`
// VaultCACert is the path to the CA certificate used to verify the vault's TLS cert.
VaultCACert string `toml:"vault_ca_cert"`
// TLSCert and TLSKey are optional. If empty, the web server uses plain HTTP
// (suitable for deployment behind a TLS-terminating reverse proxy).
TLSCert string `toml:"tls_cert"`
TLSKey string `toml:"tls_key"`
}
// DatabaseConfig holds SQLite database settings. // DatabaseConfig holds SQLite database settings.
type DatabaseConfig struct { type DatabaseConfig struct {
Path string `toml:"path"` Path string `toml:"path"`
@@ -98,5 +113,10 @@ func (c *Config) Validate() error {
c.Log.Level = "info" c.Log.Level = "info"
} }
// Apply defaults for web server.
if c.Web.ListenAddr == "" {
c.Web.ListenAddr = "127.0.0.1:8080"
}
return nil return nil
} }

130
internal/grpcserver/acme.go Normal file
View File

@@ -0,0 +1,130 @@
package grpcserver
import (
"context"
"encoding/json"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
pb "git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v1"
internacme "git.wntrmute.dev/kyle/metacrypt/internal/acme"
"git.wntrmute.dev/kyle/metacrypt/internal/engine"
)
type acmeServer struct {
pb.UnimplementedACMEServiceServer
s *GRPCServer
}
func (as *acmeServer) CreateEAB(ctx context.Context, req *pb.CreateEABRequest) (*pb.CreateEABResponse, error) {
ti := tokenInfoFromContext(ctx)
h, err := as.getOrCreateHandler(req.Mount)
if err != nil {
return nil, status.Error(codes.NotFound, "mount not found")
}
cred, err := h.CreateEAB(ctx, ti.Username)
if err != nil {
as.s.logger.Error("grpc: acme create EAB", "error", err)
return nil, status.Error(codes.Internal, "failed to create EAB credentials")
}
return &pb.CreateEABResponse{Kid: cred.KID, HmacKey: cred.HMACKey}, nil
}
func (as *acmeServer) SetConfig(ctx context.Context, req *pb.SetACMEConfigRequest) (*pb.SetACMEConfigResponse, error) {
if req.DefaultIssuer == "" {
return nil, status.Error(codes.InvalidArgument, "default_issuer is required")
}
// Verify mount exists.
if _, err := as.getOrCreateHandler(req.Mount); err != nil {
return nil, status.Error(codes.NotFound, "mount not found")
}
cfg := &internacme.ACMEConfig{DefaultIssuer: req.DefaultIssuer}
data, _ := json.Marshal(cfg)
barrierPath := "acme/" + req.Mount + "/config.json"
if err := as.s.sealMgr.Barrier().Put(ctx, barrierPath, data); err != nil {
as.s.logger.Error("grpc: acme set config", "error", err)
return nil, status.Error(codes.Internal, "failed to save config")
}
return &pb.SetACMEConfigResponse{Ok: true}, nil
}
func (as *acmeServer) ListAccounts(ctx context.Context, req *pb.ListACMEAccountsRequest) (*pb.ListACMEAccountsResponse, error) {
h, err := as.getOrCreateHandler(req.Mount)
if err != nil {
return nil, status.Error(codes.NotFound, "mount not found")
}
accounts, err := h.ListAccounts(ctx)
if err != nil {
as.s.logger.Error("grpc: acme list accounts", "error", err)
return nil, status.Error(codes.Internal, "internal error")
}
pbAccounts := make([]*pb.ACMEAccount, 0, len(accounts))
for _, a := range accounts {
contacts := make([]string, len(a.Contact))
copy(contacts, a.Contact)
pbAccounts = append(pbAccounts, &pb.ACMEAccount{
Id: a.ID,
Status: a.Status,
Contact: contacts,
MciasUsername: a.MCIASUsername,
CreatedAt: a.CreatedAt.String(),
})
}
return &pb.ListACMEAccountsResponse{Accounts: pbAccounts}, nil
}
func (as *acmeServer) ListOrders(ctx context.Context, req *pb.ListACMEOrdersRequest) (*pb.ListACMEOrdersResponse, error) {
h, err := as.getOrCreateHandler(req.Mount)
if err != nil {
return nil, status.Error(codes.NotFound, "mount not found")
}
orders, err := h.ListOrders(ctx)
if err != nil {
as.s.logger.Error("grpc: acme list orders", "error", err)
return nil, status.Error(codes.Internal, "internal error")
}
pbOrders := make([]*pb.ACMEOrder, 0, len(orders))
for _, o := range orders {
identifiers := make([]string, 0, len(o.Identifiers))
for _, id := range o.Identifiers {
identifiers = append(identifiers, id.Type+":"+id.Value)
}
pbOrders = append(pbOrders, &pb.ACMEOrder{
Id: o.ID,
AccountId: o.AccountID,
Status: o.Status,
Identifiers: identifiers,
CreatedAt: o.CreatedAt.String(),
ExpiresAt: o.ExpiresAt.String(),
})
}
return &pb.ListACMEOrdersResponse{Orders: pbOrders}, nil
}
func (as *acmeServer) getOrCreateHandler(mountName string) (*internacme.Handler, error) {
as.s.mu.Lock()
defer as.s.mu.Unlock()
// Verify mount is a CA engine.
mount, err := as.s.engines.GetMount(mountName)
if err != nil {
return nil, err
}
if mount.Type != engine.EngineTypeCA {
return nil, engine.ErrMountNotFound
}
// Check handler cache on GRPCServer.
if h, ok := as.s.acmeHandlers[mountName]; ok {
return h, nil
}
baseURL := as.s.cfg.Server.ExternalURL
if baseURL == "" {
baseURL = "https://" + as.s.cfg.Server.ListenAddr
}
h := internacme.NewHandler(mountName, as.s.sealMgr.Barrier(), as.s.engines, baseURL, as.s.logger)
as.s.acmeHandlers[mountName] = h
return h, nil
}

View File

@@ -0,0 +1,56 @@
package grpcserver
import (
"context"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
mcias "git.wntrmute.dev/kyle/mcias/clients/go"
pb "git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v1"
)
type authServer struct {
pb.UnimplementedAuthServiceServer
s *GRPCServer
}
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)
if err != nil {
return nil, status.Error(codes.Unauthenticated, "invalid credentials")
}
return &pb.LoginResponse{Token: token, ExpiresAt: expiresAt}, nil
}
func (as *authServer) Logout(ctx context.Context, _ *pb.LogoutRequest) (*pb.LogoutResponse, error) {
token := extractToken(ctx)
client, err := mcias.New(as.s.cfg.MCIAS.ServerURL, mcias.Options{
CACertPath: as.s.cfg.MCIAS.CACert,
Token: token,
})
if err == nil {
as.s.auth.Logout(client)
}
return &pb.LogoutResponse{}, nil
}
func (as *authServer) TokenInfo(ctx context.Context, _ *pb.TokenInfoRequest) (*pb.TokenInfoResponse, error) {
ti := tokenInfoFromContext(ctx)
if ti == nil {
// Shouldn't happen — authInterceptor runs first — but guard anyway.
token := extractToken(ctx)
var err error
ti, err = as.s.auth.ValidateToken(token)
if err != nil {
return nil, status.Error(codes.Unauthenticated, "invalid token")
}
}
return &pb.TokenInfoResponse{
Username: ti.Username,
Roles: ti.Roles,
IsAdmin: ti.IsAdmin,
}, nil
}

View File

@@ -0,0 +1,112 @@
package grpcserver
import (
"context"
"errors"
"strings"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/structpb"
pb "git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v1"
"git.wntrmute.dev/kyle/metacrypt/internal/engine"
)
type engineServer struct {
pb.UnimplementedEngineServiceServer
s *GRPCServer
}
func (es *engineServer) Mount(ctx context.Context, req *pb.MountRequest) (*pb.MountResponse, error) {
if req.Name == "" || req.Type == "" {
return nil, status.Error(codes.InvalidArgument, "name and type are required")
}
var config map[string]interface{}
if req.Config != nil {
config = req.Config.AsMap()
}
if err := es.s.engines.Mount(ctx, req.Name, engine.EngineType(req.Type), config); err != nil {
es.s.logger.Error("grpc: mount engine", "name", req.Name, "type", req.Type, "error", err)
switch {
case errors.Is(err, engine.ErrMountExists):
return nil, status.Error(codes.AlreadyExists, err.Error())
case errors.Is(err, engine.ErrUnknownType):
return nil, status.Error(codes.InvalidArgument, err.Error())
default:
return nil, status.Error(codes.Internal, err.Error())
}
}
return &pb.MountResponse{}, nil
}
func (es *engineServer) Unmount(ctx context.Context, req *pb.UnmountRequest) (*pb.UnmountResponse, error) {
if req.Name == "" {
return nil, status.Error(codes.InvalidArgument, "name is required")
}
if err := es.s.engines.Unmount(ctx, req.Name); err != nil {
if errors.Is(err, engine.ErrMountNotFound) {
return nil, status.Error(codes.NotFound, err.Error())
}
return nil, status.Error(codes.Internal, err.Error())
}
return &pb.UnmountResponse{}, nil
}
func (es *engineServer) ListMounts(_ context.Context, _ *pb.ListMountsRequest) (*pb.ListMountsResponse, error) {
mounts := es.s.engines.ListMounts()
pbMounts := make([]*pb.MountInfo, 0, len(mounts))
for _, m := range mounts {
pbMounts = append(pbMounts, &pb.MountInfo{
Name: m.Name,
Type: string(m.Type),
MountPath: m.MountPath,
})
}
return &pb.ListMountsResponse{Mounts: pbMounts}, nil
}
func (es *engineServer) Request(ctx context.Context, req *pb.EngineRequest) (*pb.EngineResponse, 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,
}
}
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
}
return nil, status.Error(st, err.Error())
}
pbData, err := structpb.NewStruct(resp.Data)
if err != nil {
return nil, status.Error(codes.Internal, "failed to encode response")
}
return &pb.EngineResponse{Data: pbData}, nil
}

View File

@@ -0,0 +1,107 @@
package grpcserver
import (
"context"
"strings"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
"git.wntrmute.dev/kyle/metacrypt/internal/auth"
"git.wntrmute.dev/kyle/metacrypt/internal/seal"
)
type contextKey int
const tokenInfoKey contextKey = iota
func tokenInfoFromContext(ctx context.Context) *auth.TokenInfo {
v, _ := ctx.Value(tokenInfoKey).(*auth.TokenInfo)
return v
}
// authInterceptor validates the Bearer token from gRPC metadata and injects
// *auth.TokenInfo into the context. The set of method full names that require
// auth is passed in; all others pass through without validation.
func authInterceptor(authenticator *auth.Authenticator, methods map[string]bool) grpc.UnaryServerInterceptor {
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
if !methods[info.FullMethod] {
return handler(ctx, req)
}
token := extractToken(ctx)
if token == "" {
return nil, status.Error(codes.Unauthenticated, "missing authorization token")
}
tokenInfo, err := authenticator.ValidateToken(token)
if err != nil {
return nil, status.Error(codes.Unauthenticated, "invalid token")
}
ctx = context.WithValue(ctx, tokenInfoKey, tokenInfo)
return handler(ctx, req)
}
}
// adminInterceptor requires IsAdmin on the token info for the listed methods.
// Must run after authInterceptor.
func adminInterceptor(methods map[string]bool) grpc.UnaryServerInterceptor {
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
if !methods[info.FullMethod] {
return handler(ctx, req)
}
ti := tokenInfoFromContext(ctx)
if ti == nil || !ti.IsAdmin {
return nil, status.Error(codes.PermissionDenied, "admin required")
}
return handler(ctx, req)
}
}
// sealInterceptor rejects calls with FailedPrecondition when the vault is
// sealed, for the listed methods.
func sealInterceptor(sealMgr *seal.Manager, methods map[string]bool) grpc.UnaryServerInterceptor {
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
if !methods[info.FullMethod] {
return handler(ctx, req)
}
if sealMgr.State() != seal.StateUnsealed {
return nil, status.Error(codes.FailedPrecondition, "vault is sealed")
}
return handler(ctx, req)
}
}
// chainInterceptors reduces a slice of interceptors into a single one.
func chainInterceptors(interceptors ...grpc.UnaryServerInterceptor) grpc.UnaryServerInterceptor {
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
chain := handler
for i := len(interceptors) - 1; i >= 0; i-- {
next := chain
ic := interceptors[i]
chain = func(ctx context.Context, req interface{}) (interface{}, error) {
return ic(ctx, req, info, next)
}
}
return chain(ctx, req)
}
}
func extractToken(ctx context.Context) string {
md, ok := metadata.FromIncomingContext(ctx)
if !ok {
return ""
}
vals := md.Get("authorization")
if len(vals) == 0 {
return ""
}
v := vals[0]
if strings.HasPrefix(v, "Bearer ") {
return strings.TrimPrefix(v, "Bearer ")
}
return v
}

View File

@@ -0,0 +1,81 @@
package grpcserver
import (
"context"
"errors"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
pb "git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v1"
"git.wntrmute.dev/kyle/metacrypt/internal/engine"
"git.wntrmute.dev/kyle/metacrypt/internal/engine/ca"
)
type pkiServer struct {
pb.UnimplementedPKIServiceServer
s *GRPCServer
}
func (ps *pkiServer) GetRootCert(_ context.Context, req *pb.GetRootCertRequest) (*pb.GetRootCertResponse, error) {
caEng, err := ps.getCAEngine(req.Mount)
if err != nil {
return nil, err
}
certPEM, err := caEng.GetRootCertPEM()
if err != nil {
return nil, status.Error(codes.Unavailable, "sealed")
}
return &pb.GetRootCertResponse{CertPem: certPEM}, nil
}
func (ps *pkiServer) GetChain(_ context.Context, req *pb.GetChainRequest) (*pb.GetChainResponse, error) {
if req.Issuer == "" {
return nil, status.Error(codes.InvalidArgument, "issuer is required")
}
caEng, err := ps.getCAEngine(req.Mount)
if err != nil {
return nil, err
}
chainPEM, err := caEng.GetChainPEM(req.Issuer)
if err != nil {
if errors.Is(err, ca.ErrIssuerNotFound) {
return nil, status.Error(codes.NotFound, "issuer not found")
}
return nil, status.Error(codes.Unavailable, "sealed")
}
return &pb.GetChainResponse{ChainPem: chainPEM}, nil
}
func (ps *pkiServer) GetIssuerCert(_ context.Context, req *pb.GetIssuerCertRequest) (*pb.GetIssuerCertResponse, error) {
if req.Issuer == "" {
return nil, status.Error(codes.InvalidArgument, "issuer is required")
}
caEng, err := ps.getCAEngine(req.Mount)
if err != nil {
return nil, err
}
certPEM, err := caEng.GetIssuerCertPEM(req.Issuer)
if err != nil {
if errors.Is(err, ca.ErrIssuerNotFound) {
return nil, status.Error(codes.NotFound, "issuer not found")
}
return nil, status.Error(codes.Unavailable, "sealed")
}
return &pb.GetIssuerCertResponse{CertPem: certPEM}, nil
}
func (ps *pkiServer) getCAEngine(mountName string) (*ca.CAEngine, error) {
mount, err := ps.s.engines.GetMount(mountName)
if err != nil {
return nil, status.Error(codes.NotFound, err.Error())
}
if mount.Type != engine.EngineTypeCA {
return nil, status.Error(codes.NotFound, "mount is not a CA engine")
}
caEng, ok := mount.Engine.(*ca.CAEngine)
if !ok {
return nil, status.Error(codes.NotFound, "mount is not a CA engine")
}
return caEng, nil
}

View File

@@ -0,0 +1,86 @@
package grpcserver
import (
"context"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
pb "git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v1"
"git.wntrmute.dev/kyle/metacrypt/internal/policy"
)
type policyServer struct {
pb.UnimplementedPolicyServiceServer
s *GRPCServer
}
func (ps *policyServer) CreatePolicy(ctx context.Context, req *pb.CreatePolicyRequest) (*pb.PolicyRule, error) {
if req.Rule == nil || req.Rule.Id == "" {
return nil, status.Error(codes.InvalidArgument, "rule.id is required")
}
rule := pbToRule(req.Rule)
if err := ps.s.policy.CreateRule(ctx, rule); err != nil {
ps.s.logger.Error("grpc: create policy", "error", err)
return nil, status.Error(codes.Internal, "internal error")
}
return ruleToPB(rule), nil
}
func (ps *policyServer) ListPolicies(ctx context.Context, _ *pb.ListPoliciesRequest) (*pb.ListPoliciesResponse, error) {
rules, err := ps.s.policy.ListRules(ctx)
if err != nil {
ps.s.logger.Error("grpc: list policies", "error", err)
return nil, status.Error(codes.Internal, "internal error")
}
pbRules := make([]*pb.PolicyRule, 0, len(rules))
for i := range rules {
pbRules = append(pbRules, ruleToPB(&rules[i]))
}
return &pb.ListPoliciesResponse{Rules: pbRules}, nil
}
func (ps *policyServer) GetPolicy(ctx context.Context, req *pb.GetPolicyRequest) (*pb.PolicyRule, error) {
if req.Id == "" {
return nil, status.Error(codes.InvalidArgument, "id is required")
}
rule, err := ps.s.policy.GetRule(ctx, req.Id)
if err != nil {
return nil, status.Error(codes.NotFound, "not found")
}
return ruleToPB(rule), nil
}
func (ps *policyServer) DeletePolicy(ctx context.Context, req *pb.DeletePolicyRequest) (*pb.DeletePolicyResponse, error) {
if req.Id == "" {
return nil, status.Error(codes.InvalidArgument, "id is required")
}
if err := ps.s.policy.DeleteRule(ctx, req.Id); err != nil {
return nil, status.Error(codes.NotFound, "not found")
}
return &pb.DeletePolicyResponse{}, nil
}
func pbToRule(r *pb.PolicyRule) *policy.Rule {
return &policy.Rule{
ID: r.Id,
Priority: int(r.Priority),
Effect: policy.Effect(r.Effect),
Usernames: r.Usernames,
Roles: r.Roles,
Resources: r.Resources,
Actions: r.Actions,
}
}
func ruleToPB(r *policy.Rule) *pb.PolicyRule {
return &pb.PolicyRule{
Id: r.ID,
Priority: int32(r.Priority),
Effect: string(r.Effect),
Usernames: r.Usernames,
Roles: r.Roles,
Resources: r.Resources,
Actions: r.Actions,
}
}

View File

@@ -0,0 +1,162 @@
// Package grpcserver implements the gRPC server for Metacrypt.
package grpcserver
import (
"crypto/tls"
"fmt"
"log/slog"
"net"
"sync"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
pb "git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v1"
internacme "git.wntrmute.dev/kyle/metacrypt/internal/acme"
"git.wntrmute.dev/kyle/metacrypt/internal/auth"
"git.wntrmute.dev/kyle/metacrypt/internal/config"
"git.wntrmute.dev/kyle/metacrypt/internal/engine"
"git.wntrmute.dev/kyle/metacrypt/internal/policy"
"git.wntrmute.dev/kyle/metacrypt/internal/seal"
)
// GRPCServer wraps the gRPC server and all service implementations.
type GRPCServer struct {
cfg *config.Config
sealMgr *seal.Manager
auth *auth.Authenticator
policy *policy.Engine
engines *engine.Registry
logger *slog.Logger
srv *grpc.Server
mu sync.Mutex
acmeHandlers map[string]*internacme.Handler
}
// New creates a new GRPCServer.
func New(cfg *config.Config, sealMgr *seal.Manager, authenticator *auth.Authenticator,
policyEngine *policy.Engine, engineRegistry *engine.Registry, logger *slog.Logger) *GRPCServer {
return &GRPCServer{
cfg: cfg,
sealMgr: sealMgr,
auth: authenticator,
policy: policyEngine,
engines: engineRegistry,
logger: logger,
acmeHandlers: make(map[string]*internacme.Handler),
}
}
// Start starts the gRPC server on cfg.Server.GRPCAddr.
func (s *GRPCServer) Start() error {
if s.cfg.Server.GRPCAddr == "" {
s.logger.Info("grpc_addr not configured, gRPC server disabled")
return nil
}
tlsCert, err := tls.LoadX509KeyPair(s.cfg.Server.TLSCert, s.cfg.Server.TLSKey)
if err != nil {
return fmt.Errorf("grpc: load TLS cert: %w", err)
}
tlsCfg := &tls.Config{
Certificates: []tls.Certificate{tlsCert},
MinVersion: tls.VersionTLS12,
}
creds := credentials.NewTLS(tlsCfg)
interceptor := chainInterceptors(
sealInterceptor(s.sealMgr, sealRequiredMethods()),
authInterceptor(s.auth, authRequiredMethods()),
adminInterceptor(adminRequiredMethods()),
)
s.srv = grpc.NewServer(
grpc.Creds(creds),
grpc.UnaryInterceptor(interceptor),
)
pb.RegisterSystemServiceServer(s.srv, &systemServer{s: s})
pb.RegisterAuthServiceServer(s.srv, &authServer{s: s})
pb.RegisterEngineServiceServer(s.srv, &engineServer{s: s})
pb.RegisterPKIServiceServer(s.srv, &pkiServer{s: s})
pb.RegisterPolicyServiceServer(s.srv, &policyServer{s: s})
pb.RegisterACMEServiceServer(s.srv, &acmeServer{s: s})
lis, err := net.Listen("tcp", s.cfg.Server.GRPCAddr)
if err != nil {
return fmt.Errorf("grpc: listen %s: %w", s.cfg.Server.GRPCAddr, err)
}
s.logger.Info("starting gRPC server", "addr", s.cfg.Server.GRPCAddr)
if err := s.srv.Serve(lis); err != nil {
return fmt.Errorf("grpc: serve: %w", err)
}
return nil
}
// Shutdown gracefully stops the gRPC server.
func (s *GRPCServer) Shutdown() {
if s.srv != nil {
s.srv.GracefulStop()
}
}
// sealRequiredMethods returns the set of RPC full names that require the vault
// to be unsealed.
func sealRequiredMethods() map[string]bool {
return map[string]bool{
"/metacrypt.v1.AuthService/Login": true,
"/metacrypt.v1.AuthService/Logout": true,
"/metacrypt.v1.AuthService/TokenInfo": true,
"/metacrypt.v1.EngineService/Mount": true,
"/metacrypt.v1.EngineService/Unmount": true,
"/metacrypt.v1.EngineService/ListMounts": true,
"/metacrypt.v1.EngineService/Request": true,
"/metacrypt.v1.PKIService/GetRootCert": true,
"/metacrypt.v1.PKIService/GetChain": true,
"/metacrypt.v1.PKIService/GetIssuerCert": true,
"/metacrypt.v1.PolicyService/CreatePolicy": true,
"/metacrypt.v1.PolicyService/ListPolicies": true,
"/metacrypt.v1.PolicyService/GetPolicy": true,
"/metacrypt.v1.PolicyService/DeletePolicy": true,
"/metacrypt.v1.ACMEService/CreateEAB": true,
"/metacrypt.v1.ACMEService/SetConfig": true,
"/metacrypt.v1.ACMEService/ListAccounts": true,
"/metacrypt.v1.ACMEService/ListOrders": true,
}
}
// authRequiredMethods returns the set of RPC full names that require a valid token.
func authRequiredMethods() map[string]bool {
return map[string]bool{
"/metacrypt.v1.AuthService/Logout": true,
"/metacrypt.v1.AuthService/TokenInfo": true,
"/metacrypt.v1.EngineService/Mount": true,
"/metacrypt.v1.EngineService/Unmount": true,
"/metacrypt.v1.EngineService/ListMounts": true,
"/metacrypt.v1.EngineService/Request": true,
"/metacrypt.v1.PolicyService/CreatePolicy": true,
"/metacrypt.v1.PolicyService/ListPolicies": true,
"/metacrypt.v1.PolicyService/GetPolicy": true,
"/metacrypt.v1.PolicyService/DeletePolicy": true,
"/metacrypt.v1.ACMEService/CreateEAB": true,
"/metacrypt.v1.ACMEService/SetConfig": true,
"/metacrypt.v1.ACMEService/ListAccounts": true,
"/metacrypt.v1.ACMEService/ListOrders": true,
}
}
// adminRequiredMethods returns the set of RPC full names that require admin.
func adminRequiredMethods() map[string]bool {
return map[string]bool{
"/metacrypt.v1.SystemService/Seal": true,
"/metacrypt.v1.EngineService/Mount": true,
"/metacrypt.v1.EngineService/Unmount": true,
"/metacrypt.v1.PolicyService/CreatePolicy": true,
"/metacrypt.v1.PolicyService/DeletePolicy": true,
"/metacrypt.v1.ACMEService/SetConfig": true,
"/metacrypt.v1.ACMEService/ListAccounts": true,
"/metacrypt.v1.ACMEService/ListOrders": true,
}
}

View File

@@ -0,0 +1,80 @@
package grpcserver
import (
"context"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
pb "git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v1"
"git.wntrmute.dev/kyle/metacrypt/internal/crypto"
"git.wntrmute.dev/kyle/metacrypt/internal/seal"
)
type systemServer struct {
pb.UnimplementedSystemServiceServer
s *GRPCServer
}
func (ss *systemServer) Status(_ context.Context, _ *pb.StatusRequest) (*pb.StatusResponse, error) {
return &pb.StatusResponse{State: ss.s.sealMgr.State().String()}, nil
}
func (ss *systemServer) Init(ctx context.Context, req *pb.InitRequest) (*pb.InitResponse, error) {
if req.Password == "" {
return nil, status.Error(codes.InvalidArgument, "password is required")
}
params := crypto.Argon2Params{
Time: ss.s.cfg.Seal.Argon2Time,
Memory: ss.s.cfg.Seal.Argon2Memory,
Threads: ss.s.cfg.Seal.Argon2Threads,
}
if err := ss.s.sealMgr.Initialize(ctx, []byte(req.Password), params); err != nil {
switch err {
case seal.ErrAlreadyInitialized:
return nil, status.Error(codes.AlreadyExists, "already initialized")
default:
ss.s.logger.Error("grpc: init failed", "error", err)
return nil, status.Error(codes.Internal, "initialization failed")
}
}
return &pb.InitResponse{State: ss.s.sealMgr.State().String()}, nil
}
func (ss *systemServer) Unseal(ctx context.Context, req *pb.UnsealRequest) (*pb.UnsealResponse, error) {
if err := ss.s.sealMgr.Unseal([]byte(req.Password)); err != nil {
switch err {
case seal.ErrNotInitialized:
return nil, status.Error(codes.FailedPrecondition, "not initialized")
case seal.ErrInvalidPassword:
return nil, status.Error(codes.Unauthenticated, "invalid password")
case seal.ErrRateLimited:
return nil, status.Error(codes.ResourceExhausted, "too many attempts, try again later")
case seal.ErrNotSealed:
return nil, status.Error(codes.FailedPrecondition, "already unsealed")
default:
ss.s.logger.Error("grpc: unseal failed", "error", err)
return nil, status.Error(codes.Internal, "unseal failed")
}
}
if err := ss.s.engines.UnsealAll(ctx); err != nil {
ss.s.logger.Error("grpc: engine unseal failed", "error", err)
return nil, status.Error(codes.Internal, "engine unseal failed")
}
return &pb.UnsealResponse{State: ss.s.sealMgr.State().String()}, nil
}
func (ss *systemServer) Seal(_ context.Context, _ *pb.SealRequest) (*pb.SealResponse, error) {
if err := ss.s.engines.SealAll(); err != nil {
ss.s.logger.Error("grpc: seal engines failed", "error", err)
}
if err := ss.s.sealMgr.Seal(); err != nil {
ss.s.logger.Error("grpc: seal failed", "error", err)
return nil, status.Error(codes.Internal, "seal failed")
}
ss.s.auth.ClearCache()
return &pb.SealResponse{State: ss.s.sealMgr.State().String()}, nil
}

View File

@@ -1,24 +1,16 @@
package server package server
import ( import (
"context"
"crypto/x509"
"encoding/json" "encoding/json"
"encoding/pem"
"errors" "errors"
"fmt"
"html/template"
"io" "io"
"net/http" "net/http"
"path/filepath"
"strings" "strings"
"time"
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
mcias "git.wntrmute.dev/kyle/mcias/clients/go" mcias "git.wntrmute.dev/kyle/mcias/clients/go"
"git.wntrmute.dev/kyle/metacrypt/internal/auth"
"git.wntrmute.dev/kyle/metacrypt/internal/crypto" "git.wntrmute.dev/kyle/metacrypt/internal/crypto"
"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"
@@ -27,25 +19,7 @@ import (
) )
func (s *Server) registerRoutes(r chi.Router) { func (s *Server) registerRoutes(r chi.Router) {
// Static files. // REST API routes — web UI served by metacrypt-web.
r.Handle("/static/*", http.StripPrefix("/static/", http.FileServer(http.Dir("web/static"))))
// Web UI routes.
r.Get("/", s.handleWebRoot)
r.HandleFunc("/init", s.handleWebInit)
r.HandleFunc("/unseal", s.handleWebUnseal)
r.HandleFunc("/login", s.handleWebLogin)
r.Get("/dashboard", s.requireAuthWeb(s.handleWebDashboard))
r.Post("/dashboard/mount-ca", s.requireAuthWeb(s.handleWebDashboardMountCA))
r.Route("/pki", func(r chi.Router) {
r.Get("/", s.requireAuthWeb(s.handleWebPKI))
r.Post("/import-root", s.requireAuthWeb(s.handleWebImportRoot))
r.Post("/create-issuer", s.requireAuthWeb(s.handleWebCreateIssuer))
r.Get("/{issuer}", s.requireAuthWeb(s.handleWebPKIIssuer))
})
// API routes.
r.Get("/v1/status", s.handleStatus) r.Get("/v1/status", s.handleStatus)
r.Post("/v1/init", s.handleInit) r.Post("/v1/init", s.handleInit)
r.Post("/v1/unseal", s.handleUnseal) r.Post("/v1/unseal", s.handleUnseal)
@@ -67,7 +41,8 @@ func (s *Server) registerRoutes(r chi.Router) {
r.HandleFunc("/v1/policy/rules", s.requireAuth(s.handlePolicyRules)) r.HandleFunc("/v1/policy/rules", s.requireAuth(s.handlePolicyRules))
r.HandleFunc("/v1/policy/rule", s.requireAuth(s.handlePolicyRule)) r.HandleFunc("/v1/policy/rule", s.requireAuth(s.handlePolicyRule))
s.registerACMERoutes(r)} s.registerACMERoutes(r)
}
// --- API Handlers --- // --- API Handlers ---
@@ -478,474 +453,6 @@ func (s *Server) getCAEngine(mountName string) (*ca.CAEngine, error) {
return caEng, nil return caEng, nil
} }
// findCAMount returns the name of the first CA engine mount.
func (s *Server) findCAMount() (string, error) {
for _, m := range s.engines.ListMounts() {
if m.Type == engine.EngineTypeCA {
return m.Name, nil
}
}
return "", errors.New("no CA engine mounted")
}
// --- Web Handlers ---
func (s *Server) handleWebRoot(w http.ResponseWriter, r *http.Request) {
state := s.seal.State()
switch state {
case seal.StateUninitialized:
http.Redirect(w, r, "/init", http.StatusFound)
case seal.StateSealed:
http.Redirect(w, r, "/unseal", http.StatusFound)
case seal.StateInitializing:
http.Redirect(w, r, "/init", http.StatusFound)
case seal.StateUnsealed:
http.Redirect(w, r, "/dashboard", http.StatusFound)
}
}
func (s *Server) handleWebInit(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
if s.seal.State() != seal.StateUninitialized {
http.Redirect(w, r, "/", http.StatusFound)
return
}
s.renderTemplate(w, "init.html", nil)
case http.MethodPost:
r.ParseForm()
password := r.FormValue("password")
if password == "" {
s.renderTemplate(w, "init.html", map[string]interface{}{"Error": "Password is required"})
return
}
params := crypto.Argon2Params{
Time: s.cfg.Seal.Argon2Time,
Memory: s.cfg.Seal.Argon2Memory,
Threads: s.cfg.Seal.Argon2Threads,
}
if err := s.seal.Initialize(r.Context(), []byte(password), params); err != nil {
s.renderTemplate(w, "init.html", map[string]interface{}{"Error": err.Error()})
return
}
http.Redirect(w, r, "/dashboard", http.StatusFound)
default:
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
}
}
func (s *Server) handleWebUnseal(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
state := s.seal.State()
if state == seal.StateUninitialized {
http.Redirect(w, r, "/init", http.StatusFound)
return
}
if state == seal.StateUnsealed {
http.Redirect(w, r, "/dashboard", http.StatusFound)
return
}
s.renderTemplate(w, "unseal.html", nil)
case http.MethodPost:
r.ParseForm()
password := r.FormValue("password")
if err := s.seal.Unseal([]byte(password)); err != nil {
msg := "Invalid password"
if err == seal.ErrRateLimited {
msg = "Too many attempts. Please wait 60 seconds."
}
s.renderTemplate(w, "unseal.html", map[string]interface{}{"Error": msg})
return
}
if err := s.engines.UnsealAll(r.Context()); err != nil {
s.logger.Error("engine unseal failed", "error", err)
s.renderTemplate(w, "unseal.html", map[string]interface{}{"Error": "Engine reload failed: " + err.Error()})
return
}
http.Redirect(w, r, "/dashboard", http.StatusFound)
default:
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
}
}
func (s *Server) handleWebLogin(w http.ResponseWriter, r *http.Request) {
if s.seal.State() != seal.StateUnsealed {
http.Redirect(w, r, "/", http.StatusFound)
return
}
switch r.Method {
case http.MethodGet:
s.renderTemplate(w, "login.html", nil)
case http.MethodPost:
r.ParseForm()
username := r.FormValue("username")
password := r.FormValue("password")
totpCode := r.FormValue("totp_code")
token, _, err := s.auth.Login(username, password, totpCode)
if err != nil {
s.renderTemplate(w, "login.html", map[string]interface{}{"Error": "Invalid credentials"})
return
}
http.SetCookie(w, &http.Cookie{
Name: "metacrypt_token",
Value: token,
Path: "/",
HttpOnly: true,
Secure: true,
SameSite: http.SameSiteStrictMode,
})
http.Redirect(w, r, "/dashboard", http.StatusFound)
default:
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
}
}
func (s *Server) handleWebDashboard(w http.ResponseWriter, r *http.Request) {
info := TokenInfoFromContext(r.Context())
mounts := s.engines.ListMounts()
s.renderTemplate(w, "dashboard.html", map[string]interface{}{
"Username": info.Username,
"IsAdmin": info.IsAdmin,
"Roles": info.Roles,
"Mounts": mounts,
"State": s.seal.State().String(),
"Version": s.version,
})
}
func (s *Server) handleWebDashboardMountCA(w http.ResponseWriter, r *http.Request) {
info := TokenInfoFromContext(r.Context())
if !info.IsAdmin {
http.Error(w, "forbidden", http.StatusForbidden)
return
}
if err := r.ParseMultipartForm(1 << 20); err != nil {
r.ParseForm()
}
mountName := r.FormValue("name")
if mountName == "" {
s.renderDashboardWithError(w, r, info, "Mount name is required")
return
}
config := map[string]interface{}{}
if org := r.FormValue("organization"); org != "" {
config["organization"] = org
}
// Optional root CA import.
var certPEM, keyPEM string
if f, _, err := r.FormFile("cert_file"); err == nil {
defer f.Close()
data, _ := io.ReadAll(io.LimitReader(f, 1<<20))
certPEM = string(data)
}
if f, _, err := r.FormFile("key_file"); err == nil {
defer f.Close()
data, _ := io.ReadAll(io.LimitReader(f, 1<<20))
keyPEM = string(data)
}
if certPEM != "" && keyPEM != "" {
config["root_cert_pem"] = certPEM
config["root_key_pem"] = keyPEM
}
if err := s.engines.Mount(r.Context(), mountName, engine.EngineTypeCA, config); err != nil {
s.renderDashboardWithError(w, r, info, err.Error())
return
}
http.Redirect(w, r, "/pki", http.StatusFound)
}
func (s *Server) renderDashboardWithError(w http.ResponseWriter, _ *http.Request, info *auth.TokenInfo, errMsg string) {
mounts := s.engines.ListMounts()
s.renderTemplate(w, "dashboard.html", map[string]interface{}{
"Username": info.Username,
"IsAdmin": info.IsAdmin,
"Roles": info.Roles,
"Mounts": mounts,
"State": s.seal.State().String(),
"MountError": errMsg,
})
}
func (s *Server) handleWebPKI(w http.ResponseWriter, r *http.Request) {
info := TokenInfoFromContext(r.Context())
mountName, err := s.findCAMount()
if err != nil {
http.Redirect(w, r, "/dashboard", http.StatusFound)
return
}
caEng, err := s.getCAEngine(mountName)
if err != nil {
http.Redirect(w, r, "/dashboard", http.StatusFound)
return
}
data := map[string]interface{}{
"Username": info.Username,
"IsAdmin": info.IsAdmin,
"MountName": mountName,
}
// Get root cert info.
rootPEM, err := caEng.GetRootCertPEM()
if err == nil && rootPEM != nil {
if cert, err := parsePEMCert(rootPEM); err == nil {
data["RootCN"] = cert.Subject.CommonName
data["RootOrg"] = strings.Join(cert.Subject.Organization, ", ")
data["RootNotBefore"] = cert.NotBefore.Format(time.RFC3339)
data["RootNotAfter"] = cert.NotAfter.Format(time.RFC3339)
data["RootExpired"] = time.Now().After(cert.NotAfter)
data["HasRoot"] = true
}
}
// Get issuers.
callerInfo := &engine.CallerInfo{
Username: info.Username,
Roles: info.Roles,
IsAdmin: info.IsAdmin,
}
resp, err := s.engines.HandleRequest(r.Context(), mountName, &engine.Request{
Operation: "list-issuers",
CallerInfo: callerInfo,
})
if err == nil {
data["Issuers"] = resp.Data["issuers"]
}
s.renderTemplate(w, "pki.html", data)
}
func (s *Server) handleWebImportRoot(w http.ResponseWriter, r *http.Request) {
info := TokenInfoFromContext(r.Context())
if !info.IsAdmin {
http.Error(w, "forbidden", http.StatusForbidden)
return
}
mountName, err := s.findCAMount()
if err != nil {
http.Error(w, "no CA engine mounted", http.StatusNotFound)
return
}
if err := r.ParseMultipartForm(1 << 20); err != nil {
r.ParseForm()
}
certPEM := r.FormValue("cert_pem")
keyPEM := r.FormValue("key_pem")
// Also support file uploads.
if certPEM == "" {
if f, _, err := r.FormFile("cert_file"); err == nil {
defer f.Close()
data, _ := io.ReadAll(io.LimitReader(f, 1<<20))
certPEM = string(data)
}
}
if keyPEM == "" {
if f, _, err := r.FormFile("key_file"); err == nil {
defer f.Close()
data, _ := io.ReadAll(io.LimitReader(f, 1<<20))
keyPEM = string(data)
}
}
if certPEM == "" || keyPEM == "" {
s.renderPKIWithError(w, r, mountName, info, "Certificate and private key are required")
return
}
callerInfo := &engine.CallerInfo{
Username: info.Username,
Roles: info.Roles,
IsAdmin: info.IsAdmin,
}
_, err = s.engines.HandleRequest(r.Context(), mountName, &engine.Request{
Operation: "import-root",
CallerInfo: callerInfo,
Data: map[string]interface{}{
"cert_pem": certPEM,
"key_pem": keyPEM,
},
})
if err != nil {
s.renderPKIWithError(w, r, mountName, info, err.Error())
return
}
http.Redirect(w, r, "/pki", http.StatusFound)
}
func (s *Server) handleWebCreateIssuer(w http.ResponseWriter, r *http.Request) {
info := TokenInfoFromContext(r.Context())
if !info.IsAdmin {
http.Error(w, "forbidden", http.StatusForbidden)
return
}
mountName, err := s.findCAMount()
if err != nil {
http.Error(w, "no CA engine mounted", http.StatusNotFound)
return
}
r.ParseForm()
name := r.FormValue("name")
if name == "" {
s.renderPKIWithError(w, r, mountName, info, "Issuer name is required")
return
}
data := map[string]interface{}{
"name": name,
}
if v := r.FormValue("expiry"); v != "" {
data["expiry"] = v
}
if v := r.FormValue("max_ttl"); v != "" {
data["max_ttl"] = v
}
if v := r.FormValue("key_algorithm"); v != "" {
data["key_algorithm"] = v
}
if v := r.FormValue("key_size"); v != "" {
// Parse as float64 to match JSON number convention used by the engine.
var size float64
if _, err := fmt.Sscanf(v, "%f", &size); err == nil {
data["key_size"] = size
}
}
callerInfo := &engine.CallerInfo{
Username: info.Username,
Roles: info.Roles,
IsAdmin: info.IsAdmin,
}
_, err = s.engines.HandleRequest(r.Context(), mountName, &engine.Request{
Operation: "create-issuer",
CallerInfo: callerInfo,
Data: data,
})
if err != nil {
s.renderPKIWithError(w, r, mountName, info, err.Error())
return
}
http.Redirect(w, r, "/pki", http.StatusFound)
}
func (s *Server) handleWebPKIIssuer(w http.ResponseWriter, r *http.Request) {
mountName, err := s.findCAMount()
if err != nil {
http.Error(w, "no CA engine mounted", http.StatusNotFound)
return
}
issuerName := chi.URLParam(r, "issuer")
caEng, err := s.getCAEngine(mountName)
if err != nil {
http.Error(w, err.Error(), http.StatusNotFound)
return
}
certPEM, err := caEng.GetIssuerCertPEM(issuerName)
if err != nil {
http.Error(w, "issuer not found", http.StatusNotFound)
return
}
w.Header().Set("Content-Type", "application/x-pem-file")
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s.pem", issuerName))
w.Write(certPEM)
}
func (s *Server) renderPKIWithError(w http.ResponseWriter, r *http.Request, mountName string, info *auth.TokenInfo, errMsg string) {
data := map[string]interface{}{
"Username": info.Username,
"IsAdmin": info.IsAdmin,
"MountName": mountName,
"Error": errMsg,
}
// Try to load existing root info.
mount, merr := s.engines.GetMount(mountName)
if merr == nil && mount.Type == engine.EngineTypeCA {
if caEng, ok := mount.Engine.(*ca.CAEngine); ok {
rootPEM, err := caEng.GetRootCertPEM()
if err == nil && rootPEM != nil {
if cert, err := parsePEMCert(rootPEM); err == nil {
data["RootCN"] = cert.Subject.CommonName
data["RootOrg"] = strings.Join(cert.Subject.Organization, ", ")
data["RootNotBefore"] = cert.NotBefore.Format(time.RFC3339)
data["RootNotAfter"] = cert.NotAfter.Format(time.RFC3339)
data["RootExpired"] = time.Now().After(cert.NotAfter)
data["HasRoot"] = true
}
}
}
}
s.renderTemplate(w, "pki.html", data)
}
func parsePEMCert(pemData []byte) (*x509.Certificate, error) {
block, _ := pem.Decode(pemData)
if block == nil {
return nil, errors.New("no PEM block found")
}
return x509.ParseCertificate(block.Bytes)
}
// requireAuthWeb redirects to login for web pages instead of returning 401.
func (s *Server) requireAuthWeb(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if s.seal.State() != seal.StateUnsealed {
http.Redirect(w, r, "/", http.StatusFound)
return
}
token := extractToken(r)
if token == "" {
http.Redirect(w, r, "/login", http.StatusFound)
return
}
info, err := s.auth.ValidateToken(token)
if err != nil {
http.Redirect(w, r, "/login", http.StatusFound)
return
}
ctx := r.Context()
ctx = context.WithValue(ctx, tokenInfoKey, info)
next(w, r.WithContext(ctx))
}
}
func (s *Server) renderTemplate(w http.ResponseWriter, name string, data interface{}) {
tmpl, err := template.ParseFiles(
filepath.Join("web", "templates", "layout.html"),
filepath.Join("web", "templates", name),
)
if err != nil {
s.logger.Error("parse template", "name", name, "error", err)
http.Error(w, "internal server error", http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "text/html; charset=utf-8")
if err := tmpl.ExecuteTemplate(w, "layout", data); err != nil {
s.logger.Error("execute template", "name", name, "error", err)
}
}
func writeJSON(w http.ResponseWriter, status int, v interface{}) { func writeJSON(w http.ResponseWriter, status int, v interface{}) {
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
w.WriteHeader(status) w.WriteHeader(status)

View File

@@ -151,18 +151,15 @@ func TestStatusMethodNotAllowed(t *testing.T) {
} }
} }
func TestRootRedirect(t *testing.T) { func TestRootNotFound(t *testing.T) {
_, _, mux := setupTestServer(t) _, _, mux := setupTestServer(t)
// The vault server no longer serves a web UI at /; that is handled by metacrypt-web.
req := httptest.NewRequest(http.MethodGet, "/", nil) req := httptest.NewRequest(http.MethodGet, "/", nil)
w := httptest.NewRecorder() w := httptest.NewRecorder()
mux.ServeHTTP(w, req) mux.ServeHTTP(w, req)
if w.Code != http.StatusFound { if w.Code != http.StatusNotFound {
t.Errorf("root redirect: got %d, want %d", w.Code, http.StatusFound) t.Errorf("root: got %d, want %d", w.Code, http.StatusNotFound)
}
loc := w.Header().Get("Location")
if loc != "/init" {
t.Errorf("redirect location: got %q, want /init", loc)
} }
} }

View File

@@ -0,0 +1,199 @@
package webserver
import (
"context"
"crypto/tls"
"crypto/x509"
"fmt"
"os"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/metadata"
pb "git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v1"
)
// VaultClient wraps the gRPC stubs for communicating with the vault.
type VaultClient struct {
conn *grpc.ClientConn
system pb.SystemServiceClient
auth pb.AuthServiceClient
engine pb.EngineServiceClient
pki pb.PKIServiceClient
}
// NewVaultClient dials the vault gRPC server and returns a client.
func NewVaultClient(addr, caCertPath string) (*VaultClient, error) {
tlsCfg := &tls.Config{MinVersion: tls.VersionTLS12}
if caCertPath != "" {
pemData, err := os.ReadFile(caCertPath)
if err != nil {
return nil, fmt.Errorf("webserver: read CA cert: %w", err)
}
pool := x509.NewCertPool()
if !pool.AppendCertsFromPEM(pemData) {
return nil, fmt.Errorf("webserver: parse CA cert")
}
tlsCfg.RootCAs = pool
}
conn, err := grpc.NewClient(addr, grpc.WithTransportCredentials(credentials.NewTLS(tlsCfg)))
if err != nil {
return nil, fmt.Errorf("webserver: dial vault: %w", err)
}
return &VaultClient{
conn: conn,
system: pb.NewSystemServiceClient(conn),
auth: pb.NewAuthServiceClient(conn),
engine: pb.NewEngineServiceClient(conn),
pki: pb.NewPKIServiceClient(conn),
}, nil
}
// Close closes the underlying connection.
func (c *VaultClient) Close() error {
return c.conn.Close()
}
// withToken returns a context with the Bearer token in outgoing metadata.
func withToken(ctx context.Context, token string) context.Context {
return metadata.AppendToOutgoingContext(ctx, "authorization", "Bearer "+token)
}
// Status returns the current vault state string (e.g. "unsealed").
func (c *VaultClient) Status(ctx context.Context) (string, error) {
resp, err := c.system.Status(ctx, &pb.StatusRequest{})
if err != nil {
return "", err
}
return resp.State, nil
}
// Init initializes the vault with the given password.
func (c *VaultClient) Init(ctx context.Context, password string) error {
_, err := c.system.Init(ctx, &pb.InitRequest{Password: password})
return err
}
// Unseal unseals the vault with the given password.
func (c *VaultClient) Unseal(ctx context.Context, password string) error {
_, err := c.system.Unseal(ctx, &pb.UnsealRequest{Password: password})
return err
}
// TokenInfo holds validated token details returned by the vault.
type TokenInfo struct {
Username string
Roles []string
IsAdmin bool
}
// Login authenticates against the vault and returns the session token.
func (c *VaultClient) Login(ctx context.Context, username, password, totpCode string) (string, error) {
resp, err := c.auth.Login(ctx, &pb.LoginRequest{
Username: username,
Password: password,
TotpCode: totpCode,
})
if err != nil {
return "", err
}
return resp.Token, nil
}
// ValidateToken validates a token against the vault and returns the token info.
func (c *VaultClient) ValidateToken(ctx context.Context, token string) (*TokenInfo, error) {
resp, err := c.auth.TokenInfo(withToken(ctx, token), &pb.TokenInfoRequest{})
if err != nil {
return nil, err
}
return &TokenInfo{
Username: resp.Username,
Roles: resp.Roles,
IsAdmin: resp.IsAdmin,
}, nil
}
// MountInfo holds metadata about an engine mount.
type MountInfo struct {
Name string
Type string
MountPath string
}
// ListMounts returns all engine mounts from the vault.
func (c *VaultClient) ListMounts(ctx context.Context, token string) ([]MountInfo, error) {
resp, err := c.engine.ListMounts(withToken(ctx, token), &pb.ListMountsRequest{})
if err != nil {
return nil, err
}
mounts := make([]MountInfo, 0, len(resp.Mounts))
for _, m := range resp.Mounts {
mounts = append(mounts, MountInfo{
Name: m.Name,
Type: m.Type,
MountPath: m.MountPath,
})
}
return mounts, nil
}
// Mount creates a new engine mount on the vault.
func (c *VaultClient) Mount(ctx context.Context, token, name, engineType string, config map[string]interface{}) error {
req := &pb.MountRequest{
Name: name,
Type: engineType,
}
if len(config) > 0 {
s, err := structFromMap(config)
if err != nil {
return fmt.Errorf("webserver: encode mount config: %w", err)
}
req.Config = s
}
_, err := c.engine.Mount(withToken(ctx, token), req)
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.EngineRequest{
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.Request(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.
func (c *VaultClient) GetRootCert(ctx context.Context, mount string) ([]byte, error) {
resp, err := c.pki.GetRootCert(ctx, &pb.GetRootCertRequest{Mount: mount})
if err != nil {
return nil, err
}
return resp.CertPem, nil
}
// GetIssuerCert returns a named issuer certificate PEM for the given mount.
func (c *VaultClient) GetIssuerCert(ctx context.Context, mount, issuer string) ([]byte, error) {
resp, err := c.pki.GetIssuerCert(ctx, &pb.GetIssuerCertRequest{Mount: mount, Issuer: issuer})
if err != nil {
return nil, err
}
return resp.CertPem, nil
}

View File

@@ -0,0 +1,430 @@
package webserver
import (
"fmt"
"io"
"net/http"
"strings"
"time"
"github.com/go-chi/chi/v5"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
func (ws *WebServer) registerRoutes(r chi.Router) {
r.Handle("/static/*", http.StripPrefix("/static/", http.FileServer(http.FS(ws.staticFS))))
r.Get("/", ws.handleRoot)
r.HandleFunc("/init", ws.handleInit)
r.HandleFunc("/unseal", ws.handleUnseal)
r.HandleFunc("/login", ws.handleLogin)
r.Get("/dashboard", ws.requireAuth(ws.handleDashboard))
r.Post("/dashboard/mount-ca", ws.requireAuth(ws.handleDashboardMountCA))
r.Route("/pki", func(r chi.Router) {
r.Get("/", ws.requireAuth(ws.handlePKI))
r.Post("/import-root", ws.requireAuth(ws.handleImportRoot))
r.Post("/create-issuer", ws.requireAuth(ws.handleCreateIssuer))
r.Get("/{issuer}", ws.requireAuth(ws.handlePKIIssuer))
})
}
// requireAuth validates the token cookie against the vault and injects TokenInfo.
func (ws *WebServer) requireAuth(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
state, err := ws.vault.Status(r.Context())
if err != nil || state != "unsealed" {
http.Redirect(w, r, "/", http.StatusFound)
return
}
token := extractCookie(r)
if token == "" {
http.Redirect(w, r, "/login", http.StatusFound)
return
}
info, err := ws.vault.ValidateToken(r.Context(), token)
if err != nil {
http.Redirect(w, r, "/login", http.StatusFound)
return
}
r = r.WithContext(withTokenInfo(r.Context(), info))
next(w, r)
}
}
func (ws *WebServer) handleRoot(w http.ResponseWriter, r *http.Request) {
state, err := ws.vault.Status(r.Context())
if err != nil {
ws.renderTemplate(w, "unseal.html", map[string]interface{}{"Error": "Cannot reach vault"})
return
}
switch state {
case "uninitialized", "initializing":
http.Redirect(w, r, "/init", http.StatusFound)
case "sealed":
http.Redirect(w, r, "/unseal", http.StatusFound)
case "unsealed":
http.Redirect(w, r, "/dashboard", http.StatusFound)
default:
http.Redirect(w, r, "/unseal", http.StatusFound)
}
}
func (ws *WebServer) handleInit(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
state, _ := ws.vault.Status(r.Context())
if state != "uninitialized" && state != "" {
http.Redirect(w, r, "/", http.StatusFound)
return
}
ws.renderTemplate(w, "init.html", nil)
case http.MethodPost:
r.ParseForm()
password := r.FormValue("password")
if password == "" {
ws.renderTemplate(w, "init.html", map[string]interface{}{"Error": "Password is required"})
return
}
if err := ws.vault.Init(r.Context(), password); err != nil {
ws.renderTemplate(w, "init.html", map[string]interface{}{"Error": grpcMessage(err)})
return
}
http.Redirect(w, r, "/dashboard", http.StatusFound)
default:
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
}
}
func (ws *WebServer) handleUnseal(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
state, _ := ws.vault.Status(r.Context())
if state == "uninitialized" {
http.Redirect(w, r, "/init", http.StatusFound)
return
}
if state == "unsealed" {
http.Redirect(w, r, "/dashboard", http.StatusFound)
return
}
ws.renderTemplate(w, "unseal.html", nil)
case http.MethodPost:
r.ParseForm()
password := r.FormValue("password")
if err := ws.vault.Unseal(r.Context(), password); err != nil {
msg := "Invalid password"
if st, ok := status.FromError(err); ok && st.Code() == codes.ResourceExhausted {
msg = "Too many attempts. Please wait 60 seconds."
}
ws.renderTemplate(w, "unseal.html", map[string]interface{}{"Error": msg})
return
}
http.Redirect(w, r, "/dashboard", http.StatusFound)
default:
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
}
}
func (ws *WebServer) handleLogin(w http.ResponseWriter, r *http.Request) {
state, _ := ws.vault.Status(r.Context())
if state != "unsealed" {
http.Redirect(w, r, "/", http.StatusFound)
return
}
switch r.Method {
case http.MethodGet:
ws.renderTemplate(w, "login.html", nil)
case http.MethodPost:
r.ParseForm()
token, err := ws.vault.Login(r.Context(),
r.FormValue("username"),
r.FormValue("password"),
r.FormValue("totp_code"),
)
if err != nil {
ws.renderTemplate(w, "login.html", map[string]interface{}{"Error": "Invalid credentials"})
return
}
http.SetCookie(w, &http.Cookie{
Name: "metacrypt_token",
Value: token,
Path: "/",
HttpOnly: true,
Secure: true,
SameSite: http.SameSiteStrictMode,
})
http.Redirect(w, r, "/dashboard", http.StatusFound)
default:
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
}
}
func (ws *WebServer) handleDashboard(w http.ResponseWriter, r *http.Request) {
info := tokenInfoFromContext(r.Context())
token := extractCookie(r)
mounts, _ := ws.vault.ListMounts(r.Context(), token)
state, _ := ws.vault.Status(r.Context())
ws.renderTemplate(w, "dashboard.html", map[string]interface{}{
"Username": info.Username,
"IsAdmin": info.IsAdmin,
"Roles": info.Roles,
"Mounts": mounts,
"State": state,
})
}
func (ws *WebServer) handleDashboardMountCA(w http.ResponseWriter, r *http.Request) {
info := tokenInfoFromContext(r.Context())
if !info.IsAdmin {
http.Error(w, "forbidden", http.StatusForbidden)
return
}
if err := r.ParseMultipartForm(1 << 20); err != nil {
r.ParseForm()
}
mountName := r.FormValue("name")
if mountName == "" {
ws.renderDashboardWithError(w, r, info, "Mount name is required")
return
}
cfg := map[string]interface{}{}
if org := r.FormValue("organization"); org != "" {
cfg["organization"] = org
}
var certPEM, keyPEM string
if f, _, err := r.FormFile("cert_file"); err == nil {
defer f.Close()
data, _ := io.ReadAll(io.LimitReader(f, 1<<20))
certPEM = string(data)
}
if f, _, err := r.FormFile("key_file"); err == nil {
defer f.Close()
data, _ := io.ReadAll(io.LimitReader(f, 1<<20))
keyPEM = string(data)
}
if certPEM != "" && keyPEM != "" {
cfg["root_cert_pem"] = certPEM
cfg["root_key_pem"] = keyPEM
}
token := extractCookie(r)
if err := ws.vault.Mount(r.Context(), token, mountName, "ca", cfg); err != nil {
ws.renderDashboardWithError(w, r, info, grpcMessage(err))
return
}
http.Redirect(w, r, "/pki", http.StatusFound)
}
func (ws *WebServer) renderDashboardWithError(w http.ResponseWriter, r *http.Request, info *TokenInfo, errMsg string) {
token := extractCookie(r)
mounts, _ := ws.vault.ListMounts(r.Context(), token)
state, _ := ws.vault.Status(r.Context())
ws.renderTemplate(w, "dashboard.html", map[string]interface{}{
"Username": info.Username,
"IsAdmin": info.IsAdmin,
"Roles": info.Roles,
"Mounts": mounts,
"State": state,
"MountError": errMsg,
})
}
func (ws *WebServer) handlePKI(w http.ResponseWriter, r *http.Request) {
info := tokenInfoFromContext(r.Context())
token := extractCookie(r)
mountName, err := ws.findCAMount(r, token)
if err != nil {
http.Redirect(w, r, "/dashboard", http.StatusFound)
return
}
data := map[string]interface{}{
"Username": info.Username,
"IsAdmin": info.IsAdmin,
"MountName": mountName,
}
if rootPEM, err := ws.vault.GetRootCert(r.Context(), mountName); err == nil && len(rootPEM) > 0 {
if cert, err := parsePEMCert(rootPEM); err == nil {
data["RootCN"] = cert.Subject.CommonName
data["RootOrg"] = strings.Join(cert.Subject.Organization, ", ")
data["RootNotBefore"] = cert.NotBefore.Format(time.RFC3339)
data["RootNotAfter"] = cert.NotAfter.Format(time.RFC3339)
data["RootExpired"] = time.Now().After(cert.NotAfter)
data["HasRoot"] = true
}
}
if resp, err := ws.vault.EngineRequest(r.Context(), token, mountName, "list-issuers", nil); err == nil {
data["Issuers"] = resp["issuers"]
}
ws.renderTemplate(w, "pki.html", data)
}
func (ws *WebServer) handleImportRoot(w http.ResponseWriter, r *http.Request) {
info := tokenInfoFromContext(r.Context())
if !info.IsAdmin {
http.Error(w, "forbidden", http.StatusForbidden)
return
}
token := extractCookie(r)
mountName, err := ws.findCAMount(r, token)
if err != nil {
http.Error(w, "no CA engine mounted", http.StatusNotFound)
return
}
if err := r.ParseMultipartForm(1 << 20); err != nil {
r.ParseForm()
}
certPEM := r.FormValue("cert_pem")
keyPEM := r.FormValue("key_pem")
if certPEM == "" {
if f, _, err := r.FormFile("cert_file"); err == nil {
defer f.Close()
data, _ := io.ReadAll(io.LimitReader(f, 1<<20))
certPEM = string(data)
}
}
if keyPEM == "" {
if f, _, err := r.FormFile("key_file"); err == nil {
defer f.Close()
data, _ := io.ReadAll(io.LimitReader(f, 1<<20))
keyPEM = string(data)
}
}
if certPEM == "" || keyPEM == "" {
ws.renderPKIWithError(w, r, mountName, info, "Certificate and private key are required")
return
}
_, err = ws.vault.EngineRequest(r.Context(), token, mountName, "import-root", map[string]interface{}{
"cert_pem": certPEM,
"key_pem": keyPEM,
})
if err != nil {
ws.renderPKIWithError(w, r, mountName, info, grpcMessage(err))
return
}
http.Redirect(w, r, "/pki", http.StatusFound)
}
func (ws *WebServer) handleCreateIssuer(w http.ResponseWriter, r *http.Request) {
info := tokenInfoFromContext(r.Context())
if !info.IsAdmin {
http.Error(w, "forbidden", http.StatusForbidden)
return
}
token := extractCookie(r)
mountName, err := ws.findCAMount(r, token)
if err != nil {
http.Error(w, "no CA engine mounted", http.StatusNotFound)
return
}
r.ParseForm()
name := r.FormValue("name")
if name == "" {
ws.renderPKIWithError(w, r, mountName, info, "Issuer name is required")
return
}
reqData := map[string]interface{}{"name": name}
if v := r.FormValue("expiry"); v != "" {
reqData["expiry"] = v
}
if v := r.FormValue("max_ttl"); v != "" {
reqData["max_ttl"] = v
}
if v := r.FormValue("key_algorithm"); v != "" {
reqData["key_algorithm"] = v
}
if v := r.FormValue("key_size"); v != "" {
var size float64
if _, err := fmt.Sscanf(v, "%f", &size); err == nil {
reqData["key_size"] = size
}
}
_, err = ws.vault.EngineRequest(r.Context(), token, mountName, "create-issuer", reqData)
if err != nil {
ws.renderPKIWithError(w, r, mountName, info, grpcMessage(err))
return
}
http.Redirect(w, r, "/pki", http.StatusFound)
}
func (ws *WebServer) handlePKIIssuer(w http.ResponseWriter, r *http.Request) {
token := extractCookie(r)
mountName, err := ws.findCAMount(r, token)
if err != nil {
http.Error(w, "no CA engine mounted", http.StatusNotFound)
return
}
issuerName := chi.URLParam(r, "issuer")
certPEM, err := ws.vault.GetIssuerCert(r.Context(), mountName, issuerName)
if err != nil {
http.Error(w, "issuer not found", http.StatusNotFound)
return
}
w.Header().Set("Content-Type", "application/x-pem-file")
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s.pem", issuerName))
w.Write(certPEM)
}
func (ws *WebServer) renderPKIWithError(w http.ResponseWriter, r *http.Request, mountName string, info *TokenInfo, errMsg string) {
data := map[string]interface{}{
"Username": info.Username,
"IsAdmin": info.IsAdmin,
"MountName": mountName,
"Error": errMsg,
}
if rootPEM, err := ws.vault.GetRootCert(r.Context(), mountName); err == nil && len(rootPEM) > 0 {
if cert, err := parsePEMCert(rootPEM); err == nil {
data["RootCN"] = cert.Subject.CommonName
data["RootOrg"] = strings.Join(cert.Subject.Organization, ", ")
data["RootNotBefore"] = cert.NotBefore.Format(time.RFC3339)
data["RootNotAfter"] = cert.NotAfter.Format(time.RFC3339)
data["RootExpired"] = time.Now().After(cert.NotAfter)
data["HasRoot"] = true
}
}
ws.renderTemplate(w, "pki.html", data)
}
func (ws *WebServer) findCAMount(r *http.Request, token string) (string, error) {
mounts, err := ws.vault.ListMounts(r.Context(), token)
if err != nil {
return "", err
}
for _, m := range mounts {
if m.Type == "ca" {
return m.Name, nil
}
}
return "", fmt.Errorf("no CA engine mounted")
}
// grpcMessage extracts a human-readable message from a gRPC error.
func grpcMessage(err error) string {
if st, ok := status.FromError(err); ok {
return st.Message()
}
return err.Error()
}

View File

@@ -0,0 +1,112 @@
// Package webserver implements the standalone web UI server for Metacrypt.
// It communicates with the vault over gRPC and renders server-side HTML.
package webserver
import (
"context"
"crypto/tls"
"fmt"
"html/template"
"io/fs"
"log/slog"
"net/http"
"time"
"github.com/go-chi/chi/v5"
webui "git.wntrmute.dev/kyle/metacrypt/web"
"git.wntrmute.dev/kyle/metacrypt/internal/config"
)
// WebServer is the standalone web UI server.
type WebServer struct {
cfg *config.Config
vault *VaultClient
logger *slog.Logger
httpSrv *http.Server
staticFS fs.FS
}
// New creates a new WebServer. It dials the vault gRPC endpoint.
func New(cfg *config.Config, logger *slog.Logger) (*WebServer, error) {
vault, err := NewVaultClient(cfg.Web.VaultGRPC, cfg.Web.VaultCACert)
if err != nil {
return nil, fmt.Errorf("webserver: connect to vault: %w", err)
}
staticFS, err := fs.Sub(webui.FS, "static")
if err != nil {
return nil, fmt.Errorf("webserver: static FS: %w", err)
}
return &WebServer{
cfg: cfg,
vault: vault,
logger: logger,
staticFS: staticFS,
}, nil
}
// Start starts the web server. It blocks until the server is closed.
func (ws *WebServer) Start() error {
r := chi.NewRouter()
ws.registerRoutes(r)
ws.httpSrv = &http.Server{
Addr: ws.cfg.Web.ListenAddr,
Handler: r,
ReadTimeout: 30 * time.Second,
WriteTimeout: 30 * time.Second,
IdleTimeout: 120 * time.Second,
}
ws.logger.Info("starting web server", "addr", ws.cfg.Web.ListenAddr)
if ws.cfg.Web.TLSCert != "" && ws.cfg.Web.TLSKey != "" {
ws.httpSrv.TLSConfig = &tls.Config{MinVersion: tls.VersionTLS12}
err := ws.httpSrv.ListenAndServeTLS(ws.cfg.Web.TLSCert, ws.cfg.Web.TLSKey)
if err != nil && err != http.ErrServerClosed {
return fmt.Errorf("webserver: %w", err)
}
return nil
}
err := ws.httpSrv.ListenAndServe()
if err != nil && err != http.ErrServerClosed {
return fmt.Errorf("webserver: %w", err)
}
return nil
}
// Shutdown gracefully shuts down the web server.
func (ws *WebServer) Shutdown(ctx context.Context) error {
_ = ws.vault.Close()
if ws.httpSrv != nil {
return ws.httpSrv.Shutdown(ctx)
}
return nil
}
func (ws *WebServer) renderTemplate(w http.ResponseWriter, name string, data interface{}) {
tmpl, err := template.ParseFS(webui.FS,
"templates/layout.html",
"templates/"+name,
)
if err != nil {
ws.logger.Error("parse template", "name", name, "error", err)
http.Error(w, "internal server error", http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "text/html; charset=utf-8")
if err := tmpl.ExecuteTemplate(w, "layout", data); err != nil {
ws.logger.Error("execute template", "name", name, "error", err)
}
}
func extractCookie(r *http.Request) string {
c, err := r.Cookie("metacrypt_token")
if err != nil {
return ""
}
return c.Value
}

View File

@@ -0,0 +1,37 @@
package webserver
import (
"context"
"crypto/x509"
"encoding/pem"
"errors"
"google.golang.org/protobuf/types/known/structpb"
)
type contextKey int
const tokenInfoCtxKey contextKey = iota
func withTokenInfo(ctx context.Context, info *TokenInfo) context.Context {
return context.WithValue(ctx, tokenInfoCtxKey, info)
}
func tokenInfoFromContext(ctx context.Context) *TokenInfo {
v, _ := ctx.Value(tokenInfoCtxKey).(*TokenInfo)
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.
func parsePEMCert(pemData []byte) (*x509.Certificate, error) {
block, _ := pem.Decode(pemData)
if block == nil {
return nil, errors.New("no PEM block found")
}
return x509.ParseCertificate(block.Bytes)
}

9
web/embed.go Normal file
View File

@@ -0,0 +1,9 @@
// Package webui provides the embedded web UI assets (templates and static files).
package webui
import "embed"
// FS contains all web UI templates and static files.
//
//go:embed templates static
var FS embed.FS