From e971027a372119d4f6b9a7909fd803d13ded505f Mon Sep 17 00:00:00 2001 From: Ahmad Anvari Date: Tue, 10 Sep 2024 17:23:30 +0330 Subject: [PATCH] feat: implement everything --- internal/authenticator/auto_authenticator.go | 54 +++++++++++++++++-- .../authenticator/auto_authenticator_test.go | 11 ++-- internal/authenticator/builder.go | 34 ++++++------ .../authenticator/manual_authenticator.go | 1 + .../manual_authenticator_test.go | 7 +-- internal/config/config.go | 8 ++- pkg/validator/client.go | 5 ++ 7 files changed, 93 insertions(+), 27 deletions(-) diff --git a/internal/authenticator/auto_authenticator.go b/internal/authenticator/auto_authenticator.go index 50ce0bf8..7a00f223 100644 --- a/internal/authenticator/auto_authenticator.go +++ b/internal/authenticator/auto_authenticator.go @@ -6,13 +6,15 @@ import ( "net/http" "github.com/golang-jwt/jwt/v5" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/propagation" + "go.opentelemetry.io/otel/trace" + "go.uber.org/zap" + "github.com/snapp-incubator/soteria/internal/config" "github.com/snapp-incubator/soteria/internal/topics" "github.com/snapp-incubator/soteria/pkg/acl" "github.com/snapp-incubator/soteria/pkg/validator" - "go.opentelemetry.io/otel" - "go.opentelemetry.io/otel/propagation" - "go.opentelemetry.io/otel/trace" ) // AutoAuthenticator is responsible for Acl/Auth/Token of users. @@ -24,6 +26,8 @@ type AutoAuthenticator struct { Validator validator.Client Parser *jwt.Parser Tracer trace.Tracer + Logger *zap.Logger + blackList autoBlackListChecker } // Auth check user authentication by checking the user's token @@ -43,10 +47,25 @@ func (a AutoAuthenticator) Auth(tokenString string) error { otel.GetTextMapPropagator().Inject(ctx, propagation.HeaderCarrier(headers)) - if _, err := a.Validator.Validate(ctx, headers, "bearer "+tokenString); err != nil { + payload, err := a.Validator.Validate(ctx, headers, "bearer "+tokenString) + if err != nil { return fmt.Errorf("token is invalid: %w", err) } + if a.blackList.isBlackList(payload.UserID, payload.Iss) { + a.Logger.Warn("blacklisted user is requesting!", + zap.Int("iat", payload.IAT), + zap.String("aud", payload.Aud), + zap.Int("iss", payload.Iss), + zap.String("sub", payload.Sub), + zap.Int("user_id", payload.UserID), + zap.String("email", payload.Email), + zap.Int("exp", payload.Exp), + zap.String("locale", payload.Locale), + zap.String("sid", payload.Sid), + ) + } + return nil } @@ -114,3 +133,30 @@ func (a AutoAuthenticator) GetCompany() string { func (a AutoAuthenticator) IsSuperuser() bool { return false } + +type autoBlackListChecker struct { + users map[int]struct{} + iss int +} + +func NewAutoBlackListChecker(cfg config.BlackListUserLogging) autoBlackListChecker { + users := make(map[int]struct{}) + for _, userID := range cfg.UserIDs { + users[userID] = struct{}{} + } + + return autoBlackListChecker{ + users: users, + iss: cfg.Iss, + } +} + +func (a autoBlackListChecker) isBlackList(userID, iss int) bool { + if iss != a.iss { + return false + } + + _, ok := a.users[userID] + + return ok +} diff --git a/internal/authenticator/auto_authenticator_test.go b/internal/authenticator/auto_authenticator_test.go index 422041d4..fd027793 100644 --- a/internal/authenticator/auto_authenticator_test.go +++ b/internal/authenticator/auto_authenticator_test.go @@ -10,15 +10,16 @@ import ( "time" "github.com/golang-jwt/jwt/v5" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + "go.opentelemetry.io/otel/trace/noop" + "go.uber.org/zap" + "github.com/snapp-incubator/soteria/internal/authenticator" "github.com/snapp-incubator/soteria/internal/config" "github.com/snapp-incubator/soteria/internal/topics" "github.com/snapp-incubator/soteria/pkg/acl" "github.com/snapp-incubator/soteria/pkg/validator" - "github.com/stretchr/testify/require" - "github.com/stretchr/testify/suite" - "go.opentelemetry.io/otel/trace/noop" - "go.uber.org/zap" ) type AutoAuthenticatorTestSuite struct { @@ -100,6 +101,7 @@ func (suite *AutoAuthenticatorTestSuite) SetupSuite() { SubName: "sub", SigningMethod: "rsa256", }, + Logger: zap.NewNop(), } } @@ -132,6 +134,7 @@ func TestAutoAuthenticator_ValidateTopicBySender(t *testing.T) { AllowedAccessTypes: []acl.AccessType{acl.Pub, acl.Sub}, Company: "snapp", TopicManager: topics.NewTopicManager(cfg.Topics, hid, "snapp", cfg.IssEntityMap, cfg.IssPeerMap, zap.NewNop()), + Logger: zap.NewNop(), } t.Run("testing valid driver cab event", func(t *testing.T) { diff --git a/internal/authenticator/builder.go b/internal/authenticator/builder.go index f124001b..73b244fa 100644 --- a/internal/authenticator/builder.go +++ b/internal/authenticator/builder.go @@ -5,12 +5,13 @@ import ( "fmt" "github.com/golang-jwt/jwt/v5" + "go.opentelemetry.io/otel/trace" + "go.uber.org/zap" + "github.com/snapp-incubator/soteria/internal/config" "github.com/snapp-incubator/soteria/internal/topics" "github.com/snapp-incubator/soteria/pkg/acl" "github.com/snapp-incubator/soteria/pkg/validator" - "go.opentelemetry.io/otel/trace" - "go.uber.org/zap" ) var ( @@ -22,10 +23,11 @@ var ( ) type Builder struct { - Vendors []config.Vendor - Logger *zap.Logger - ValidatorConfig config.Validator - Tracer trace.Tracer + Vendors []config.Vendor + Logger *zap.Logger + ValidatorConfig config.Validator + Tracer trace.Tracer + BlackListUserLoggingConfig config.BlackListUserLogging } func (b Builder) Authenticators() (map[string]Authenticator, error) { @@ -122,13 +124,13 @@ func (b Builder) manualAuthenticator(vendor config.Vendor) (*ManualAuthenticator }, nil } -func (b Builder) autoAuthenticator(vendor config.Vendor) (*AutoAuthenticator, error) { - allowedAccessTypes, err := b.GetAllowedAccessTypes(vendor.AllowedAccessTypes) +func (b Builder) autoAuthenticator(vendorCfg config.Vendor, blackListUserLoggingCfg config.BlackListUserLogging) (*AutoAuthenticator, error) { + allowedAccessTypes, err := b.GetAllowedAccessTypes(vendorCfg.AllowedAccessTypes) if err != nil { return nil, fmt.Errorf("cannot parse allowed access types %w", err) } - hid, err := topics.NewHashIDManager(vendor.HashIDMap) + hid, err := topics.NewHashIDManager(vendorCfg.HashIDMap) if err != nil { return nil, fmt.Errorf("cannot create hash-id manager %w", err) } @@ -137,19 +139,21 @@ func (b Builder) autoAuthenticator(vendor config.Vendor) (*AutoAuthenticator, er return &AutoAuthenticator{ AllowedAccessTypes: allowedAccessTypes, - Company: vendor.Company, + Company: vendorCfg.Company, TopicManager: topics.NewTopicManager( - vendor.Topics, + vendorCfg.Topics, hid, - vendor.Company, - vendor.IssEntityMap, - vendor.IssPeerMap, + vendorCfg.Company, + vendorCfg.IssEntityMap, + vendorCfg.IssPeerMap, b.Logger.Named("topic-manager"), ), Tracer: b.Tracer, - JWTConfig: vendor.Jwt, + JWTConfig: vendorCfg.Jwt, Validator: client, Parser: jwt.NewParser(), + Logger: b.Logger.Named("auto-authenticator"), + blackList: NewAutoBlackListChecker(blackListUserLoggingCfg), }, nil } diff --git a/internal/authenticator/manual_authenticator.go b/internal/authenticator/manual_authenticator.go index 07afd915..a7224658 100644 --- a/internal/authenticator/manual_authenticator.go +++ b/internal/authenticator/manual_authenticator.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/golang-jwt/jwt/v5" + "github.com/snapp-incubator/soteria/internal/config" "github.com/snapp-incubator/soteria/internal/topics" "github.com/snapp-incubator/soteria/pkg/acl" diff --git a/internal/authenticator/manual_authenticator_test.go b/internal/authenticator/manual_authenticator_test.go index c3795963..34d547cf 100644 --- a/internal/authenticator/manual_authenticator_test.go +++ b/internal/authenticator/manual_authenticator_test.go @@ -5,13 +5,14 @@ import ( "testing" "github.com/golang-jwt/jwt/v5" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + "go.uber.org/zap" + "github.com/snapp-incubator/soteria/internal/authenticator" "github.com/snapp-incubator/soteria/internal/config" "github.com/snapp-incubator/soteria/internal/topics" "github.com/snapp-incubator/soteria/pkg/acl" - "github.com/stretchr/testify/require" - "github.com/stretchr/testify/suite" - "go.uber.org/zap" ) type ManualAuthenticatorSnappTestSuite struct { diff --git a/internal/config/config.go b/internal/config/config.go index 1b7de39f..f74eff6e 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -11,10 +11,11 @@ import ( "github.com/knadh/koanf/providers/file" "github.com/knadh/koanf/providers/structs" "github.com/knadh/koanf/v2" + "github.com/tidwall/pretty" + "github.com/snapp-incubator/soteria/internal/logger" "github.com/snapp-incubator/soteria/internal/topics" "github.com/snapp-incubator/soteria/internal/tracing" - "github.com/tidwall/pretty" ) const ( @@ -55,6 +56,11 @@ type ( URL string `json:"url,omitempty" koanf:"url"` Timeout time.Duration `json:"timeout,omitempty" koanf:"timeout"` } + + BlackListUserLogging struct { + Iss int `json:"iss,omitempty" koanf:"iss"` + UserIDs []int `json:"user_ids,omitempty" koanf:"user_ids"` + } ) // New reads configuration with koanf. diff --git a/pkg/validator/client.go b/pkg/validator/client.go index c60b6bd5..b8980711 100644 --- a/pkg/validator/client.go +++ b/pkg/validator/client.go @@ -43,6 +43,7 @@ type Payload struct { Email string `json:"email"` Exp int `json:"exp"` Locale string `json:"locale"` + Sid string `json:"sid"` } // New creates a new Client with default attributes. @@ -159,6 +160,10 @@ func (c *Client) Validate(parentCtx context.Context, headers http.Header, bearer payload.Locale = locale } + if sid, ok := userData["sid"].(string); ok { + payload.Sid = sid + } + return payload, nil }