package grpcserver import ( "context" "errors" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" pb "git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v2" "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 { if errors.Is(err, seal.ErrAlreadyInitialized) { return nil, status.Error(codes.AlreadyExists, "already initialized") } 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 { if errors.Is(err, seal.ErrNotInitialized) { return nil, status.Error(codes.FailedPrecondition, "not initialized") } else if errors.Is(err, seal.ErrInvalidPassword) { return nil, status.Error(codes.Unauthenticated, "invalid password") } else if errors.Is(err, seal.ErrRateLimited) { return nil, status.Error(codes.ResourceExhausted, "too many attempts, try again later") } else if errors.Is(err, seal.ErrNotSealed) { return nil, status.Error(codes.FailedPrecondition, "already unsealed") } 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 }