From 8e0b7b6c257558c62f58fcf787e86cc57658e3c7 Mon Sep 17 00:00:00 2001 From: pascal Date: Thu, 29 Jan 2026 14:27:57 +0100 Subject: [PATCH] add api for access log events --- .../reverseproxy/accesslogs/accesslogentry.go | 105 +++++++ .../reverseproxy/accesslogs/interface.go | 10 + .../reverseproxy/accesslogs/manager/api.go | 45 +++ .../accesslogs/manager/manager.go | 74 +++++ .../modules/reverseproxy/domain/api.go | 2 +- .../modules/reverseproxy/manager/api.go | 10 +- .../modules/reverseproxy/reverseproxy.go | 13 +- management/internals/server/boot.go | 13 +- management/internals/shared/grpc/proxy.go | 48 ++- management/server/http/handler.go | 5 +- management/server/store/sql_store.go | 39 +++ management/server/store/store.go | 4 + proxy/internal/accesslog/logger.go | 4 + proxy/internal/accesslog/middleware.go | 9 +- proxy/internal/proxy/context.go | 54 +++- proxy/internal/proxy/reverseproxy.go | 4 +- proxy/internal/proxy/servicemapping.go | 17 +- proxy/internal/roundtrip/netbird.go | 5 +- proxy/server.go | 8 +- shared/management/http/api/openapi.yml | 89 ++++++ shared/management/http/api/types.gen.go | 57 +++- shared/management/proto/proxy_service.pb.go | 287 ++++++++++-------- shared/management/proto/proxy_service.proto | 32 +- 23 files changed, 745 insertions(+), 189 deletions(-) create mode 100644 management/internals/modules/reverseproxy/accesslogs/accesslogentry.go create mode 100644 management/internals/modules/reverseproxy/accesslogs/interface.go create mode 100644 management/internals/modules/reverseproxy/accesslogs/manager/api.go create mode 100644 management/internals/modules/reverseproxy/accesslogs/manager/manager.go diff --git a/management/internals/modules/reverseproxy/accesslogs/accesslogentry.go b/management/internals/modules/reverseproxy/accesslogs/accesslogentry.go new file mode 100644 index 000000000..b524d027b --- /dev/null +++ b/management/internals/modules/reverseproxy/accesslogs/accesslogentry.go @@ -0,0 +1,105 @@ +package accesslogs + +import ( + "net" + "net/netip" + "time" + + "github.com/netbirdio/netbird/management/server/peer" + "github.com/netbirdio/netbird/shared/management/http/api" + "github.com/netbirdio/netbird/shared/management/proto" +) + +type AccessLogEntry struct { + ID string `gorm:"primaryKey"` + AccountID string `gorm:"index"` + ProxyID string `gorm:"index"` + Timestamp time.Time `gorm:"index"` + GeoLocation peer.Location `gorm:"embedded;embeddedPrefix:location_"` + Method string + Host string + Path string + Duration time.Duration + StatusCode int + Reason string + UserId string + AuthMethodUsed string +} + +// FromProto creates an AccessLogEntry from a proto.AccessLog +func (a *AccessLogEntry) FromProto(proxyLog *proto.AccessLog) { + a.ID = proxyLog.GetLogId() + a.ProxyID = proxyLog.GetServiceId() + a.Timestamp = proxyLog.GetTimestamp().AsTime() + a.Method = proxyLog.GetMethod() + a.Host = proxyLog.GetHost() + a.Path = proxyLog.GetPath() + a.Duration = time.Duration(proxyLog.GetDurationMs()) * time.Millisecond + a.StatusCode = int(proxyLog.GetResponseCode()) + a.UserId = proxyLog.GetUserId() + a.AuthMethodUsed = proxyLog.GetAuthMechanism() + a.AccountID = proxyLog.GetAccountId() + + if sourceIP := proxyLog.GetSourceIp(); sourceIP != "" { + if ip, err := netip.ParseAddr(sourceIP); err == nil { + a.GeoLocation.ConnectionIP = net.IP(ip.AsSlice()) + } + } + + if !proxyLog.GetAuthSuccess() { + a.Reason = "Authentication failed" + } else if proxyLog.GetResponseCode() >= 400 { + a.Reason = "Request failed" + } +} + +// ToAPIResponse converts an AccessLogEntry to the API ProxyAccessLog type +func (a *AccessLogEntry) ToAPIResponse() *api.ProxyAccessLog { + var sourceIP *string + if a.GeoLocation.ConnectionIP != nil { + ip := a.GeoLocation.ConnectionIP.String() + sourceIP = &ip + } + + var reason *string + if a.Reason != "" { + reason = &a.Reason + } + + var userID *string + if a.UserId != "" { + userID = &a.UserId + } + + var authMethod *string + if a.AuthMethodUsed != "" { + authMethod = &a.AuthMethodUsed + } + + var countryCode *string + if a.GeoLocation.CountryCode != "" { + countryCode = &a.GeoLocation.CountryCode + } + + var cityName *string + if a.GeoLocation.CityName != "" { + cityName = &a.GeoLocation.CityName + } + + return &api.ProxyAccessLog{ + Id: a.ID, + ProxyId: a.ProxyID, + Timestamp: a.Timestamp, + Method: a.Method, + Host: a.Host, + Path: a.Path, + DurationMs: int(a.Duration.Milliseconds()), + StatusCode: a.StatusCode, + SourceIp: sourceIP, + Reason: reason, + UserId: userID, + AuthMethodUsed: authMethod, + CountryCode: countryCode, + CityName: cityName, + } +} diff --git a/management/internals/modules/reverseproxy/accesslogs/interface.go b/management/internals/modules/reverseproxy/accesslogs/interface.go new file mode 100644 index 000000000..3b92b04e0 --- /dev/null +++ b/management/internals/modules/reverseproxy/accesslogs/interface.go @@ -0,0 +1,10 @@ +package accesslogs + +import ( + "context" +) + +type Manager interface { + SaveAccessLog(ctx context.Context, proxyLog *AccessLogEntry) error + GetAllAccessLogs(ctx context.Context, accountID, userID string) ([]*AccessLogEntry, error) +} diff --git a/management/internals/modules/reverseproxy/accesslogs/manager/api.go b/management/internals/modules/reverseproxy/accesslogs/manager/api.go new file mode 100644 index 000000000..a0e5ad84c --- /dev/null +++ b/management/internals/modules/reverseproxy/accesslogs/manager/api.go @@ -0,0 +1,45 @@ +package manager + +import ( + "net/http" + + "github.com/gorilla/mux" + + "github.com/netbirdio/netbird/management/internals/modules/reverseproxy/accesslogs" + nbcontext "github.com/netbirdio/netbird/management/server/context" + "github.com/netbirdio/netbird/shared/management/http/api" + "github.com/netbirdio/netbird/shared/management/http/util" +) + +type handler struct { + manager accesslogs.Manager +} + +func RegisterEndpoints(router *mux.Router, manager accesslogs.Manager) { + h := &handler{ + manager: manager, + } + + router.HandleFunc("/events/proxy", h.getAccessLogs).Methods("GET", "OPTIONS") +} + +func (h *handler) getAccessLogs(w http.ResponseWriter, r *http.Request) { + userAuth, err := nbcontext.GetUserAuthFromContext(r.Context()) + if err != nil { + util.WriteError(r.Context(), err, w) + return + } + + logs, err := h.manager.GetAllAccessLogs(r.Context(), userAuth.AccountId, userAuth.UserId) + if err != nil { + util.WriteError(r.Context(), err, w) + return + } + + apiLogs := make([]api.ProxyAccessLog, 0, len(logs)) + for _, log := range logs { + apiLogs = append(apiLogs, *log.ToAPIResponse()) + } + + util.WriteJSONObject(r.Context(), w, apiLogs) +} diff --git a/management/internals/modules/reverseproxy/accesslogs/manager/manager.go b/management/internals/modules/reverseproxy/accesslogs/manager/manager.go new file mode 100644 index 000000000..319e401be --- /dev/null +++ b/management/internals/modules/reverseproxy/accesslogs/manager/manager.go @@ -0,0 +1,74 @@ +package manager + +import ( + "context" + + log "github.com/sirupsen/logrus" + + "github.com/netbirdio/netbird/management/internals/modules/reverseproxy/accesslogs" + "github.com/netbirdio/netbird/management/server/geolocation" + "github.com/netbirdio/netbird/management/server/permissions" + "github.com/netbirdio/netbird/management/server/permissions/modules" + "github.com/netbirdio/netbird/management/server/permissions/operations" + "github.com/netbirdio/netbird/management/server/store" + "github.com/netbirdio/netbird/shared/management/status" +) + +type managerImpl struct { + store store.Store + permissionsManager permissions.Manager + geo geolocation.Geolocation +} + +func NewManager(store store.Store, permissionsManager permissions.Manager, geo geolocation.Geolocation) accesslogs.Manager { + return &managerImpl{ + store: store, + permissionsManager: permissionsManager, + geo: geo, + } +} + +// SaveAccessLog saves an access log entry to the database after enriching it +func (m *managerImpl) SaveAccessLog(ctx context.Context, logEntry *accesslogs.AccessLogEntry) error { + if m.geo != nil && logEntry.GeoLocation.ConnectionIP != nil { + location, err := m.geo.Lookup(logEntry.GeoLocation.ConnectionIP) + if err != nil { + log.WithContext(ctx).Warnf("failed to get location for access log source IP [%s]: %v", logEntry.GeoLocation.ConnectionIP.String(), err) + } else { + logEntry.GeoLocation.CountryCode = location.Country.ISOCode + logEntry.GeoLocation.CityName = location.City.Names.En + logEntry.GeoLocation.GeoNameID = location.City.GeonameID + } + } + + if err := m.store.CreateAccessLog(ctx, logEntry); err != nil { + log.WithContext(ctx).WithFields(log.Fields{ + "proxy_id": logEntry.ProxyID, + "method": logEntry.Method, + "host": logEntry.Host, + "path": logEntry.Path, + "status": logEntry.StatusCode, + }).Errorf("failed to save access log: %v", err) + return err + } + + return nil +} + +// GetAllAccessLogs retrieves all access logs for an account +func (m *managerImpl) GetAllAccessLogs(ctx context.Context, accountID, userID string) ([]*accesslogs.AccessLogEntry, error) { + ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Services, operations.Read) + if err != nil { + return nil, status.NewPermissionValidationError(err) + } + if !ok { + return nil, status.NewPermissionDeniedError() + } + + logs, err := m.store.GetAccountAccessLogs(ctx, store.LockingStrengthNone, accountID) + if err != nil { + return nil, err + } + + return logs, nil +} diff --git a/management/internals/modules/reverseproxy/domain/api.go b/management/internals/modules/reverseproxy/domain/api.go index 3b069bd94..7d1a37cc8 100644 --- a/management/internals/modules/reverseproxy/domain/api.go +++ b/management/internals/modules/reverseproxy/domain/api.go @@ -76,7 +76,7 @@ func (h *handler) createCustomDomain(w http.ResponseWriter, r *http.Request) { return } - var req api.PostApiReverseProxyDomainsJSONRequestBody + var req api.PostApiReverseProxiesDomainsJSONRequestBody if err := json.NewDecoder(r.Body).Decode(&req); err != nil { util.WriteErrorResponse("couldn't parse JSON request", http.StatusBadRequest, w) return diff --git a/management/internals/modules/reverseproxy/manager/api.go b/management/internals/modules/reverseproxy/manager/api.go index d505b327a..efe088d4d 100644 --- a/management/internals/modules/reverseproxy/manager/api.go +++ b/management/internals/modules/reverseproxy/manager/api.go @@ -7,6 +7,8 @@ import ( "github.com/gorilla/mux" "github.com/netbirdio/netbird/management/internals/modules/reverseproxy" + "github.com/netbirdio/netbird/management/internals/modules/reverseproxy/accesslogs" + accesslogsmanager "github.com/netbirdio/netbird/management/internals/modules/reverseproxy/accesslogs/manager" "github.com/netbirdio/netbird/management/internals/modules/reverseproxy/domain" nbcontext "github.com/netbirdio/netbird/management/server/context" "github.com/netbirdio/netbird/shared/management/http/api" @@ -18,7 +20,7 @@ type handler struct { manager reverseproxy.Manager } -func RegisterEndpoints(manager reverseproxy.Manager, domainManager domain.Manager, router *mux.Router) { +func RegisterEndpoints(manager reverseproxy.Manager, domainManager domain.Manager, accessLogsManager accesslogs.Manager, router *mux.Router) { h := &handler{ manager: manager, } @@ -27,6 +29,8 @@ func RegisterEndpoints(manager reverseproxy.Manager, domainManager domain.Manage domainRouter := router.PathPrefix("/reverse-proxies").Subrouter() domain.RegisterEndpoints(domainRouter, domainManager) + accesslogsmanager.RegisterEndpoints(router, accessLogsManager) + router.HandleFunc("/reverse-proxies", h.getAllReverseProxies).Methods("GET", "OPTIONS") router.HandleFunc("/reverse-proxies", h.createReverseProxy).Methods("POST", "OPTIONS") router.HandleFunc("/reverse-proxies/{proxyId}", h.getReverseProxy).Methods("GET", "OPTIONS") @@ -62,7 +66,7 @@ func (h *handler) createReverseProxy(w http.ResponseWriter, r *http.Request) { return } - var req api.PostApiReverseProxyJSONRequestBody + var req api.ReverseProxyRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { util.WriteErrorResponse("couldn't parse JSON request", http.StatusBadRequest, w) return @@ -120,7 +124,7 @@ func (h *handler) updateReverseProxy(w http.ResponseWriter, r *http.Request) { return } - var req api.PutApiReverseProxyProxyIdJSONRequestBody + var req api.ReverseProxyRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { util.WriteErrorResponse("couldn't parse JSON request", http.StatusBadRequest, w) return diff --git a/management/internals/modules/reverseproxy/reverseproxy.go b/management/internals/modules/reverseproxy/reverseproxy.go index 8c47f25ee..7b14423bc 100644 --- a/management/internals/modules/reverseproxy/reverseproxy.go +++ b/management/internals/modules/reverseproxy/reverseproxy.go @@ -182,12 +182,13 @@ func (r *ReverseProxy) ToProtoMapping(operation Operation, setupKey string) *pro } return &proto.ProxyMapping{ - Type: operationToProtoType(operation), - Id: r.ID, - Domain: r.Domain, - Path: pathMappings, - SetupKey: setupKey, - Auth: auth, + Type: operationToProtoType(operation), + Id: r.ID, + Domain: r.Domain, + Path: pathMappings, + SetupKey: setupKey, + Auth: auth, + AccountId: r.AccountID, } } diff --git a/management/internals/server/boot.go b/management/internals/server/boot.go index 0c7f6c695..0c26e7d0a 100644 --- a/management/internals/server/boot.go +++ b/management/internals/server/boot.go @@ -21,6 +21,8 @@ import ( "github.com/netbirdio/management-integrations/integrations" "github.com/netbirdio/netbird/encryption" "github.com/netbirdio/netbird/formatter/hook" + "github.com/netbirdio/netbird/management/internals/modules/reverseproxy/accesslogs" + accesslogsmanager "github.com/netbirdio/netbird/management/internals/modules/reverseproxy/accesslogs/manager" nbgrpc "github.com/netbirdio/netbird/management/internals/shared/grpc" "github.com/netbirdio/netbird/management/server/activity" nbContext "github.com/netbirdio/netbird/management/server/context" @@ -92,7 +94,7 @@ func (s *BaseServer) EventStore() activity.Store { func (s *BaseServer) APIHandler() http.Handler { return Create(s, func() http.Handler { - httpAPIHandler, err := nbhttp.NewAPIHandler(context.Background(), s.AccountManager(), s.NetworksManager(), s.ResourcesManager(), s.RoutesManager(), s.GroupsManager(), s.GeoLocationManager(), s.AuthManager(), s.Metrics(), s.IntegratedValidator(), s.ProxyController(), s.PermissionsManager(), s.PeersManager(), s.SettingsManager(), s.ZonesManager(), s.RecordsManager(), s.NetworkMapController(), s.IdpManager(), s.ReverseProxyManager(), s.ReverseProxyDomainManager()) + httpAPIHandler, err := nbhttp.NewAPIHandler(context.Background(), s.AccountManager(), s.NetworksManager(), s.ResourcesManager(), s.RoutesManager(), s.GroupsManager(), s.GeoLocationManager(), s.AuthManager(), s.Metrics(), s.IntegratedValidator(), s.ProxyController(), s.PermissionsManager(), s.PeersManager(), s.SettingsManager(), s.ZonesManager(), s.RecordsManager(), s.NetworkMapController(), s.IdpManager(), s.ReverseProxyManager(), s.ReverseProxyDomainManager(), s.AccessLogsManager()) if err != nil { log.Fatalf("failed to create API handler: %v", err) } @@ -159,11 +161,18 @@ func (s *BaseServer) GRPCServer() *grpc.Server { func (s *BaseServer) ReverseProxyGRPCServer() *nbgrpc.ProxyServiceServer { return Create(s, func() *nbgrpc.ProxyServiceServer { - proxyService := nbgrpc.NewProxyServiceServer(s.Store(), s.AccountManager()) + proxyService := nbgrpc.NewProxyServiceServer(s.Store(), s.AccountManager(), s.AccessLogsManager()) return proxyService }) } +func (s *BaseServer) AccessLogsManager() accesslogs.Manager { + return Create(s, func() accesslogs.Manager { + accessLogManager := accesslogsmanager.NewManager(s.Store(), s.PermissionsManager(), s.GeoLocationManager()) + return accessLogManager + }) +} + func loadTLSConfig(certFile string, certKey string) (*tls.Config, error) { // Load server's certificate and private key serverCert, err := tls.LoadX509KeyPair(certFile, certKey) diff --git a/management/internals/shared/grpc/proxy.go b/management/internals/shared/grpc/proxy.go index 12f97289d..239f977d7 100644 --- a/management/internals/shared/grpc/proxy.go +++ b/management/internals/shared/grpc/proxy.go @@ -6,13 +6,15 @@ import ( "sync" "time" - "github.com/netbirdio/netbird/management/server/activity" log "github.com/sirupsen/logrus" "google.golang.org/grpc/codes" "google.golang.org/grpc/peer" "google.golang.org/grpc/status" + "github.com/netbirdio/netbird/management/server/activity" + "github.com/netbirdio/netbird/management/internals/modules/reverseproxy" + "github.com/netbirdio/netbird/management/internals/modules/reverseproxy/accesslogs" "github.com/netbirdio/netbird/management/server/store" "github.com/netbirdio/netbird/management/server/types" "github.com/netbirdio/netbird/shared/management/proto" @@ -21,6 +23,7 @@ import ( type reverseProxyStore interface { GetReverseProxies(ctx context.Context, lockStrength store.LockingStrength) ([]*reverseproxy.ReverseProxy, error) GetAccountReverseProxies(ctx context.Context, lockStrength store.LockingStrength, accountID string) ([]*reverseproxy.ReverseProxy, error) + GetReverseProxyByID(ctx context.Context, lockStrength store.LockingStrength, accountID string, serviceID string) (*reverseproxy.ReverseProxy, error) } type keyStore interface { @@ -43,6 +46,9 @@ type ProxyServiceServer struct { // Store for client setup keys keyStore keyStore + + // Manager for access logs + accessLogManager accesslogs.Manager } // proxyConnection represents a connected proxy @@ -56,11 +62,12 @@ type proxyConnection struct { } // NewProxyServiceServer creates a new proxy service server -func NewProxyServiceServer(store reverseProxyStore, keys keyStore) *ProxyServiceServer { +func NewProxyServiceServer(store reverseProxyStore, keys keyStore, accessLogMgr accesslogs.Manager) *ProxyServiceServer { return &ProxyServiceServer{ updatesChan: make(chan *proto.ProxyMapping, 100), reverseProxyStore: store, keyStore: keys, + accessLogManager: accessLogMgr, } } @@ -186,21 +193,30 @@ func (s *ProxyServiceServer) sender(conn *proxyConnection, errChan chan<- error) // SendAccessLog processes access log from proxy func (s *ProxyServiceServer) SendAccessLog(ctx context.Context, req *proto.SendAccessLogRequest) (*proto.SendAccessLogResponse, error) { - log.WithFields(log.Fields{ - "proxy_id": "", // TODO: get proxy id, probably from context or maybe from request message. - "reverse_proxy_id": req.GetLog().GetServiceId(), - "host": req.GetLog().GetHost(), - "path": req.GetLog().GetPath(), - "method": req.GetLog().GetMethod(), - "response_code": req.GetLog().GetResponseCode(), - "duration_ms": req.GetLog().GetDurationMs(), - "source_ip": req.GetLog().GetSourceIp(), - "auth_mechanism": req.GetLog().GetAuthMechanism(), - "user_id": req.GetLog().GetUserId(), - "auth_success": req.GetLog().GetAuthSuccess(), - }).Info("Access log from proxy") + accessLog := req.GetLog() + + log.WithFields(log.Fields{ + "reverse_proxy_id": accessLog.GetServiceId(), + "account_id": accessLog.GetAccountId(), + "host": accessLog.GetHost(), + "path": accessLog.GetPath(), + "method": accessLog.GetMethod(), + "response_code": accessLog.GetResponseCode(), + "duration_ms": accessLog.GetDurationMs(), + "source_ip": accessLog.GetSourceIp(), + "auth_mechanism": accessLog.GetAuthMechanism(), + "user_id": accessLog.GetUserId(), + "auth_success": accessLog.GetAuthSuccess(), + }).Debug("Access log from proxy") + + logEntry := &accesslogs.AccessLogEntry{} + logEntry.FromProto(accessLog) + + if err := s.accessLogManager.SaveAccessLog(ctx, logEntry); err != nil { + log.WithContext(ctx).Errorf("failed to save access log: %v", err) + return nil, status.Errorf(codes.Internal, "failed to save access log: %v", err) + } - // TODO: Store access log in database/metrics system return &proto.SendAccessLogResponse{}, nil } diff --git a/management/server/http/handler.go b/management/server/http/handler.go index 0416a2ad4..2aed06fa4 100644 --- a/management/server/http/handler.go +++ b/management/server/http/handler.go @@ -13,6 +13,7 @@ import ( log "github.com/sirupsen/logrus" "github.com/netbirdio/netbird/management/internals/modules/reverseproxy" + "github.com/netbirdio/netbird/management/internals/modules/reverseproxy/accesslogs" "github.com/netbirdio/netbird/management/internals/modules/reverseproxy/domain" reverseproxymanager "github.com/netbirdio/netbird/management/internals/modules/reverseproxy/manager" idpmanager "github.com/netbirdio/netbird/management/server/idp" @@ -63,7 +64,7 @@ const ( ) // NewAPIHandler creates the Management service HTTP API handler registering all the available endpoints. -func NewAPIHandler(ctx context.Context, accountManager account.Manager, networksManager nbnetworks.Manager, resourceManager resources.Manager, routerManager routers.Manager, groupsManager nbgroups.Manager, LocationManager geolocation.Geolocation, authManager auth.Manager, appMetrics telemetry.AppMetrics, integratedValidator integrated_validator.IntegratedValidator, proxyController port_forwarding.Controller, permissionsManager permissions.Manager, peersManager nbpeers.Manager, settingsManager settings.Manager, zManager zones.Manager, rManager records.Manager, networkMapController network_map.Controller, idpManager idpmanager.Manager, reverseProxyManager reverseproxy.Manager, reverseProxyDomainManager domain.Manager) (http.Handler, error) { +func NewAPIHandler(ctx context.Context, accountManager account.Manager, networksManager nbnetworks.Manager, resourceManager resources.Manager, routerManager routers.Manager, groupsManager nbgroups.Manager, LocationManager geolocation.Geolocation, authManager auth.Manager, appMetrics telemetry.AppMetrics, integratedValidator integrated_validator.IntegratedValidator, proxyController port_forwarding.Controller, permissionsManager permissions.Manager, peersManager nbpeers.Manager, settingsManager settings.Manager, zManager zones.Manager, rManager records.Manager, networkMapController network_map.Controller, idpManager idpmanager.Manager, reverseProxyManager reverseproxy.Manager, reverseProxyDomainManager domain.Manager, reverseProxyAccessLogsManager accesslogs.Manager) (http.Handler, error) { // Register bypass paths for unauthenticated endpoints if err := bypass.AddBypassPath("/api/instance"); err != nil { @@ -159,7 +160,7 @@ func NewAPIHandler(ctx context.Context, accountManager account.Manager, networks idp.AddEndpoints(accountManager, router) instance.AddEndpoints(instanceManager, router) instance.AddVersionEndpoint(instanceManager, router) - reverseproxymanager.RegisterEndpoints(reverseProxyManager, reverseProxyDomainManager, router) + reverseproxymanager.RegisterEndpoints(reverseProxyManager, reverseProxyDomainManager, reverseProxyAccessLogsManager, router) // Mount embedded IdP handler at /oauth2 path if configured if embeddedIdpEnabled { diff --git a/management/server/store/sql_store.go b/management/server/store/sql_store.go index df63482dc..d84abe3cf 100644 --- a/management/server/store/sql_store.go +++ b/management/server/store/sql_store.go @@ -29,6 +29,7 @@ import ( nbdns "github.com/netbirdio/netbird/dns" "github.com/netbirdio/netbird/management/internals/modules/reverseproxy" + "github.com/netbirdio/netbird/management/internals/modules/reverseproxy/accesslogs" "github.com/netbirdio/netbird/management/internals/modules/reverseproxy/domain" "github.com/netbirdio/netbird/management/internals/modules/zones" "github.com/netbirdio/netbird/management/internals/modules/zones/records" @@ -130,6 +131,7 @@ func NewSqlStore(ctx context.Context, db *gorm.DB, storeEngine types.Engine, met &installation{}, &types.ExtraSettings{}, &posture.Checks{}, &nbpeer.NetworkAddress{}, &networkTypes.Network{}, &routerTypes.NetworkRouter{}, &resourceTypes.NetworkResource{}, &types.AccountOnboarding{}, &types.Job{}, &zones.Zone{}, &records.Record{}, &types.UserInviteRecord{}, &reverseproxy.ReverseProxy{}, &domain.Domain{}, + &accesslogs.AccessLogEntry{}, ) if err != nil { return nil, fmt.Errorf("auto migratePreAuto: %w", err) @@ -4782,3 +4784,40 @@ func (s *SqlStore) DeleteCustomDomain(ctx context.Context, accountID string, dom return nil } + +// CreateAccessLog creates a new access log entry in the database +func (s *SqlStore) CreateAccessLog(ctx context.Context, logEntry *accesslogs.AccessLogEntry) error { + result := s.db.Create(logEntry) + if result.Error != nil { + log.WithContext(ctx).WithFields(log.Fields{ + "proxy_id": logEntry.ProxyID, + "method": logEntry.Method, + "host": logEntry.Host, + "path": logEntry.Path, + }).Errorf("failed to create access log entry in store: %v", result.Error) + return status.Errorf(status.Internal, "failed to create access log entry in store") + } + return nil +} + +// GetAccountAccessLogs retrieves all access logs for a given account +func (s *SqlStore) GetAccountAccessLogs(ctx context.Context, lockStrength LockingStrength, accountID string) ([]*accesslogs.AccessLogEntry, error) { + var logs []*accesslogs.AccessLogEntry + + query := s.db.WithContext(ctx). + Where(accountIDCondition, accountID). + Order("timestamp DESC"). + Limit(1000) + + if lockStrength != LockingStrengthNone { + query = query.Clauses(clause.Locking{Strength: string(lockStrength)}) + } + + result := query.Find(&logs) + if result.Error != nil { + log.WithContext(ctx).Errorf("failed to get access logs from store: %v", result.Error) + return nil, status.Errorf(status.Internal, "failed to get access logs from store") + } + + return logs, nil +} diff --git a/management/server/store/store.go b/management/server/store/store.go index 01f04f5b0..ce27ab9e2 100644 --- a/management/server/store/store.go +++ b/management/server/store/store.go @@ -24,6 +24,7 @@ import ( "github.com/netbirdio/netbird/dns" "github.com/netbirdio/netbird/management/internals/modules/reverseproxy" + "github.com/netbirdio/netbird/management/internals/modules/reverseproxy/accesslogs" "github.com/netbirdio/netbird/management/internals/modules/reverseproxy/domain" "github.com/netbirdio/netbird/management/internals/modules/zones" "github.com/netbirdio/netbird/management/internals/modules/zones/records" @@ -257,6 +258,9 @@ type Store interface { CreateCustomDomain(ctx context.Context, accountID string, domainName string, validated bool) (*domain.Domain, error) UpdateCustomDomain(ctx context.Context, accountID string, d *domain.Domain) (*domain.Domain, error) DeleteCustomDomain(ctx context.Context, accountID string, domainID string) error + + CreateAccessLog(ctx context.Context, log *accesslogs.AccessLogEntry) error + GetAccountAccessLogs(ctx context.Context, lockStrength LockingStrength, accountID string) ([]*accesslogs.AccessLogEntry, error) } const ( diff --git a/proxy/internal/accesslog/logger.go b/proxy/internal/accesslog/logger.go index dc43007e0..64bf47cd1 100644 --- a/proxy/internal/accesslog/logger.go +++ b/proxy/internal/accesslog/logger.go @@ -25,6 +25,8 @@ func NewLogger(client gRPCClient) *Logger { } type logEntry struct { + ID string + AccountID string ServiceId string Host string Path string @@ -50,6 +52,8 @@ func (l *Logger) log(ctx context.Context, entry logEntry) { go func() { if _, err := l.client.SendAccessLog(context.Background(), &proto.SendAccessLogRequest{ Log: &proto.AccessLog{ + LogId: entry.ID, + AccountId: entry.AccountID, Timestamp: now, ServiceId: entry.ServiceId, Host: entry.Host, diff --git a/proxy/internal/accesslog/middleware.go b/proxy/internal/accesslog/middleware.go index e119f95ef..13f0029a4 100644 --- a/proxy/internal/accesslog/middleware.go +++ b/proxy/internal/accesslog/middleware.go @@ -5,6 +5,8 @@ import ( "net/http" "time" + "github.com/rs/xid" + "github.com/netbirdio/netbird/proxy/internal/auth" "github.com/netbirdio/netbird/proxy/internal/proxy" ) @@ -31,8 +33,10 @@ func (l *Logger) Middleware(next http.Handler) http.Handler { host = r.Host } - l.log(r.Context(), logEntry{ + entry := logEntry{ + ID: xid.New().String(), ServiceId: proxy.ServiceIdFromContext(r.Context()), + AccountID: proxy.AccountIdFromContext(r.Context()), Host: host, Path: r.URL.Path, DurationMs: duration.Milliseconds(), @@ -42,6 +46,7 @@ func (l *Logger) Middleware(next http.Handler) http.Handler { AuthMechanism: auth.MethodFromContext(r.Context()).String(), UserId: auth.UserFromContext(r.Context()), AuthSuccess: sw.status != http.StatusUnauthorized && sw.status != http.StatusForbidden, - }) + } + l.log(r.Context(), entry) }) } diff --git a/proxy/internal/proxy/context.go b/proxy/internal/proxy/context.go index c37106ade..2aa4d699b 100644 --- a/proxy/internal/proxy/context.go +++ b/proxy/internal/proxy/context.go @@ -2,14 +2,54 @@ package proxy import ( "context" + "sync" ) type requestContextKey string const ( - serviceIdKey requestContextKey = "serviceId" + serviceIdKey requestContextKey = "serviceId" + accountIdKey requestContextKey = "accountId" + capturedDataKey requestContextKey = "capturedData" ) +// CapturedData is a mutable struct that allows downstream handlers +// to pass data back up the middleware chain. +type CapturedData struct { + mu sync.RWMutex + ServiceId string + AccountId string +} + +// SetServiceId safely sets the service ID +func (c *CapturedData) SetServiceId(serviceId string) { + c.mu.Lock() + defer c.mu.Unlock() + c.ServiceId = serviceId +} + +// SetAccountId safely sets the account ID +func (c *CapturedData) SetAccountId(accountId string) { + c.mu.Lock() + defer c.mu.Unlock() + c.AccountId = accountId +} + +// WithCapturedData adds a CapturedData struct to the context +func WithCapturedData(ctx context.Context, data *CapturedData) context.Context { + return context.WithValue(ctx, capturedDataKey, data) +} + +// CapturedDataFromContext retrieves the CapturedData from context +func CapturedDataFromContext(ctx context.Context) *CapturedData { + v := ctx.Value(capturedDataKey) + data, ok := v.(*CapturedData) + if !ok { + return nil + } + return data +} + func withServiceId(ctx context.Context, serviceId string) context.Context { return context.WithValue(ctx, serviceIdKey, serviceId) } @@ -22,3 +62,15 @@ func ServiceIdFromContext(ctx context.Context) string { } return serviceId } +func withAccountId(ctx context.Context, accountId string) context.Context { + return context.WithValue(ctx, accountIdKey, accountId) +} + +func AccountIdFromContext(ctx context.Context) string { + v := ctx.Value(accountIdKey) + accountId, ok := v.(string) + if !ok { + return "" + } + return accountId +} diff --git a/proxy/internal/proxy/reverseproxy.go b/proxy/internal/proxy/reverseproxy.go index 13e1f1f53..a06699653 100644 --- a/proxy/internal/proxy/reverseproxy.go +++ b/proxy/internal/proxy/reverseproxy.go @@ -26,7 +26,7 @@ func NewReverseProxy(transport http.RoundTripper) *ReverseProxy { } func (p *ReverseProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) { - target, serviceId, exists := p.findTargetForRequest(r) + target, serviceId, accountID, exists := p.findTargetForRequest(r) if !exists { // No mapping found so return an error here. // TODO: prettier error page. @@ -36,6 +36,8 @@ func (p *ReverseProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) { // Set the serviceId in the context for later retrieval. ctx := withServiceId(r.Context(), serviceId) + // Set the accountId in the context for later retrieval. + ctx = withAccountId(ctx, accountID) // Set up a reverse proxy using the transport and then use it to serve the request. proxy := httputil.NewSingleHostReverseProxy(target) diff --git a/proxy/internal/proxy/servicemapping.go b/proxy/internal/proxy/servicemapping.go index 12dd5f1fc..0fc1dbb57 100644 --- a/proxy/internal/proxy/servicemapping.go +++ b/proxy/internal/proxy/servicemapping.go @@ -8,12 +8,13 @@ import ( ) type Mapping struct { - ID string - Host string - Paths map[string]*url.URL + ID string + AccountID string + Host string + Paths map[string]*url.URL } -func (p *ReverseProxy) findTargetForRequest(req *http.Request) (*url.URL, string, bool) { +func (p *ReverseProxy) findTargetForRequest(req *http.Request) (*url.URL, string, string, bool) { p.mappingsMux.RLock() if p.mappings == nil { p.mappingsMux.RUnlock() @@ -21,12 +22,12 @@ func (p *ReverseProxy) findTargetForRequest(req *http.Request) (*url.URL, string defer p.mappingsMux.Unlock() p.mappings = make(map[string]Mapping) // There cannot be any loaded Mappings as we have only just initialized. - return nil, "", false + return nil, "", "", false } defer p.mappingsMux.RUnlock() m, exists := p.mappings[req.Host] if !exists { - return nil, "", false + return nil, "", "", false } // Sort paths by length (longest first) in a naive attempt to match the most specific route first. @@ -40,10 +41,10 @@ func (p *ReverseProxy) findTargetForRequest(req *http.Request) (*url.URL, string for _, path := range paths { if strings.HasPrefix(req.URL.Path, path) { - return m.Paths[path], m.ID, true + return m.Paths[path], m.ID, m.AccountID, true } } - return nil, "", false + return nil, "", "", false } func (p *ReverseProxy) AddMapping(m Mapping) { diff --git a/proxy/internal/roundtrip/netbird.go b/proxy/internal/roundtrip/netbird.go index de907e397..e01501dc3 100644 --- a/proxy/internal/roundtrip/netbird.go +++ b/proxy/internal/roundtrip/netbird.go @@ -3,12 +3,14 @@ package roundtrip import ( "context" "fmt" + "io" "net/http" "sync" "time" - "github.com/netbirdio/netbird/client/embed" log "github.com/sirupsen/logrus" + + "github.com/netbirdio/netbird/client/embed" ) const deviceNamePrefix = "ingress-" @@ -34,6 +36,7 @@ func (n *NetBird) AddPeer(ctx context.Context, domain, key string) error { DeviceName: deviceNamePrefix + domain, ManagementURL: n.mgmtAddr, SetupKey: key, + LogOutput: io.Discard, }) if err != nil { return fmt.Errorf("create netbird client: %w", err) diff --git a/proxy/server.go b/proxy/server.go index 787d3343b..ae95546c2 100644 --- a/proxy/server.go +++ b/proxy/server.go @@ -334,6 +334,7 @@ func (s *Server) protoToMapping(mapping *proto.ProxyMapping) proxy.Mapping { // TODO: Should we warn management about this so it can be bubbled up to a user to reconfigure? log.WithFields(log.Fields{ "service_id": mapping.GetId(), + "account_id": mapping.GetAccountId(), "domain": mapping.GetDomain(), "path": pathMapping.GetPath(), "target": pathMapping.GetTarget(), @@ -343,8 +344,9 @@ func (s *Server) protoToMapping(mapping *proto.ProxyMapping) proxy.Mapping { paths[pathMapping.GetPath()] = targetURL } return proxy.Mapping{ - ID: mapping.GetId(), - Host: mapping.GetDomain(), - Paths: paths, + ID: mapping.GetId(), + AccountID: mapping.AccountId, + Host: mapping.GetDomain(), + Paths: paths, } } diff --git a/shared/management/http/api/openapi.yml b/shared/management/http/api/openapi.yml index 6e95b6980..573924a44 100644 --- a/shared/management/http/api/openapi.yml +++ b/shared/management/http/api/openapi.yml @@ -2699,6 +2699,75 @@ components: - page_size - total_records - total_pages + ProxyAccessLog: + type: object + properties: + id: + type: string + description: "Unique identifier for the access log entry" + example: "ch8i4ug6lnn4g9hqv7m0" + proxy_id: + type: string + description: "ID of the reverse proxy that handled the request" + example: "ch8i4ug6lnn4g9hqv7m0" + timestamp: + type: string + format: date-time + description: "Timestamp when the request was made" + example: "2024-01-31T15:30:00Z" + method: + type: string + description: "HTTP method of the request" + example: "GET" + host: + type: string + description: "Host header of the request" + example: "example.com" + path: + type: string + description: "Path of the request" + example: "/api/users" + duration_ms: + type: integer + description: "Duration of the request in milliseconds" + example: 150 + status_code: + type: integer + description: "HTTP status code returned" + example: 200 + source_ip: + type: string + description: "Source IP address of the request" + example: "192.168.1.100" + reason: + type: string + description: "Reason for the request result (e.g., authentication failure)" + example: "Authentication failed" + user_id: + type: string + description: "ID of the authenticated user, if applicable" + example: "user-123" + auth_method_used: + type: string + description: "Authentication method used (e.g., password, pin, oidc)" + example: "oidc" + country_code: + type: string + description: "Country code from geolocation" + example: "US" + city_name: + type: string + description: "City name from geolocation" + example: "San Francisco" + required: + - id + - proxy_id + - timestamp + - method + - host + - path + - duration_ms + - status_code IdentityProviderType: type: string description: Type of identity provider @@ -6197,6 +6266,26 @@ paths: "$ref": "#/components/responses/forbidden" '500': "$ref": "#/components/responses/internal_error" + /api/events/proxy: + get: + summary: List all Reverse Proxy Access Logs + description: Returns a list of all reverse proxy access log entries + tags: [ Events ] + responses: + "200": + description: List of reverse proxy access logs + content: + application/json: + schema: + type: array + items: + $ref: "#/components/schemas/ProxyAccessLog" + '401': + "$ref": "#/components/responses/requires_authentication" + '403': + "$ref": "#/components/responses/forbidden" + '500': + "$ref": "#/components/responses/internal_error" /api/posture-checks: get: summary: List all Posture Checks diff --git a/shared/management/http/api/types.gen.go b/shared/management/http/api/types.gen.go index d006d81b1..2290e7e1f 100644 --- a/shared/management/http/api/types.gen.go +++ b/shared/management/http/api/types.gen.go @@ -1892,6 +1892,51 @@ type ProcessCheck struct { Processes []Process `json:"processes"` } +// ProxyAccessLog defines model for ProxyAccessLog. +type ProxyAccessLog struct { + // AuthMethodUsed Authentication method used (e.g., password, pin, oidc) + AuthMethodUsed *string `json:"auth_method_used,omitempty"` + + // CityName City name from geolocation + CityName *string `json:"city_name,omitempty"` + + // CountryCode Country code from geolocation + CountryCode *string `json:"country_code,omitempty"` + + // DurationMs Duration of the request in milliseconds + DurationMs int `json:"duration_ms"` + + // Host Host header of the request + Host string `json:"host"` + + // Id Unique identifier for the access log entry + Id string `json:"id"` + + // Method HTTP method of the request + Method string `json:"method"` + + // Path Path of the request + Path string `json:"path"` + + // ProxyId ID of the reverse proxy that handled the request + ProxyId string `json:"proxy_id"` + + // Reason Reason for the request result (e.g., authentication failure) + Reason *string `json:"reason,omitempty"` + + // SourceIp Source IP address of the request + SourceIp *string `json:"source_ip,omitempty"` + + // StatusCode HTTP status code returned + StatusCode int `json:"status_code"` + + // Timestamp Timestamp when the request was made + Timestamp time.Time `json:"timestamp"` + + // UserId ID of the authenticated user, if applicable + UserId *string `json:"user_id,omitempty"` +} + // Resource defines model for Resource. type Resource struct { // Id ID of the resource @@ -2665,14 +2710,14 @@ type PostApiPostureChecksJSONRequestBody = PostureCheckUpdate // PutApiPostureChecksPostureCheckIdJSONRequestBody defines body for PutApiPostureChecksPostureCheckId for application/json ContentType. type PutApiPostureChecksPostureCheckIdJSONRequestBody = PostureCheckUpdate -// PostApiReverseProxyJSONRequestBody defines body for PostApiReverseProxy for application/json ContentType. -type PostApiReverseProxyJSONRequestBody = ReverseProxyRequest +// PostApiReverseProxiesJSONRequestBody defines body for PostApiReverseProxies for application/json ContentType. +type PostApiReverseProxiesJSONRequestBody = ReverseProxyRequest -// PostApiReverseProxyDomainsJSONRequestBody defines body for PostApiReverseProxyDomains for application/json ContentType. -type PostApiReverseProxyDomainsJSONRequestBody = ReverseProxyDomainRequest +// PostApiReverseProxiesDomainsJSONRequestBody defines body for PostApiReverseProxiesDomains for application/json ContentType. +type PostApiReverseProxiesDomainsJSONRequestBody = ReverseProxyDomainRequest -// PutApiReverseProxyProxyIdJSONRequestBody defines body for PutApiReverseProxyProxyId for application/json ContentType. -type PutApiReverseProxyProxyIdJSONRequestBody = ReverseProxyRequest +// PutApiReverseProxiesProxyIdJSONRequestBody defines body for PutApiReverseProxiesProxyId for application/json ContentType. +type PutApiReverseProxiesProxyIdJSONRequestBody = ReverseProxyRequest // PostApiRoutesJSONRequestBody defines body for PostApiRoutes for application/json ContentType. type PostApiRoutesJSONRequestBody = RouteRequest diff --git a/shared/management/proto/proxy_service.pb.go b/shared/management/proto/proxy_service.pb.go index e159a1e1f..7b04c1bf4 100644 --- a/shared/management/proto/proxy_service.pb.go +++ b/shared/management/proto/proxy_service.pb.go @@ -247,6 +247,7 @@ type Authentication struct { Password *Password `protobuf:"bytes,1,opt,name=password,proto3" json:"password,omitempty"` Pin *Pin `protobuf:"bytes,2,opt,name=pin,proto3" json:"pin,omitempty"` Oidc *OIDC `protobuf:"bytes,3,opt,name=oidc,proto3" json:"oidc,omitempty"` + Link *Link `protobuf:"bytes,4,opt,name=link,proto3" json:"link,omitempty"` } func (x *Authentication) Reset() { @@ -302,6 +303,13 @@ func (x *Authentication) GetOidc() *OIDC { return nil } +func (x *Authentication) GetLink() *Link { + if x != nil { + return x.Link + } + return nil +} + type Password struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -567,12 +575,13 @@ type ProxyMapping struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Type ProxyMappingUpdateType `protobuf:"varint,1,opt,name=type,proto3,enum=management.ProxyMappingUpdateType" json:"type,omitempty"` - Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"` - Domain string `protobuf:"bytes,3,opt,name=domain,proto3" json:"domain,omitempty"` - Path []*PathMapping `protobuf:"bytes,4,rep,name=path,proto3" json:"path,omitempty"` - SetupKey string `protobuf:"bytes,5,opt,name=setup_key,json=setupKey,proto3" json:"setup_key,omitempty"` - Auth *Authentication `protobuf:"bytes,6,opt,name=auth,proto3" json:"auth,omitempty"` + Type ProxyMappingUpdateType `protobuf:"varint,1,opt,name=type,proto3,enum=management.ProxyMappingUpdateType" json:"type,omitempty"` + Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"` + AccountId string `protobuf:"bytes,3,opt,name=account_id,json=accountId,proto3" json:"account_id,omitempty"` + Domain string `protobuf:"bytes,4,opt,name=domain,proto3" json:"domain,omitempty"` + Path []*PathMapping `protobuf:"bytes,5,rep,name=path,proto3" json:"path,omitempty"` + SetupKey string `protobuf:"bytes,6,opt,name=setup_key,json=setupKey,proto3" json:"setup_key,omitempty"` + Auth *Authentication `protobuf:"bytes,7,opt,name=auth,proto3" json:"auth,omitempty"` } func (x *ProxyMapping) Reset() { @@ -621,6 +630,13 @@ func (x *ProxyMapping) GetId() string { return "" } +func (x *ProxyMapping) GetAccountId() string { + if x != nil { + return x.AccountId + } + return "" +} + func (x *ProxyMapping) GetDomain() string { if x != nil { return x.Domain @@ -742,16 +758,18 @@ type AccessLog struct { unknownFields protoimpl.UnknownFields Timestamp *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` - ServiceId string `protobuf:"bytes,2,opt,name=service_id,json=serviceId,proto3" json:"service_id,omitempty"` - Host string `protobuf:"bytes,3,opt,name=host,proto3" json:"host,omitempty"` - Path string `protobuf:"bytes,4,opt,name=path,proto3" json:"path,omitempty"` - DurationMs int64 `protobuf:"varint,5,opt,name=duration_ms,json=durationMs,proto3" json:"duration_ms,omitempty"` - Method string `protobuf:"bytes,6,opt,name=method,proto3" json:"method,omitempty"` - ResponseCode int32 `protobuf:"varint,7,opt,name=response_code,json=responseCode,proto3" json:"response_code,omitempty"` - SourceIp string `protobuf:"bytes,8,opt,name=source_ip,json=sourceIp,proto3" json:"source_ip,omitempty"` - AuthMechanism string `protobuf:"bytes,9,opt,name=auth_mechanism,json=authMechanism,proto3" json:"auth_mechanism,omitempty"` - UserId string `protobuf:"bytes,10,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - AuthSuccess bool `protobuf:"varint,11,opt,name=auth_success,json=authSuccess,proto3" json:"auth_success,omitempty"` + LogId string `protobuf:"bytes,2,opt,name=log_id,json=logId,proto3" json:"log_id,omitempty"` + AccountId string `protobuf:"bytes,3,opt,name=account_id,json=accountId,proto3" json:"account_id,omitempty"` + ServiceId string `protobuf:"bytes,4,opt,name=service_id,json=serviceId,proto3" json:"service_id,omitempty"` + Host string `protobuf:"bytes,5,opt,name=host,proto3" json:"host,omitempty"` + Path string `protobuf:"bytes,6,opt,name=path,proto3" json:"path,omitempty"` + DurationMs int64 `protobuf:"varint,7,opt,name=duration_ms,json=durationMs,proto3" json:"duration_ms,omitempty"` + Method string `protobuf:"bytes,8,opt,name=method,proto3" json:"method,omitempty"` + ResponseCode int32 `protobuf:"varint,9,opt,name=response_code,json=responseCode,proto3" json:"response_code,omitempty"` + SourceIp string `protobuf:"bytes,10,opt,name=source_ip,json=sourceIp,proto3" json:"source_ip,omitempty"` + AuthMechanism string `protobuf:"bytes,11,opt,name=auth_mechanism,json=authMechanism,proto3" json:"auth_mechanism,omitempty"` + UserId string `protobuf:"bytes,12,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + AuthSuccess bool `protobuf:"varint,13,opt,name=auth_success,json=authSuccess,proto3" json:"auth_success,omitempty"` } func (x *AccessLog) Reset() { @@ -793,6 +811,20 @@ func (x *AccessLog) GetTimestamp() *timestamppb.Timestamp { return nil } +func (x *AccessLog) GetLogId() string { + if x != nil { + return x.LogId + } + return "" +} + +func (x *AccessLog) GetAccountId() string { + if x != nil { + return x.AccountId + } + return "" +} + func (x *AccessLog) GetServiceId() string { if x != nil { return x.ServiceId @@ -887,7 +919,7 @@ var file_proxy_service_proto_rawDesc = []byte{ 0x0a, 0x0b, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0x8b, 0x01, 0x0a, 0x0e, 0x41, 0x75, + 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0xb1, 0x01, 0x0a, 0x0e, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x30, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x61, 0x73, 0x73, @@ -896,99 +928,107 @@ var file_proxy_service_proto_rawDesc = []byte{ 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x69, 0x6e, 0x52, 0x03, 0x70, 0x69, 0x6e, 0x12, 0x24, 0x0a, 0x04, 0x6f, 0x69, 0x64, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x4f, 0x49, 0x44, - 0x43, 0x52, 0x04, 0x6f, 0x69, 0x64, 0x63, 0x22, 0x40, 0x0a, 0x08, 0x50, 0x61, 0x73, 0x73, 0x77, - 0x6f, 0x72, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1a, 0x0a, - 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x31, 0x0a, 0x03, 0x50, 0x69, 0x6e, - 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, - 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x70, 0x69, 0x6e, 0x22, 0x3b, 0x0a, 0x04, - 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x19, - 0x0a, 0x08, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x6c, 0x69, 0x6e, 0x6b, 0x55, 0x72, 0x6c, 0x22, 0x9d, 0x02, 0x0a, 0x04, 0x4f, 0x49, - 0x44, 0x43, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x2a, 0x0a, 0x11, - 0x6f, 0x69, 0x64, 0x63, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x75, 0x72, - 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6f, 0x69, 0x64, 0x63, 0x50, 0x72, 0x6f, - 0x76, 0x69, 0x64, 0x65, 0x72, 0x55, 0x72, 0x6c, 0x12, 0x24, 0x0a, 0x0e, 0x6f, 0x69, 0x64, 0x63, - 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0c, 0x6f, 0x69, 0x64, 0x63, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x2c, - 0x0a, 0x12, 0x6f, 0x69, 0x64, 0x63, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, - 0x63, 0x72, 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6f, 0x69, 0x64, 0x63, - 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x2a, 0x0a, 0x11, - 0x6f, 0x69, 0x64, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5f, 0x75, 0x72, - 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6f, 0x69, 0x64, 0x63, 0x52, 0x65, 0x64, - 0x69, 0x72, 0x65, 0x63, 0x74, 0x55, 0x72, 0x6c, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x69, 0x64, 0x63, - 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x6f, - 0x69, 0x64, 0x63, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x73, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, - 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xe8, 0x01, 0x0a, 0x0c, 0x50, 0x72, - 0x6f, 0x78, 0x79, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x36, 0x0a, 0x04, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, - 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x61, 0x70, 0x70, 0x69, - 0x6e, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, - 0x70, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, - 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x2b, 0x0a, 0x04, 0x70, 0x61, - 0x74, 0x68, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, - 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, - 0x67, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x65, 0x74, 0x75, 0x70, - 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x74, 0x75, - 0x70, 0x4b, 0x65, 0x79, 0x12, 0x2e, 0x0a, 0x04, 0x61, 0x75, 0x74, 0x68, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, - 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x04, - 0x61, 0x75, 0x74, 0x68, 0x22, 0x3f, 0x0a, 0x14, 0x53, 0x65, 0x6e, 0x64, 0x41, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x03, - 0x6c, 0x6f, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x61, 0x6e, 0x61, - 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, - 0x52, 0x03, 0x6c, 0x6f, 0x67, 0x22, 0x17, 0x0a, 0x15, 0x53, 0x65, 0x6e, 0x64, 0x41, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xea, - 0x02, 0x0a, 0x09, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x12, 0x38, 0x0a, 0x09, - 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, - 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1f, 0x0a, - 0x0b, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x0a, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x73, 0x12, 0x16, - 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x72, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x70, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x70, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x75, 0x74, 0x68, - 0x5f, 0x6d, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x6d, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0d, 0x61, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x6d, 0x12, - 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x75, 0x74, 0x68, - 0x5f, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, - 0x61, 0x75, 0x74, 0x68, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x2a, 0x64, 0x0a, 0x16, 0x50, - 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x17, 0x0a, 0x13, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, - 0x54, 0x59, 0x50, 0x45, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, - 0x0a, 0x14, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x4f, - 0x44, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x55, 0x50, 0x44, 0x41, - 0x54, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x4d, 0x4f, 0x56, 0x45, 0x44, 0x10, - 0x02, 0x32, 0xc5, 0x01, 0x0a, 0x0c, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x12, 0x5f, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x23, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, + 0x43, 0x52, 0x04, 0x6f, 0x69, 0x64, 0x63, 0x12, 0x24, 0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, + 0x6e, 0x74, 0x2e, 0x4c, 0x69, 0x6e, 0x6b, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x22, 0x40, 0x0a, + 0x08, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, + 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, + 0x6c, 0x65, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, + 0x31, 0x0a, 0x03, 0x50, 0x69, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, + 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x70, + 0x69, 0x6e, 0x22, 0x3b, 0x0a, 0x04, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, + 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, + 0x62, 0x6c, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x75, 0x72, 0x6c, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6c, 0x69, 0x6e, 0x6b, 0x55, 0x72, 0x6c, 0x22, + 0x9d, 0x02, 0x0a, 0x04, 0x4f, 0x49, 0x44, 0x43, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, + 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, + 0x65, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x6f, 0x69, 0x64, 0x63, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, + 0x64, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6f, + 0x69, 0x64, 0x63, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x55, 0x72, 0x6c, 0x12, 0x24, + 0x0a, 0x0e, 0x6f, 0x69, 0x64, 0x63, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6f, 0x69, 0x64, 0x63, 0x43, 0x6c, 0x69, 0x65, + 0x6e, 0x74, 0x49, 0x64, 0x12, 0x2c, 0x0a, 0x12, 0x6f, 0x69, 0x64, 0x63, 0x5f, 0x63, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x10, 0x6f, 0x69, 0x64, 0x63, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x63, 0x72, + 0x65, 0x74, 0x12, 0x2a, 0x0a, 0x11, 0x6f, 0x69, 0x64, 0x63, 0x5f, 0x72, 0x65, 0x64, 0x69, 0x72, + 0x65, 0x63, 0x74, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6f, + 0x69, 0x64, 0x63, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x55, 0x72, 0x6c, 0x12, 0x1f, + 0x0a, 0x0b, 0x6f, 0x69, 0x64, 0x63, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x18, 0x06, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x0a, 0x6f, 0x69, 0x64, 0x63, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x12, + 0x2e, 0x0a, 0x13, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6f, 0x6b, 0x69, + 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x73, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x22, + 0x87, 0x02, 0x0a, 0x0c, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, + 0x12, 0x36, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, + 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x72, 0x6f, 0x78, + 0x79, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x79, + 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, + 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, + 0x2b, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, + 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x4d, + 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1b, 0x0a, 0x09, + 0x73, 0x65, 0x74, 0x75, 0x70, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x73, 0x65, 0x74, 0x75, 0x70, 0x4b, 0x65, 0x79, 0x12, 0x2e, 0x0a, 0x04, 0x61, 0x75, 0x74, + 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, + 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x61, 0x75, 0x74, 0x68, 0x22, 0x3f, 0x0a, 0x14, 0x53, 0x65, 0x6e, + 0x64, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x27, 0x0a, 0x03, 0x6c, 0x6f, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, + 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x52, 0x03, 0x6c, 0x6f, 0x67, 0x22, 0x17, 0x0a, 0x15, 0x53, 0x65, + 0x6e, 0x64, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0xa0, 0x03, 0x0a, 0x09, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, + 0x67, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x15, 0x0a, 0x06, 0x6c, + 0x6f, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x6f, 0x67, + 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, + 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, + 0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x68, 0x6f, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x75, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, + 0x68, 0x6f, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, + 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x63, 0x6f, + 0x64, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x5f, 0x69, 0x70, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x49, 0x70, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6d, 0x65, 0x63, 0x68, + 0x61, 0x6e, 0x69, 0x73, 0x6d, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x61, 0x75, 0x74, + 0x68, 0x4d, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x6d, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, + 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, + 0x72, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x73, 0x75, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x61, 0x75, 0x74, 0x68, 0x53, + 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x2a, 0x64, 0x0a, 0x16, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, + 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x17, 0x0a, 0x13, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, + 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x55, 0x50, 0x44, + 0x41, 0x54, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x49, 0x46, 0x49, 0x45, + 0x44, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x54, 0x59, + 0x50, 0x45, 0x5f, 0x52, 0x45, 0x4d, 0x4f, 0x56, 0x45, 0x44, 0x10, 0x02, 0x32, 0xc5, 0x01, 0x0a, + 0x0c, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5f, 0x0a, + 0x10, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x12, 0x23, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x47, + 0x65, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x6d, 0x61, - 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x70, 0x70, - 0x69, 0x6e, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x30, 0x01, 0x12, 0x54, 0x0a, 0x0d, 0x53, 0x65, 0x6e, 0x64, 0x41, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x4c, 0x6f, 0x67, 0x12, 0x20, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, - 0x74, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, - 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, - 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x08, 0x5a, 0x06, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x54, + 0x0a, 0x0d, 0x53, 0x65, 0x6e, 0x64, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x12, + 0x20, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x65, 0x6e, + 0x64, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x21, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x53, + 0x65, 0x6e, 0x64, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x08, 0x5a, 0x06, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1027,20 +1067,21 @@ var file_proxy_service_proto_depIdxs = []int32{ 5, // 2: management.Authentication.password:type_name -> management.Password 6, // 3: management.Authentication.pin:type_name -> management.Pin 8, // 4: management.Authentication.oidc:type_name -> management.OIDC - 0, // 5: management.ProxyMapping.type:type_name -> management.ProxyMappingUpdateType - 3, // 6: management.ProxyMapping.path:type_name -> management.PathMapping - 4, // 7: management.ProxyMapping.auth:type_name -> management.Authentication - 12, // 8: management.SendAccessLogRequest.log:type_name -> management.AccessLog - 13, // 9: management.AccessLog.timestamp:type_name -> google.protobuf.Timestamp - 1, // 10: management.ProxyService.GetMappingUpdate:input_type -> management.GetMappingUpdateRequest - 10, // 11: management.ProxyService.SendAccessLog:input_type -> management.SendAccessLogRequest - 2, // 12: management.ProxyService.GetMappingUpdate:output_type -> management.GetMappingUpdateResponse - 11, // 13: management.ProxyService.SendAccessLog:output_type -> management.SendAccessLogResponse - 12, // [12:14] is the sub-list for method output_type - 10, // [10:12] is the sub-list for method input_type - 10, // [10:10] is the sub-list for extension type_name - 10, // [10:10] is the sub-list for extension extendee - 0, // [0:10] is the sub-list for field type_name + 7, // 5: management.Authentication.link:type_name -> management.Link + 0, // 6: management.ProxyMapping.type:type_name -> management.ProxyMappingUpdateType + 3, // 7: management.ProxyMapping.path:type_name -> management.PathMapping + 4, // 8: management.ProxyMapping.auth:type_name -> management.Authentication + 12, // 9: management.SendAccessLogRequest.log:type_name -> management.AccessLog + 13, // 10: management.AccessLog.timestamp:type_name -> google.protobuf.Timestamp + 1, // 11: management.ProxyService.GetMappingUpdate:input_type -> management.GetMappingUpdateRequest + 10, // 12: management.ProxyService.SendAccessLog:input_type -> management.SendAccessLogRequest + 2, // 13: management.ProxyService.GetMappingUpdate:output_type -> management.GetMappingUpdateResponse + 11, // 14: management.ProxyService.SendAccessLog:output_type -> management.SendAccessLogResponse + 13, // [13:15] is the sub-list for method output_type + 11, // [11:13] is the sub-list for method input_type + 11, // [11:11] is the sub-list for extension type_name + 11, // [11:11] is the sub-list for extension extendee + 0, // [0:11] is the sub-list for field type_name } func init() { file_proxy_service_proto_init() } diff --git a/shared/management/proto/proxy_service.proto b/shared/management/proto/proxy_service.proto index 486d978fb..f92a7cb8a 100644 --- a/shared/management/proto/proxy_service.proto +++ b/shared/management/proto/proxy_service.proto @@ -43,6 +43,7 @@ message Authentication { Password password = 1; Pin pin = 2; OIDC oidc = 3; + Link link = 4; } message Password { @@ -73,10 +74,11 @@ message OIDC { message ProxyMapping { ProxyMappingUpdateType type = 1; string id = 2; - string domain = 3; - repeated PathMapping path = 4; - string setup_key = 5; - Authentication auth = 6; + string account_id = 3; + string domain = 4; + repeated PathMapping path = 5; + string setup_key = 6; + Authentication auth = 7; } // SendAccessLogRequest consists of one or more AccessLogs from a Proxy. @@ -89,14 +91,16 @@ message SendAccessLogResponse {} message AccessLog { google.protobuf.Timestamp timestamp = 1; - string service_id = 2; - string host = 3; - string path = 4; - int64 duration_ms = 5; - string method = 6; - int32 response_code = 7; - string source_ip = 8; - string auth_mechanism = 9; - string user_id = 10; - bool auth_success = 11; + string log_id = 2; + string account_id = 3; + string service_id = 4; + string host = 5; + string path = 6; + int64 duration_ms = 7; + string method = 8; + int32 response_code = 9; + string source_ip = 10; + string auth_mechanism = 11; + string user_id = 12; + bool auth_success = 13; }