mirror of
https://github.com/pomerium/pomerium.git
synced 2025-04-29 18:36:30 +02:00
211 lines
5.8 KiB
Go
211 lines
5.8 KiB
Go
package authorize
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/go-jose/go-jose/v3/jwt"
|
|
"github.com/rs/zerolog"
|
|
"go.opentelemetry.io/otel/attribute"
|
|
|
|
"github.com/pomerium/pomerium/authorize/evaluator"
|
|
"github.com/pomerium/pomerium/internal/log"
|
|
"github.com/pomerium/pomerium/pkg/grpc/databroker"
|
|
"github.com/pomerium/pomerium/pkg/grpc/session"
|
|
"github.com/pomerium/pomerium/pkg/grpc/user"
|
|
"github.com/pomerium/pomerium/pkg/grpcutil"
|
|
"github.com/pomerium/pomerium/pkg/storage"
|
|
"github.com/pomerium/pomerium/pkg/telemetry/requestid"
|
|
)
|
|
|
|
func (a *Authorize) logAuthorizeCheck(
|
|
ctx context.Context,
|
|
in *evaluator.Request,
|
|
res *evaluator.Result, s sessionOrServiceAccount, u *user.User,
|
|
) {
|
|
ctx, span := a.tracer.Start(ctx, "authorize.grpc.LogAuthorizeCheck")
|
|
defer span.End()
|
|
|
|
hdrs := in.HTTP.Headers
|
|
impersonateDetails := a.getImpersonateDetails(ctx, s)
|
|
|
|
evt := log.Ctx(ctx).Info().Str("service", "authorize")
|
|
fields := a.currentOptions.Load().GetAuthorizeLogFields()
|
|
for _, field := range fields {
|
|
evt = populateLogEvent(ctx, field, evt, in, s, u, impersonateDetails, res)
|
|
}
|
|
evt = log.HTTPHeaders(evt, fields, hdrs)
|
|
|
|
// result
|
|
if res != nil {
|
|
span.SetAttributes(attribute.Bool("result.allow", res.Allow.Value))
|
|
evt = evt.Bool("allow", res.Allow.Value)
|
|
allowReasons := res.Allow.Reasons.Strings()
|
|
if res.Allow.Value {
|
|
span.SetAttributes(attribute.StringSlice("result.allow-why-true", allowReasons))
|
|
evt = evt.Strs("allow-why-true", allowReasons)
|
|
} else {
|
|
span.SetAttributes(attribute.StringSlice("result.allow-why-false", allowReasons))
|
|
evt = evt.Strs("allow-why-false", allowReasons)
|
|
}
|
|
evt = evt.Bool("deny", res.Deny.Value)
|
|
denyReasons := res.Deny.Reasons.Strings()
|
|
if res.Deny.Value {
|
|
span.SetAttributes(attribute.StringSlice("result.deny-why-true", denyReasons))
|
|
evt = evt.Strs("deny-why-true", denyReasons)
|
|
} else {
|
|
span.SetAttributes(attribute.StringSlice("result.deny-why-false", denyReasons))
|
|
evt = evt.Strs("deny-why-false", denyReasons)
|
|
}
|
|
}
|
|
|
|
evt.Msg("authorize check")
|
|
}
|
|
|
|
type impersonateDetails struct {
|
|
email string
|
|
sessionID string
|
|
userID string
|
|
}
|
|
|
|
func (a *Authorize) getImpersonateDetails(
|
|
ctx context.Context,
|
|
s sessionOrServiceAccount,
|
|
) *impersonateDetails {
|
|
var sessionID string
|
|
if s, ok := s.(*session.Session); ok {
|
|
sessionID = s.GetImpersonateSessionId()
|
|
}
|
|
if sessionID == "" {
|
|
return nil
|
|
}
|
|
|
|
querier := storage.GetQuerier(ctx)
|
|
|
|
req := &databroker.QueryRequest{
|
|
Type: grpcutil.GetTypeURL(new(session.Session)),
|
|
Limit: 1,
|
|
}
|
|
req.SetFilterByID(sessionID)
|
|
res, err := querier.Query(ctx, req)
|
|
if err != nil || len(res.GetRecords()) == 0 {
|
|
return nil
|
|
}
|
|
|
|
impersonatedSessionMsg, err := res.GetRecords()[0].GetData().UnmarshalNew()
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
impersonatedSession, ok := impersonatedSessionMsg.(*session.Session)
|
|
if !ok {
|
|
return nil
|
|
}
|
|
userID := impersonatedSession.GetUserId()
|
|
|
|
req = &databroker.QueryRequest{
|
|
Type: grpcutil.GetTypeURL(new(user.User)),
|
|
Limit: 1,
|
|
}
|
|
req.SetFilterByID(userID)
|
|
res, err = querier.Query(ctx, req)
|
|
if err != nil || len(res.GetRecords()) == 0 {
|
|
return nil
|
|
}
|
|
|
|
impersonatedUserMsg, err := res.GetRecords()[0].GetData().UnmarshalNew()
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
impersonatedUser, ok := impersonatedUserMsg.(*user.User)
|
|
if !ok {
|
|
return nil
|
|
}
|
|
email := impersonatedUser.GetEmail()
|
|
|
|
return &impersonateDetails{
|
|
sessionID: sessionID,
|
|
userID: userID,
|
|
email: email,
|
|
}
|
|
}
|
|
|
|
func populateLogEvent(
|
|
ctx context.Context,
|
|
field log.AuthorizeLogField,
|
|
evt *zerolog.Event,
|
|
in *evaluator.Request,
|
|
s sessionOrServiceAccount,
|
|
u *user.User,
|
|
impersonateDetails *impersonateDetails,
|
|
res *evaluator.Result,
|
|
) *zerolog.Event {
|
|
switch field {
|
|
case log.AuthorizeLogFieldCheckRequestID:
|
|
return evt.Str(string(field), in.HTTP.Headers["X-Request-Id"])
|
|
case log.AuthorizeLogFieldEmail:
|
|
return evt.Str(string(field), u.GetEmail())
|
|
case log.AuthorizeLogFieldHost:
|
|
return evt.Str(string(field), in.HTTP.Hostname)
|
|
case log.AuthorizeLogFieldIDToken:
|
|
if s, ok := s.(*session.Session); ok {
|
|
evt = evt.Str(string(field), s.GetIdToken().GetRaw())
|
|
}
|
|
return evt
|
|
case log.AuthorizeLogFieldIDTokenClaims:
|
|
if s, ok := s.(*session.Session); ok {
|
|
if t, err := jwt.ParseSigned(s.GetIdToken().GetRaw()); err == nil {
|
|
var m map[string]any
|
|
_ = t.UnsafeClaimsWithoutVerification(&m)
|
|
evt = evt.Interface(string(field), m)
|
|
}
|
|
}
|
|
return evt
|
|
case log.AuthorizeLogFieldImpersonateEmail:
|
|
if impersonateDetails != nil {
|
|
evt = evt.Str(string(field), impersonateDetails.email)
|
|
}
|
|
return evt
|
|
case log.AuthorizeLogFieldImpersonateSessionID:
|
|
if impersonateDetails != nil {
|
|
evt = evt.Str(string(field), impersonateDetails.sessionID)
|
|
}
|
|
return evt
|
|
case log.AuthorizeLogFieldImpersonateUserID:
|
|
if impersonateDetails != nil {
|
|
evt = evt.Str(string(field), impersonateDetails.userID)
|
|
}
|
|
return evt
|
|
case log.AuthorizeLogFieldIP:
|
|
return evt.Str(string(field), in.HTTP.IP)
|
|
case log.AuthorizeLogFieldMethod:
|
|
return evt.Str(string(field), in.HTTP.Method)
|
|
case log.AuthorizeLogFieldPath:
|
|
return evt.Str(string(field), in.HTTP.Path)
|
|
case log.AuthorizeLogFieldQuery:
|
|
return evt.Str(string(field), in.HTTP.Query)
|
|
case log.AuthorizeLogFieldRequestID:
|
|
return evt.Str(string(field), requestid.FromContext(ctx))
|
|
case log.AuthorizeLogFieldServiceAccountID:
|
|
if sa, ok := s.(*user.ServiceAccount); ok {
|
|
evt = evt.Str(string(field), sa.GetId())
|
|
}
|
|
return evt
|
|
case log.AuthorizeLogFieldSessionID:
|
|
if s, ok := s.(*session.Session); ok {
|
|
evt = evt.Str(string(field), s.GetId())
|
|
}
|
|
return evt
|
|
case log.AuthorizeLogFieldUser:
|
|
var userID string
|
|
if s != nil {
|
|
userID = s.GetUserId()
|
|
}
|
|
return evt.Str(string(field), userID)
|
|
default:
|
|
if res != nil {
|
|
if v, ok := res.AdditionalLogFields[field]; ok {
|
|
evt = evt.Interface(string(field), v)
|
|
}
|
|
}
|
|
return evt
|
|
}
|
|
}
|