fix: add requester IP to workspace build audit logs (#10242)

This commit is contained in:
Colin Adler
2023-10-18 15:08:02 -05:00
committed by GitHub
parent 504cedf15a
commit 1ad998ee3a
17 changed files with 381 additions and 174 deletions
+61 -6
View File
@@ -11,6 +11,8 @@ import (
"github.com/google/uuid"
"github.com/sqlc-dev/pqtype"
"go.opentelemetry.io/otel/baggage"
"golang.org/x/xerrors"
"cdr.dev/slog"
"github.com/coder/coder/v2/coderd/database"
@@ -54,6 +56,7 @@ type BuildAuditParams[T Auditable] struct {
Status int
Action database.AuditAction
OrganizationID uuid.UUID
IP string
AdditionalFields json.RawMessage
New T
@@ -248,9 +251,7 @@ func InitRequest[T Auditable](w http.ResponseWriter, p *RequestParams) (*Request
// WorkspaceBuildAudit creates an audit log for a workspace build.
// The audit log is committed upon invocation.
func WorkspaceBuildAudit[T Auditable](ctx context.Context, p *BuildAuditParams[T]) {
// As the audit request has not been initiated directly by a user, we omit
// certain user details.
ip := parseIP("")
ip := parseIP(p.IP)
diff := Diff(p.Audit, p.Old, p.New)
var err error
@@ -280,16 +281,70 @@ func WorkspaceBuildAudit[T Auditable](ctx context.Context, p *BuildAuditParams[T
RequestID: p.JobID,
AdditionalFields: p.AdditionalFields,
}
exportErr := p.Audit.Export(ctx, auditLog)
if exportErr != nil {
err = p.Audit.Export(ctx, auditLog)
if err != nil {
p.Log.Error(ctx, "export audit log",
slog.F("audit_log", auditLog),
slog.Error(err),
)
return
}
}
type WorkspaceBuildBaggage struct {
IP string
}
func (b WorkspaceBuildBaggage) Props() ([]baggage.Property, error) {
ipProp, err := baggage.NewKeyValueProperty("ip", b.IP)
if err != nil {
return nil, xerrors.Errorf("create ip kv property: %w", err)
}
return []baggage.Property{ipProp}, nil
}
func WorkspaceBuildBaggageFromRequest(r *http.Request) WorkspaceBuildBaggage {
return WorkspaceBuildBaggage{IP: r.RemoteAddr}
}
type Baggage interface {
Props() ([]baggage.Property, error)
}
func BaggageToContext(ctx context.Context, d Baggage) (context.Context, error) {
props, err := d.Props()
if err != nil {
return ctx, xerrors.Errorf("create baggage properties: %w", err)
}
m, err := baggage.NewMember("audit", "baggage", props...)
if err != nil {
return ctx, xerrors.Errorf("create new baggage member: %w", err)
}
b, err := baggage.New(m)
if err != nil {
return ctx, xerrors.Errorf("create new baggage carrier: %w", err)
}
return baggage.ContextWithBaggage(ctx, b), nil
}
func BaggageFromContext(ctx context.Context) WorkspaceBuildBaggage {
d := WorkspaceBuildBaggage{}
b := baggage.FromContext(ctx)
props := b.Member("audit").Properties()
for _, prop := range props {
switch prop.Key() {
case "ip":
d.IP, _ = prop.Value()
default:
}
}
return d
}
func either[T Auditable, R any](old, new T, fn func(T) R, auditAction database.AuditAction) R {
if ResourceID(new) != uuid.Nil {
return fn(new)