Skip to content

Commit

Permalink
feat: provide metrics auto authenticator
Browse files Browse the repository at this point in the history
  • Loading branch information
1995parham committed Nov 24, 2024
1 parent 92557b5 commit f6be236
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 75 deletions.
19 changes: 14 additions & 5 deletions internal/authenticator/auto_authenticator.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import (
"context"
"fmt"
"net/http"
"time"

"github.com/golang-jwt/jwt/v5"
"github.com/snapp-incubator/soteria/internal/config"
"github.com/snapp-incubator/soteria/internal/metric"
"github.com/snapp-incubator/soteria/internal/topics"
"github.com/snapp-incubator/soteria/pkg/acl"
"github.com/snapp-incubator/soteria/pkg/validator"
Expand All @@ -24,6 +26,7 @@ type AutoAuthenticator struct {
Validator validator.Client
Parser *jwt.Parser
Tracer trace.Tracer
metrics *metric.AutoAuthenticatorMetrics
}

// Auth check user authentication by checking the user's token
Expand All @@ -44,10 +47,16 @@ func (a AutoAuthenticator) Auth(ctx context.Context, tokenString string) error {

otel.GetTextMapPropagator().Inject(ctx, propagation.HeaderCarrier(headers))

start := time.Now()

if _, err := a.Validator.Validate(ctx, headers, "bearer "+tokenString); err != nil {
a.metrics.Latency(time.Since(start).Seconds(), a.Company, err)

return fmt.Errorf("token is invalid: %w", err)
}

a.metrics.Latency(time.Since(start).Seconds(), a.Company, nil)

return nil
}

Expand Down Expand Up @@ -88,11 +97,11 @@ func (a AutoAuthenticator) ACL(

if !topicTemplate.HasAccess(issuer, accessType) {
return false, TopicNotAllowedError{
issuer,
sub,
accessType,
topic,
topicTemplate.Type,
Issuer: issuer,
Sub: sub,
AccessType: accessType,
Topic: topic,
TopicType: topicTemplate.Type,
}
}

Expand Down
2 changes: 2 additions & 0 deletions internal/authenticator/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/golang-jwt/jwt/v5"
"github.com/snapp-incubator/soteria/internal/config"
"github.com/snapp-incubator/soteria/internal/metric"
"github.com/snapp-incubator/soteria/internal/topics"
"github.com/snapp-incubator/soteria/pkg/acl"
"github.com/snapp-incubator/soteria/pkg/validator"
Expand Down Expand Up @@ -138,6 +139,7 @@ func (b Builder) autoAuthenticator(vendor config.Vendor) (*AutoAuthenticator, er
return &AutoAuthenticator{
AllowedAccessTypes: allowedAccessTypes,
Company: vendor.Company,
metrics: metric.NewAutoAuthenticatorMetrics(),
TopicManager: topics.NewTopicManager(
vendor.Topics,
hid,
Expand Down
26 changes: 13 additions & 13 deletions internal/authenticator/errors.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
package authenticator

import "github.com/snapp-incubator/soteria/internal/error"
import "github.com/snapp-incubator/soteria/internal/errors"

var (
ErrInvalidSigningMethod = error.ErrInvalidSigningMethod
ErrIssNotFound = error.ErrIssNotFound
ErrSubNotFound = error.ErrSubNotFound
ErrInvalidClaims = error.ErrInvalidClaims
ErrInvalidIP = error.ErrInvalidIP
ErrInvalidAccessType = error.ErrInvalidAccessType
ErrDecodeHashID = error.ErrDecodeHashID
ErrInvalidSecret = error.ErrInvalidSecret
ErrIncorrectPassword = error.ErrIncorrectPassword
ErrInvalidSigningMethod = errors.ErrInvalidSigningMethod
ErrIssNotFound = errors.ErrIssNotFound
ErrSubNotFound = errors.ErrSubNotFound
ErrInvalidClaims = errors.ErrInvalidClaims
ErrInvalidIP = errors.ErrInvalidIP
ErrInvalidAccessType = errors.ErrInvalidAccessType
ErrDecodeHashID = errors.ErrDecodeHashID
ErrInvalidSecret = errors.ErrInvalidSecret
ErrIncorrectPassword = errors.ErrIncorrectPassword
)

type TopicNotAllowedError = error.TopicNotAllowedError
type TopicNotAllowedError = errors.TopicNotAllowedError

type KeyNotFoundError = error.KeyNotFoundError
type KeyNotFoundError = errors.KeyNotFoundError

type InvalidTopicError = error.InvalidTopicError
type InvalidTopicError = errors.InvalidTopicError
10 changes: 5 additions & 5 deletions internal/authenticator/manual_authenticator.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,11 @@ func (a ManualAuthenticator) ACL(

if !topicTemplate.HasAccess(issuer, accessType) {
return false, TopicNotAllowedError{
issuer,
sub,
accessType,
topic,
topicTemplate.Type,
Issuer: issuer,
Sub: sub,
AccessType: accessType,
Topic: topic,
TopicType: topicTemplate.Type,
}
}

Expand Down
2 changes: 1 addition & 1 deletion internal/error/error.go → internal/errors/error.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package error
package errors

import (
"errors"
Expand Down
56 changes: 30 additions & 26 deletions internal/metric/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ package metric

import (
"errors"
"strconv"

"github.com/prometheus/client_golang/prometheus"
serror "github.com/snapp-incubator/soteria/internal/error"
serrors "github.com/snapp-incubator/soteria/internal/errors"
)

type AutoAuthenticatorMetrics struct {
Expand Down Expand Up @@ -42,8 +41,13 @@ func NewAutoAuthenticatorMetrics() *AutoAuthenticatorMetrics {
}

// Latency measures latency in seconds.
func (m *AutoAuthenticatorMetrics) Latency(latency float64, company string, status int) {
m.latency.WithLabelValues(company, strconv.Itoa(status)).Observe(latency)
func (m *AutoAuthenticatorMetrics) Latency(latency float64, company string, err error) {
message := ""
if err != nil {
message = err.Error()
}

m.latency.WithLabelValues(company, message).Observe(latency)
}

func (m *AutoAuthenticatorMetrics) register() {
Expand Down Expand Up @@ -86,28 +90,28 @@ func (m *APIMetrics) AuthSuccess(company, source string) {
func (m *APIMetrics) AuthFailed(company, source string, err error) {
var (
status string
topicNotAllowedErrorTarget *serror.TopicNotAllowedError
keyNotFoundErrorTarget *serror.KeyNotFoundError
topicNotAllowedErrorTarget *serrors.TopicNotAllowedError
keyNotFoundErrorTarget *serrors.KeyNotFoundError
)

switch {
case errors.Is(err, serror.ErrInvalidSigningMethod):
case errors.Is(err, serrors.ErrInvalidSigningMethod):
status = "err_invalid_signing_method"
case errors.Is(err, serror.ErrIssNotFound):
case errors.Is(err, serrors.ErrIssNotFound):
status = "err_iss_not_found"
case errors.Is(err, serror.ErrSubNotFound):
case errors.Is(err, serrors.ErrSubNotFound):
status = "err_sub_not_found"
case errors.Is(err, serror.ErrInvalidClaims):
case errors.Is(err, serrors.ErrInvalidClaims):
status = "err_invalid_claims"
case errors.Is(err, serror.ErrInvalidIP):
case errors.Is(err, serrors.ErrInvalidIP):
status = "err_invalid_ip"
case errors.Is(err, serror.ErrInvalidAccessType):
case errors.Is(err, serrors.ErrInvalidAccessType):
status = "err_invalid_access_type"
case errors.Is(err, serror.ErrDecodeHashID):
case errors.Is(err, serrors.ErrDecodeHashID):
status = "err_decode_hash_id"
case errors.Is(err, serror.ErrInvalidSecret):
case errors.Is(err, serrors.ErrInvalidSecret):
status = "err_invalid_secret"
case errors.Is(err, serror.ErrIncorrectPassword):
case errors.Is(err, serrors.ErrIncorrectPassword):
status = "err_incorrect_password"
case errors.As(err, &topicNotAllowedErrorTarget):
status = "topic_not_allowed_error"
Expand All @@ -128,28 +132,28 @@ func (m *APIMetrics) ACLSuccess(company string) {
func (m *APIMetrics) ACLFailed(company string, err error) {
var (
status string
topicNotAllowedErrorTarget *serror.TopicNotAllowedError
keyNotFoundErrorTarget *serror.KeyNotFoundError
topicNotAllowedErrorTarget *serrors.TopicNotAllowedError
keyNotFoundErrorTarget *serrors.KeyNotFoundError
)

switch {
case errors.Is(err, serror.ErrInvalidSigningMethod):
case errors.Is(err, serrors.ErrInvalidSigningMethod):
status = "err_invalid_signing_method"
case errors.Is(err, serror.ErrIssNotFound):
case errors.Is(err, serrors.ErrIssNotFound):
status = "err_iss_not_found"
case errors.Is(err, serror.ErrSubNotFound):
case errors.Is(err, serrors.ErrSubNotFound):
status = "err_sub_not_found"
case errors.Is(err, serror.ErrInvalidClaims):
case errors.Is(err, serrors.ErrInvalidClaims):
status = "err_invalid_claims"
case errors.Is(err, serror.ErrInvalidIP):
case errors.Is(err, serrors.ErrInvalidIP):
status = "err_invalid_ip"
case errors.Is(err, serror.ErrInvalidAccessType):
case errors.Is(err, serrors.ErrInvalidAccessType):
status = "err_invalid_access_type"
case errors.Is(err, serror.ErrDecodeHashID):
case errors.Is(err, serrors.ErrDecodeHashID):
status = "err_decode_hash_id"
case errors.Is(err, serror.ErrInvalidSecret):
case errors.Is(err, serrors.ErrInvalidSecret):
status = "err_invalid_secret"
case errors.Is(err, serror.ErrIncorrectPassword):
case errors.Is(err, serrors.ErrIncorrectPassword):
status = "err_incorrect_password"
case errors.As(err, &topicNotAllowedErrorTarget):
status = "topic_not_allowed_error"
Expand Down
50 changes: 25 additions & 25 deletions internal/metric/metrics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"errors"
"testing"

serror "github.com/snapp-incubator/soteria/internal/error"
serrors "github.com/snapp-incubator/soteria/internal/errors"
"github.com/snapp-incubator/soteria/internal/metric"
)

Expand All @@ -14,44 +14,44 @@ func TestAuthIncrement(t *testing.T) {
m := metric.NewAPIMetrics()

m.AuthSuccess("snapp", "-")
m.AuthFailed("snapp", "-", serror.ErrInvalidSigningMethod)
m.AuthFailed("snapp", "-", serror.ErrIssNotFound)
m.AuthFailed("snapp", "-", serror.ErrSubNotFound)
m.AuthFailed("snapp", "-", serror.ErrInvalidClaims)
m.AuthFailed("snapp", "-", serror.ErrInvalidIP)

m.AuthFailed("snapp", "-", serror.ErrInvalidAccessType)
m.AuthFailed("snapp", "-", serror.ErrDecodeHashID)
m.AuthFailed("snapp", "-", serror.ErrInvalidSecret)
m.AuthFailed("snapp", "-", serror.ErrIncorrectPassword)
m.AuthFailed("snapp", "-", &serror.TopicNotAllowedError{
m.AuthFailed("snapp", "-", serrors.ErrInvalidSigningMethod)
m.AuthFailed("snapp", "-", serrors.ErrIssNotFound)
m.AuthFailed("snapp", "-", serrors.ErrSubNotFound)
m.AuthFailed("snapp", "-", serrors.ErrInvalidClaims)
m.AuthFailed("snapp", "-", serrors.ErrInvalidIP)

m.AuthFailed("snapp", "-", serrors.ErrInvalidAccessType)
m.AuthFailed("snapp", "-", serrors.ErrDecodeHashID)
m.AuthFailed("snapp", "-", serrors.ErrInvalidSecret)
m.AuthFailed("snapp", "-", serrors.ErrIncorrectPassword)
m.AuthFailed("snapp", "-", &serrors.TopicNotAllowedError{
Issuer: "issuer",
Sub: "subject",
AccessType: "1",
Topic: "topic",
TopicType: "pub",
})
m.AuthFailed("snapp", "-", &serror.KeyNotFoundError{Issuer: "iss"})
m.AuthFailed("snapp", "-", &serrors.KeyNotFoundError{Issuer: "iss"})
m.AuthFailed("snapp", "-", errors.ErrUnsupported)

m.ACLSuccess("snapp")
m.ACLFailed("snapp", serror.ErrInvalidSigningMethod)
m.ACLFailed("snapp", serror.ErrIssNotFound)
m.ACLFailed("snapp", serror.ErrSubNotFound)
m.ACLFailed("snapp", serror.ErrInvalidClaims)
m.ACLFailed("snapp", serror.ErrInvalidIP)

m.ACLFailed("snapp", serror.ErrInvalidAccessType)
m.ACLFailed("snapp", serror.ErrDecodeHashID)
m.ACLFailed("snapp", serror.ErrInvalidSecret)
m.ACLFailed("snapp", serror.ErrIncorrectPassword)
m.ACLFailed("snapp", &serror.TopicNotAllowedError{
m.ACLFailed("snapp", serrors.ErrInvalidSigningMethod)
m.ACLFailed("snapp", serrors.ErrIssNotFound)
m.ACLFailed("snapp", serrors.ErrSubNotFound)
m.ACLFailed("snapp", serrors.ErrInvalidClaims)
m.ACLFailed("snapp", serrors.ErrInvalidIP)

m.ACLFailed("snapp", serrors.ErrInvalidAccessType)
m.ACLFailed("snapp", serrors.ErrDecodeHashID)
m.ACLFailed("snapp", serrors.ErrInvalidSecret)
m.ACLFailed("snapp", serrors.ErrIncorrectPassword)
m.ACLFailed("snapp", &serrors.TopicNotAllowedError{
Issuer: "issuer",
Sub: "subject",
AccessType: "1",
Topic: "topic",
TopicType: "pub",
})
m.ACLFailed("snapp", &serror.KeyNotFoundError{Issuer: "iss"})
m.ACLFailed("snapp", &serrors.KeyNotFoundError{Issuer: "iss"})
m.ACLFailed("snapp", errors.ErrUnsupported)
}

0 comments on commit f6be236

Please sign in to comment.