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>
64 lines
1.8 KiB
Go
64 lines
1.8 KiB
Go
package grpcserver
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"google.golang.org/grpc/codes"
|
|
"google.golang.org/grpc/status"
|
|
"google.golang.org/protobuf/types/known/timestamppb"
|
|
|
|
mcias "git.wntrmute.dev/kyle/mcias/clients/go"
|
|
|
|
pb "git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v2"
|
|
)
|
|
|
|
type authServer struct {
|
|
pb.UnimplementedAuthServiceServer
|
|
s *GRPCServer
|
|
}
|
|
|
|
func (as *authServer) Login(_ context.Context, req *pb.LoginRequest) (*pb.LoginResponse, error) {
|
|
token, expiresAtStr, err := as.s.auth.Login(req.Username, req.Password, req.TotpCode)
|
|
if err != nil {
|
|
return nil, status.Error(codes.Unauthenticated, "invalid credentials")
|
|
}
|
|
var expiresAt *timestamppb.Timestamp
|
|
if t, err := time.Parse(time.RFC3339, expiresAtStr); err == nil {
|
|
expiresAt = timestamppb.New(t)
|
|
}
|
|
as.s.logger.Info("audit: login", "username", req.Username)
|
|
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)
|
|
}
|
|
as.s.logger.Info("audit: logout", "username", callerUsername(ctx))
|
|
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
|
|
}
|