Migrate gRPC server to mcdsl grpcserver package
Replace metacrypt's hand-rolled gRPC interceptor chain with the mcdsl grpcserver package, which provides TLS setup, logging, and method-map auth (public/auth-required/admin-required) out of the box. Metacrypt-specific interceptors are preserved as hooks: - sealInterceptor runs as a PreInterceptor (before logging/auth) - auditInterceptor runs as a PostInterceptor (after auth) The three legacy method maps (seal/auth/admin) are restructured into mcdsl's MethodMap (Public/AuthRequired/AdminRequired) plus a separate seal-required map for the PreInterceptor. Token context is now stored via mcdsl/auth.ContextWithTokenInfo instead of a package-local key. Bumps mcdsl from v1.0.0 to v1.0.1 (adds PreInterceptors/PostInterceptors to grpcserver.Options). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,16 +2,18 @@
|
||||
package grpcserver
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/metadata"
|
||||
|
||||
pb "git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v2"
|
||||
"git.wntrmute.dev/kyle/mcdsl/grpcserver"
|
||||
|
||||
internacme "git.wntrmute.dev/kyle/metacrypt/internal/acme"
|
||||
"git.wntrmute.dev/kyle/metacrypt/internal/audit"
|
||||
"git.wntrmute.dev/kyle/metacrypt/internal/auth"
|
||||
@@ -21,7 +23,7 @@ import (
|
||||
"git.wntrmute.dev/kyle/metacrypt/internal/seal"
|
||||
)
|
||||
|
||||
// GRPCServer wraps the gRPC server and all service implementations.
|
||||
// GRPCServer wraps the mcdsl gRPC server and all service implementations.
|
||||
type GRPCServer struct {
|
||||
cfg *config.Config
|
||||
sealMgr *seal.Manager
|
||||
@@ -30,7 +32,7 @@ type GRPCServer struct {
|
||||
engines *engine.Registry
|
||||
audit *audit.Logger
|
||||
logger *slog.Logger
|
||||
srv *grpc.Server
|
||||
srv *grpcserver.Server
|
||||
acmeHandlers map[string]*internacme.Handler
|
||||
mu sync.Mutex
|
||||
}
|
||||
@@ -57,61 +59,201 @@ func (s *GRPCServer) Start() error {
|
||||
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)
|
||||
opts := &grpcserver.Options{
|
||||
PreInterceptors: []grpc.UnaryServerInterceptor{sealInterceptor(s.sealMgr, s.logger, sealRequiredMethods())},
|
||||
PostInterceptors: []grpc.UnaryServerInterceptor{auditInterceptor(s.audit)},
|
||||
}
|
||||
tlsCfg := &tls.Config{
|
||||
Certificates: []tls.Certificate{tlsCert},
|
||||
MinVersion: tls.VersionTLS13,
|
||||
}
|
||||
creds := credentials.NewTLS(tlsCfg)
|
||||
|
||||
interceptor := chainInterceptors(
|
||||
sealInterceptor(s.sealMgr, s.logger, sealRequiredMethods()),
|
||||
authInterceptor(s.auth, s.logger, authRequiredMethods()),
|
||||
adminInterceptor(s.logger, adminRequiredMethods()),
|
||||
auditInterceptor(s.audit),
|
||||
srv, err := grpcserver.New(
|
||||
s.cfg.Server.TLSCert,
|
||||
s.cfg.Server.TLSKey,
|
||||
s.auth,
|
||||
methodMap(),
|
||||
s.logger,
|
||||
opts,
|
||||
)
|
||||
|
||||
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.RegisterCAServiceServer(s.srv, &caServer{s: s})
|
||||
pb.RegisterPolicyServiceServer(s.srv, &policyServer{s: s})
|
||||
pb.RegisterBarrierServiceServer(s.srv, &barrierServer{s: s})
|
||||
pb.RegisterUserServiceServer(s.srv, &userServer{s: s})
|
||||
pb.RegisterACMEServiceServer(s.srv, &acmeServer{s: s})
|
||||
pb.RegisterSSHCAServiceServer(s.srv, &sshcaServer{s: s})
|
||||
pb.RegisterTransitServiceServer(s.srv, &transitServer{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)
|
||||
return fmt.Errorf("grpc: create server: %w", err)
|
||||
}
|
||||
s.srv = srv
|
||||
|
||||
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
|
||||
pb.RegisterSystemServiceServer(srv.GRPCServer, &systemServer{s: s})
|
||||
pb.RegisterAuthServiceServer(srv.GRPCServer, &authServer{s: s})
|
||||
pb.RegisterEngineServiceServer(srv.GRPCServer, &engineServer{s: s})
|
||||
pb.RegisterPKIServiceServer(srv.GRPCServer, &pkiServer{s: s})
|
||||
pb.RegisterCAServiceServer(srv.GRPCServer, &caServer{s: s})
|
||||
pb.RegisterPolicyServiceServer(srv.GRPCServer, &policyServer{s: s})
|
||||
pb.RegisterBarrierServiceServer(srv.GRPCServer, &barrierServer{s: s})
|
||||
pb.RegisterUserServiceServer(srv.GRPCServer, &userServer{s: s})
|
||||
pb.RegisterACMEServiceServer(srv.GRPCServer, &acmeServer{s: s})
|
||||
pb.RegisterSSHCAServiceServer(srv.GRPCServer, &sshcaServer{s: s})
|
||||
pb.RegisterTransitServiceServer(srv.GRPCServer, &transitServer{s: s})
|
||||
|
||||
return srv.Serve(s.cfg.Server.GRPCAddr)
|
||||
}
|
||||
|
||||
// Shutdown gracefully stops the gRPC server.
|
||||
func (s *GRPCServer) Shutdown() {
|
||||
if s.srv != nil {
|
||||
s.srv.GracefulStop()
|
||||
s.srv.Stop()
|
||||
}
|
||||
}
|
||||
|
||||
// extractToken extracts the bearer token from gRPC metadata. Used by the
|
||||
// auth service Logout handler which needs the raw token.
|
||||
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
|
||||
}
|
||||
|
||||
// callerUsername returns the username from the token info in the context,
|
||||
// or empty string if no token info is present.
|
||||
func callerUsername(ctx context.Context) string {
|
||||
ti := auth.TokenInfoFromContext(ctx)
|
||||
if ti == nil {
|
||||
return ""
|
||||
}
|
||||
return ti.Username
|
||||
}
|
||||
|
||||
// methodMap builds the mcdsl grpcserver.MethodMap for Metacrypt.
|
||||
//
|
||||
// Public methods require no authentication. Auth-required and admin-required
|
||||
// methods are enforced by the mcdsl auth interceptor.
|
||||
func methodMap() grpcserver.MethodMap {
|
||||
return grpcserver.MethodMap{
|
||||
Public: publicMethods(),
|
||||
|
||||
AuthRequired: authRequiredMethods(),
|
||||
|
||||
AdminRequired: adminRequiredMethods(),
|
||||
}
|
||||
}
|
||||
|
||||
// publicMethods returns methods that require no authentication.
|
||||
// These include system lifecycle RPCs (status, init, unseal), the login
|
||||
// endpoint, and read-only PKI/CA/SSH CA endpoints that serve public
|
||||
// certificates and keys.
|
||||
func publicMethods() map[string]bool {
|
||||
return map[string]bool{
|
||||
// System lifecycle — always available.
|
||||
"/metacrypt.v2.SystemService/Status": true,
|
||||
"/metacrypt.v2.SystemService/Init": true,
|
||||
"/metacrypt.v2.SystemService/Unseal": true,
|
||||
// Auth — login requires no existing token.
|
||||
"/metacrypt.v2.AuthService/Login": true,
|
||||
// PKI read-only — public certificates.
|
||||
"/metacrypt.v2.PKIService/GetRootCert": true,
|
||||
"/metacrypt.v2.PKIService/GetChain": true,
|
||||
"/metacrypt.v2.PKIService/GetIssuerCert": true,
|
||||
// CA read-only — public certificates and chains.
|
||||
"/metacrypt.v2.CAService/GetRoot": true,
|
||||
"/metacrypt.v2.CAService/GetIssuer": true,
|
||||
"/metacrypt.v2.CAService/ListIssuers": true,
|
||||
"/metacrypt.v2.CAService/GetChain": true,
|
||||
// SSH CA — public key and key revocation list.
|
||||
"/metacrypt.v2.SSHCAService/GetCAPublicKey": true,
|
||||
"/metacrypt.v2.SSHCAService/GetKRL": true,
|
||||
}
|
||||
}
|
||||
|
||||
// authRequiredMethods returns methods that require a valid MCIAS token but
|
||||
// not necessarily the admin role.
|
||||
func authRequiredMethods() map[string]bool {
|
||||
return map[string]bool{
|
||||
"/metacrypt.v2.AuthService/Logout": true,
|
||||
"/metacrypt.v2.AuthService/TokenInfo": true,
|
||||
"/metacrypt.v2.EngineService/ListMounts": true,
|
||||
"/metacrypt.v2.CAService/IssueCert": true,
|
||||
"/metacrypt.v2.CAService/GetCert": true,
|
||||
"/metacrypt.v2.CAService/ListCerts": true,
|
||||
"/metacrypt.v2.CAService/RenewCert": true,
|
||||
"/metacrypt.v2.CAService/SignCSR": true,
|
||||
"/metacrypt.v2.UserService/Register": true,
|
||||
"/metacrypt.v2.UserService/GetPublicKey": true,
|
||||
"/metacrypt.v2.UserService/ListUsers": true,
|
||||
"/metacrypt.v2.UserService/Encrypt": true,
|
||||
"/metacrypt.v2.UserService/Decrypt": true,
|
||||
"/metacrypt.v2.UserService/ReEncrypt": true,
|
||||
"/metacrypt.v2.UserService/RotateKey": true,
|
||||
"/metacrypt.v2.ACMEService/CreateEAB": true,
|
||||
// SSH CA — sign and read operations.
|
||||
"/metacrypt.v2.SSHCAService/SignHost": true,
|
||||
"/metacrypt.v2.SSHCAService/SignUser": true,
|
||||
"/metacrypt.v2.SSHCAService/GetProfile": true,
|
||||
"/metacrypt.v2.SSHCAService/ListProfiles": true,
|
||||
"/metacrypt.v2.SSHCAService/GetCert": true,
|
||||
"/metacrypt.v2.SSHCAService/ListCerts": true,
|
||||
// Transit — data-plane operations.
|
||||
"/metacrypt.v2.TransitService/GetKey": true,
|
||||
"/metacrypt.v2.TransitService/ListKeys": true,
|
||||
"/metacrypt.v2.TransitService/Encrypt": true,
|
||||
"/metacrypt.v2.TransitService/Decrypt": true,
|
||||
"/metacrypt.v2.TransitService/Rewrap": true,
|
||||
"/metacrypt.v2.TransitService/BatchEncrypt": true,
|
||||
"/metacrypt.v2.TransitService/BatchDecrypt": true,
|
||||
"/metacrypt.v2.TransitService/BatchRewrap": true,
|
||||
"/metacrypt.v2.TransitService/Sign": true,
|
||||
"/metacrypt.v2.TransitService/Verify": true,
|
||||
"/metacrypt.v2.TransitService/Hmac": true,
|
||||
"/metacrypt.v2.TransitService/GetPublicKey": true,
|
||||
}
|
||||
}
|
||||
|
||||
// adminRequiredMethods returns methods that require a valid MCIAS token
|
||||
// with the admin role.
|
||||
func adminRequiredMethods() map[string]bool {
|
||||
return map[string]bool{
|
||||
"/metacrypt.v2.SystemService/Seal": true,
|
||||
"/metacrypt.v2.EngineService/Mount": true,
|
||||
"/metacrypt.v2.EngineService/Unmount": true,
|
||||
"/metacrypt.v2.CAService/ImportRoot": true,
|
||||
"/metacrypt.v2.CAService/CreateIssuer": true,
|
||||
"/metacrypt.v2.CAService/DeleteIssuer": true,
|
||||
"/metacrypt.v2.CAService/RevokeCert": true,
|
||||
"/metacrypt.v2.CAService/DeleteCert": true,
|
||||
"/metacrypt.v2.PolicyService/CreatePolicy": true,
|
||||
"/metacrypt.v2.PolicyService/ListPolicies": true,
|
||||
"/metacrypt.v2.PolicyService/GetPolicy": true,
|
||||
"/metacrypt.v2.PolicyService/DeletePolicy": true,
|
||||
// User.
|
||||
"/metacrypt.v2.UserService/Provision": true,
|
||||
"/metacrypt.v2.UserService/DeleteUser": true,
|
||||
"/metacrypt.v2.ACMEService/SetConfig": true,
|
||||
"/metacrypt.v2.ACMEService/ListAccounts": true,
|
||||
"/metacrypt.v2.ACMEService/ListOrders": true,
|
||||
"/metacrypt.v2.BarrierService/ListKeys": true,
|
||||
"/metacrypt.v2.BarrierService/RotateMEK": true,
|
||||
"/metacrypt.v2.BarrierService/RotateKey": true,
|
||||
"/metacrypt.v2.BarrierService/Migrate": true,
|
||||
// SSH CA.
|
||||
"/metacrypt.v2.SSHCAService/CreateProfile": true,
|
||||
"/metacrypt.v2.SSHCAService/UpdateProfile": true,
|
||||
"/metacrypt.v2.SSHCAService/DeleteProfile": true,
|
||||
"/metacrypt.v2.SSHCAService/RevokeCert": true,
|
||||
"/metacrypt.v2.SSHCAService/DeleteCert": true,
|
||||
// Transit.
|
||||
"/metacrypt.v2.TransitService/CreateKey": true,
|
||||
"/metacrypt.v2.TransitService/DeleteKey": true,
|
||||
"/metacrypt.v2.TransitService/RotateKey": true,
|
||||
"/metacrypt.v2.TransitService/UpdateKeyConfig": true,
|
||||
"/metacrypt.v2.TransitService/TrimKey": true,
|
||||
}
|
||||
}
|
||||
|
||||
// sealRequiredMethods returns the set of RPC full names that require the vault
|
||||
// to be unsealed.
|
||||
// to be unsealed. This is used by the sealInterceptor PreInterceptor.
|
||||
func sealRequiredMethods() map[string]bool {
|
||||
return map[string]bool{
|
||||
"/metacrypt.v2.AuthService/Login": true,
|
||||
@@ -153,11 +295,11 @@ func sealRequiredMethods() map[string]bool {
|
||||
"/metacrypt.v2.ACMEService/CreateEAB": true,
|
||||
"/metacrypt.v2.ACMEService/SetConfig": true,
|
||||
"/metacrypt.v2.ACMEService/ListAccounts": true,
|
||||
"/metacrypt.v2.ACMEService/ListOrders": true,
|
||||
"/metacrypt.v2.BarrierService/ListKeys": true,
|
||||
"/metacrypt.v2.BarrierService/RotateMEK": true,
|
||||
"/metacrypt.v2.BarrierService/RotateKey": true,
|
||||
"/metacrypt.v2.BarrierService/Migrate": true,
|
||||
"/metacrypt.v2.ACMEService/ListOrders": true,
|
||||
"/metacrypt.v2.BarrierService/ListKeys": true,
|
||||
"/metacrypt.v2.BarrierService/RotateMEK": true,
|
||||
"/metacrypt.v2.BarrierService/RotateKey": true,
|
||||
"/metacrypt.v2.BarrierService/Migrate": true,
|
||||
// SSH CA.
|
||||
"/metacrypt.v2.SSHCAService/GetCAPublicKey": true,
|
||||
"/metacrypt.v2.SSHCAService/SignHost": true,
|
||||
@@ -190,118 +332,7 @@ func sealRequiredMethods() map[string]bool {
|
||||
"/metacrypt.v2.TransitService/Verify": true,
|
||||
"/metacrypt.v2.TransitService/Hmac": true,
|
||||
"/metacrypt.v2.TransitService/GetPublicKey": true,
|
||||
}
|
||||
}
|
||||
|
||||
// authRequiredMethods returns the set of RPC full names that require a valid token.
|
||||
func authRequiredMethods() map[string]bool {
|
||||
return map[string]bool{
|
||||
"/metacrypt.v2.AuthService/Logout": true,
|
||||
"/metacrypt.v2.AuthService/TokenInfo": true,
|
||||
"/metacrypt.v2.EngineService/Mount": true,
|
||||
"/metacrypt.v2.EngineService/Unmount": true,
|
||||
"/metacrypt.v2.EngineService/ListMounts": true,
|
||||
"/metacrypt.v2.CAService/ImportRoot": true,
|
||||
"/metacrypt.v2.CAService/CreateIssuer": true,
|
||||
"/metacrypt.v2.CAService/DeleteIssuer": true,
|
||||
"/metacrypt.v2.CAService/ListIssuers": true,
|
||||
"/metacrypt.v2.CAService/IssueCert": true,
|
||||
"/metacrypt.v2.CAService/GetCert": true,
|
||||
"/metacrypt.v2.CAService/ListCerts": true,
|
||||
"/metacrypt.v2.CAService/RenewCert": true,
|
||||
"/metacrypt.v2.CAService/SignCSR": true,
|
||||
"/metacrypt.v2.CAService/RevokeCert": true,
|
||||
"/metacrypt.v2.CAService/DeleteCert": true,
|
||||
"/metacrypt.v2.PolicyService/CreatePolicy": true,
|
||||
"/metacrypt.v2.PolicyService/ListPolicies": true,
|
||||
"/metacrypt.v2.PolicyService/GetPolicy": true,
|
||||
"/metacrypt.v2.PolicyService/DeletePolicy": true,
|
||||
"/metacrypt.v2.UserService/Register": true,
|
||||
"/metacrypt.v2.UserService/Provision": true,
|
||||
"/metacrypt.v2.UserService/GetPublicKey": true,
|
||||
"/metacrypt.v2.UserService/ListUsers": true,
|
||||
"/metacrypt.v2.UserService/Encrypt": true,
|
||||
"/metacrypt.v2.UserService/Decrypt": true,
|
||||
"/metacrypt.v2.UserService/ReEncrypt": true,
|
||||
"/metacrypt.v2.UserService/RotateKey": true,
|
||||
"/metacrypt.v2.UserService/DeleteUser": true,
|
||||
"/metacrypt.v2.ACMEService/CreateEAB": true,
|
||||
"/metacrypt.v2.ACMEService/SetConfig": true,
|
||||
"/metacrypt.v2.ACMEService/ListAccounts": true,
|
||||
"/metacrypt.v2.ACMEService/ListOrders": true,
|
||||
"/metacrypt.v2.BarrierService/ListKeys": true,
|
||||
"/metacrypt.v2.BarrierService/RotateMEK": true,
|
||||
"/metacrypt.v2.BarrierService/RotateKey": true,
|
||||
"/metacrypt.v2.BarrierService/Migrate": true,
|
||||
// SSH CA.
|
||||
"/metacrypt.v2.SSHCAService/SignHost": true,
|
||||
"/metacrypt.v2.SSHCAService/SignUser": true,
|
||||
"/metacrypt.v2.SSHCAService/CreateProfile": true,
|
||||
"/metacrypt.v2.SSHCAService/UpdateProfile": true,
|
||||
"/metacrypt.v2.SSHCAService/GetProfile": true,
|
||||
"/metacrypt.v2.SSHCAService/ListProfiles": true,
|
||||
"/metacrypt.v2.SSHCAService/DeleteProfile": true,
|
||||
"/metacrypt.v2.SSHCAService/GetCert": true,
|
||||
"/metacrypt.v2.SSHCAService/ListCerts": true,
|
||||
"/metacrypt.v2.SSHCAService/RevokeCert": true,
|
||||
"/metacrypt.v2.SSHCAService/DeleteCert": true,
|
||||
// Transit.
|
||||
"/metacrypt.v2.TransitService/CreateKey": true,
|
||||
"/metacrypt.v2.TransitService/DeleteKey": true,
|
||||
"/metacrypt.v2.TransitService/GetKey": true,
|
||||
"/metacrypt.v2.TransitService/ListKeys": true,
|
||||
"/metacrypt.v2.TransitService/RotateKey": true,
|
||||
"/metacrypt.v2.TransitService/UpdateKeyConfig": true,
|
||||
"/metacrypt.v2.TransitService/TrimKey": true,
|
||||
"/metacrypt.v2.TransitService/Encrypt": true,
|
||||
"/metacrypt.v2.TransitService/Decrypt": true,
|
||||
"/metacrypt.v2.TransitService/Rewrap": true,
|
||||
"/metacrypt.v2.TransitService/BatchEncrypt": true,
|
||||
"/metacrypt.v2.TransitService/BatchDecrypt": true,
|
||||
"/metacrypt.v2.TransitService/BatchRewrap": true,
|
||||
"/metacrypt.v2.TransitService/Sign": true,
|
||||
"/metacrypt.v2.TransitService/Verify": true,
|
||||
"/metacrypt.v2.TransitService/Hmac": true,
|
||||
"/metacrypt.v2.TransitService/GetPublicKey": true,
|
||||
}
|
||||
}
|
||||
|
||||
// adminRequiredMethods returns the set of RPC full names that require admin.
|
||||
func adminRequiredMethods() map[string]bool {
|
||||
return map[string]bool{
|
||||
"/metacrypt.v2.SystemService/Seal": true,
|
||||
"/metacrypt.v2.EngineService/Mount": true,
|
||||
"/metacrypt.v2.EngineService/Unmount": true,
|
||||
"/metacrypt.v2.CAService/ImportRoot": true,
|
||||
"/metacrypt.v2.CAService/CreateIssuer": true,
|
||||
"/metacrypt.v2.CAService/DeleteIssuer": true,
|
||||
"/metacrypt.v2.CAService/RevokeCert": true,
|
||||
"/metacrypt.v2.CAService/DeleteCert": true,
|
||||
"/metacrypt.v2.PolicyService/CreatePolicy": true,
|
||||
"/metacrypt.v2.PolicyService/ListPolicies": true,
|
||||
"/metacrypt.v2.PolicyService/GetPolicy": true,
|
||||
"/metacrypt.v2.PolicyService/DeletePolicy": true,
|
||||
// User.
|
||||
"/metacrypt.v2.UserService/Provision": true,
|
||||
"/metacrypt.v2.UserService/DeleteUser": true,
|
||||
"/metacrypt.v2.ACMEService/SetConfig": true,
|
||||
"/metacrypt.v2.ACMEService/ListAccounts": true,
|
||||
"/metacrypt.v2.ACMEService/ListOrders": true,
|
||||
"/metacrypt.v2.BarrierService/ListKeys": true,
|
||||
"/metacrypt.v2.BarrierService/RotateMEK": true,
|
||||
"/metacrypt.v2.BarrierService/RotateKey": true,
|
||||
"/metacrypt.v2.BarrierService/Migrate": true,
|
||||
// SSH CA.
|
||||
"/metacrypt.v2.SSHCAService/CreateProfile": true,
|
||||
"/metacrypt.v2.SSHCAService/UpdateProfile": true,
|
||||
"/metacrypt.v2.SSHCAService/DeleteProfile": true,
|
||||
"/metacrypt.v2.SSHCAService/RevokeCert": true,
|
||||
"/metacrypt.v2.SSHCAService/DeleteCert": true,
|
||||
// Transit.
|
||||
"/metacrypt.v2.TransitService/CreateKey": true,
|
||||
"/metacrypt.v2.TransitService/DeleteKey": true,
|
||||
"/metacrypt.v2.TransitService/RotateKey": true,
|
||||
"/metacrypt.v2.TransitService/UpdateKeyConfig": true,
|
||||
"/metacrypt.v2.TransitService/TrimKey": true,
|
||||
// Seal itself requires unsealed state.
|
||||
"/metacrypt.v2.SystemService/Seal": true,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user