Log Info-level audit events on success for: - system: Init, Unseal, Seal - auth: Login, Logout - engine: Mount, Unmount - policy: CreatePolicy, DeletePolicy - ca: ImportRoot, CreateIssuer, DeleteIssuer, IssueCert, RenewCert Each log line includes relevant identifiers (mount, issuer, serial, CN, SANs, username) so that certificate issuance and other privileged operations are traceable in the server logs. Co-authored-by: Junie <junie@jetbrains.com>
84 lines
2.4 KiB
Go
84 lines
2.4 KiB
Go
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/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 len(req.Config) > 0 {
|
|
config = make(map[string]interface{}, len(req.Config))
|
|
for k, v := range req.Config {
|
|
config[k] = v
|
|
}
|
|
}
|
|
|
|
if err := es.s.engines.Mount(ctx, req.Name, engine.EngineType(req.Type), config); err != nil {
|
|
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())
|
|
}
|
|
}
|
|
ti := tokenInfoFromContext(ctx)
|
|
username := ""
|
|
if ti != nil {
|
|
username = ti.Username
|
|
}
|
|
es.s.logger.Info("audit: engine mounted", "name", req.Name, "type", req.Type, "username", username)
|
|
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())
|
|
}
|
|
ti := tokenInfoFromContext(ctx)
|
|
username := ""
|
|
if ti != nil {
|
|
username = ti.Username
|
|
}
|
|
es.s.logger.Info("audit: engine unmounted", "name", req.Name, "username", username)
|
|
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
|
|
}
|
|
|