diff options
author | Mike Crute <mike@crute.us> | 2023-08-19 10:49:51 -0700 |
---|---|---|
committer | Mike Crute <mike@crute.us> | 2023-08-19 10:50:36 -0700 |
commit | 9b1afe4a7c84fbc5365b7f83e6eabc926bb508cb (patch) | |
tree | 8cf74d42fc184c86ce3c8158c77c1436906cd854 | |
parent | aa0254d2eb8cfb89d594861dcb3c9af2b0cf2b89 (diff) | |
download | websocket_proxy-9b1afe4a7c84fbc5365b7f83e6eabc926bb508cb.tar.bz2 websocket_proxy-9b1afe4a7c84fbc5365b7f83e6eabc926bb508cb.tar.xz websocket_proxy-9b1afe4a7c84fbc5365b7f83e6eabc926bb508cb.zip |
Add prometheus metrics
-rw-r--r-- | app/controllers/ca.go | 22 | ||||
-rw-r--r-- | app/controllers/login.go | 20 | ||||
-rw-r--r-- | app/controllers/oauth2_device.go | 28 | ||||
-rw-r--r-- | app/controllers/proxy.go | 19 | ||||
-rw-r--r-- | app/controllers/register.go | 22 | ||||
-rw-r--r-- | go.mod | 2 |
6 files changed, 112 insertions, 1 deletions
diff --git a/app/controllers/ca.go b/app/controllers/ca.go index 632db50..c04dcd8 100644 --- a/app/controllers/ca.go +++ b/app/controllers/ca.go | |||
@@ -11,9 +11,24 @@ import ( | |||
11 | "code.crute.us/mcrute/ssh-proxy/app/middleware" | 11 | "code.crute.us/mcrute/ssh-proxy/app/middleware" |
12 | "code.crute.us/mcrute/ssh-proxy/app/models" | 12 | "code.crute.us/mcrute/ssh-proxy/app/models" |
13 | "github.com/labstack/echo/v4" | 13 | "github.com/labstack/echo/v4" |
14 | "github.com/prometheus/client_golang/prometheus" | ||
15 | "github.com/prometheus/client_golang/prometheus/promauto" | ||
14 | "golang.org/x/crypto/ssh" | 16 | "golang.org/x/crypto/ssh" |
15 | ) | 17 | ) |
16 | 18 | ||
19 | var ( | ||
20 | caError = promauto.NewCounterVec(prometheus.CounterOpts{ | ||
21 | Namespace: "ssh_proxy", | ||
22 | Name: "ssh_ca_error", | ||
23 | Help: "Total number of errors during SSH CA operation", | ||
24 | }, []string{"type"}) | ||
25 | caSuccess = promauto.NewCounter(prometheus.CounterOpts{ | ||
26 | Namespace: "ssh_proxy", | ||
27 | Name: "ssh_ca_success", | ||
28 | Help: "Total number of successful CA operations", | ||
29 | }) | ||
30 | ) | ||
31 | |||
17 | type CASecret struct { | 32 | type CASecret struct { |
18 | Key string `mapstructure:"key"` | 33 | Key string `mapstructure:"key"` |
19 | } | 34 | } |
@@ -57,24 +72,29 @@ func (h *CAHandler) authorizeRequest(c echo.Context, certRequest *ssh.Certificat | |||
57 | } | 72 | } |
58 | 73 | ||
59 | if user.Username != certRequest.ValidPrincipals[0] { | 74 | if user.Username != certRequest.ValidPrincipals[0] { |
75 | caError.With(prometheus.Labels{"type": "user_request_mismatch"}).Inc() | ||
60 | return fmt.Errorf("Authenticated username and cert username must match") | 76 | return fmt.Errorf("Authenticated username and cert username must match") |
61 | } | 77 | } |
62 | 78 | ||
63 | if !session.HasScope("ca:issue") { | 79 | if !session.HasScope("ca:issue") { |
80 | caError.With(prometheus.Labels{"type": "missing_oauth_scope"}).Inc() | ||
64 | return fmt.Errorf("Authorized session does not have scope ca:issue") | 81 | return fmt.Errorf("Authorized session does not have scope ca:issue") |
65 | } | 82 | } |
66 | 83 | ||
67 | if certRequest.Extensions == nil { | 84 | if certRequest.Extensions == nil { |
85 | caError.With(prometheus.Labels{"type": "no_extensions"}).Inc() | ||
68 | return fmt.Errorf("Cert request extensions are empty") | 86 | return fmt.Errorf("Cert request extensions are empty") |
69 | } | 87 | } |
70 | 88 | ||
71 | hostLine, ok := certRequest.Extensions["allowed-hosts"] | 89 | hostLine, ok := certRequest.Extensions["allowed-hosts"] |
72 | if !ok { | 90 | if !ok { |
91 | caError.With(prometheus.Labels{"type": "no_allowed_hosts"}).Inc() | ||
73 | return fmt.Errorf("Cert request allowed-hosts is blank") | 92 | return fmt.Errorf("Cert request allowed-hosts is blank") |
74 | } | 93 | } |
75 | 94 | ||
76 | for _, host := range strings.Split(hostLine, ",") { | 95 | for _, host := range strings.Split(hostLine, ",") { |
77 | if !user.AuthorizedForHost(host) { | 96 | if !user.AuthorizedForHost(host) { |
97 | caError.With(prometheus.Labels{"type": "user_no_auth_host"}).Inc() | ||
78 | return fmt.Errorf("User %s is not authorized for host %s", session.UserId, host) | 98 | return fmt.Errorf("User %s is not authorized for host %s", session.UserId, host) |
79 | } | 99 | } |
80 | } | 100 | } |
@@ -168,5 +188,7 @@ func (h *CAHandler) HandleIssue(c echo.Context) error { | |||
168 | }) | 188 | }) |
169 | } | 189 | } |
170 | 190 | ||
191 | caSuccess.Inc() | ||
192 | |||
171 | return c.Blob(http.StatusOK, "application/x-ssh-certificate", ssh.MarshalAuthorizedKey(certToIssue)) | 193 | return c.Blob(http.StatusOK, "application/x-ssh-certificate", ssh.MarshalAuthorizedKey(certToIssue)) |
172 | } | 194 | } |
diff --git a/app/controllers/login.go b/app/controllers/login.go index 603eb20..f59789f 100644 --- a/app/controllers/login.go +++ b/app/controllers/login.go | |||
@@ -13,6 +13,21 @@ import ( | |||
13 | "github.com/go-webauthn/webauthn/protocol" | 13 | "github.com/go-webauthn/webauthn/protocol" |
14 | "github.com/go-webauthn/webauthn/webauthn" | 14 | "github.com/go-webauthn/webauthn/webauthn" |
15 | "github.com/labstack/echo/v4" | 15 | "github.com/labstack/echo/v4" |
16 | "github.com/prometheus/client_golang/prometheus" | ||
17 | "github.com/prometheus/client_golang/prometheus/promauto" | ||
18 | ) | ||
19 | |||
20 | var ( | ||
21 | loginError = promauto.NewCounterVec(prometheus.CounterOpts{ | ||
22 | Namespace: "ssh_proxy", | ||
23 | Name: "login_error", | ||
24 | Help: "Total number of errors during login operation", | ||
25 | }, []string{"type"}) | ||
26 | loginSuccess = promauto.NewCounter(prometheus.CounterOpts{ | ||
27 | Namespace: "ssh_proxy", | ||
28 | Name: "login_success", | ||
29 | Help: "Total number of successful logins", | ||
30 | }) | ||
16 | ) | 31 | ) |
17 | 32 | ||
18 | type LoginController[T app.AppSession] struct { | 33 | type LoginController[T app.AppSession] struct { |
@@ -57,6 +72,7 @@ func (a *LoginController[T]) HandleFinish(c echo.Context) error { | |||
57 | user, err := a.Users.Get(ctx, c.Param("username")) | 72 | user, err := a.Users.Get(ctx, c.Param("username")) |
58 | if err != nil { | 73 | if err != nil { |
59 | a.Logger.Errorf("Error getting user: %s", err) | 74 | a.Logger.Errorf("Error getting user: %s", err) |
75 | loginError.With(prometheus.Labels{"type": "no_user"}).Inc() | ||
60 | return c.NoContent(http.StatusNotFound) | 76 | return c.NoContent(http.StatusNotFound) |
61 | } | 77 | } |
62 | 78 | ||
@@ -76,6 +92,7 @@ func (a *LoginController[T]) HandleFinish(c echo.Context) error { | |||
76 | 92 | ||
77 | if _, err := a.Webauthn.ValidateLogin(user, *s.WebauthnSession, response); err != nil { | 93 | if _, err := a.Webauthn.ValidateLogin(user, *s.WebauthnSession, response); err != nil { |
78 | a.Logger.Errorf("Error validating login: %s", err) | 94 | a.Logger.Errorf("Error validating login: %s", err) |
95 | loginError.With(prometheus.Labels{"type": "webauthn_invalid"}).Inc() | ||
79 | return c.NoContent(http.StatusBadRequest) | 96 | return c.NoContent(http.StatusBadRequest) |
80 | } | 97 | } |
81 | 98 | ||
@@ -96,11 +113,13 @@ func (a *LoginController[T]) HandleFinish(c echo.Context) error { | |||
96 | authSession, err := a.AuthSessions.GetByUserCode(ctx, code.Code) | 113 | authSession, err := a.AuthSessions.GetByUserCode(ctx, code.Code) |
97 | if err != nil { | 114 | if err != nil { |
98 | a.Logger.Errorf("No auth session exists") | 115 | a.Logger.Errorf("No auth session exists") |
116 | loginError.With(prometheus.Labels{"type": "no_session_for_code"}).Inc() | ||
99 | return c.NoContent(http.StatusUnauthorized) | 117 | return c.NoContent(http.StatusUnauthorized) |
100 | } | 118 | } |
101 | 119 | ||
102 | if authSession.AccessCode != "" { | 120 | if authSession.AccessCode != "" { |
103 | a.Logger.Errorf("Session is already authenticated") | 121 | a.Logger.Errorf("Session is already authenticated") |
122 | loginError.With(prometheus.Labels{"type": "already_authenticated"}).Inc() | ||
104 | return c.NoContent(http.StatusUnauthorized) | 123 | return c.NoContent(http.StatusUnauthorized) |
105 | } | 124 | } |
106 | 125 | ||
@@ -113,5 +132,6 @@ func (a *LoginController[T]) HandleFinish(c echo.Context) error { | |||
113 | return c.NoContent(http.StatusInternalServerError) | 132 | return c.NoContent(http.StatusInternalServerError) |
114 | } | 133 | } |
115 | 134 | ||
135 | loginSuccess.Inc() | ||
116 | return c.NoContent(http.StatusOK) | 136 | return c.NoContent(http.StatusOK) |
117 | } | 137 | } |
diff --git a/app/controllers/oauth2_device.go b/app/controllers/oauth2_device.go index 0ddf653..c431495 100644 --- a/app/controllers/oauth2_device.go +++ b/app/controllers/oauth2_device.go | |||
@@ -9,7 +9,23 @@ import ( | |||
9 | 9 | ||
10 | "code.crute.us/mcrute/ssh-proxy/app" | 10 | "code.crute.us/mcrute/ssh-proxy/app" |
11 | "code.crute.us/mcrute/ssh-proxy/app/models" | 11 | "code.crute.us/mcrute/ssh-proxy/app/models" |
12 | |||
12 | "github.com/labstack/echo/v4" | 13 | "github.com/labstack/echo/v4" |
14 | "github.com/prometheus/client_golang/prometheus" | ||
15 | "github.com/prometheus/client_golang/prometheus/promauto" | ||
16 | ) | ||
17 | |||
18 | var ( | ||
19 | oauth2DeviceError = promauto.NewCounterVec(prometheus.CounterOpts{ | ||
20 | Namespace: "ssh_proxy", | ||
21 | Name: "oauth2_device_error", | ||
22 | Help: "Total number of errors during oauth2 device operations", | ||
23 | }, []string{"type"}) | ||
24 | oauth2DeviceSuccess = promauto.NewCounter(prometheus.CounterOpts{ | ||
25 | Namespace: "ssh_proxy", | ||
26 | Name: "oauth2_device_success", | ||
27 | Help: "Total number of successful oauth2 device auths", | ||
28 | }) | ||
13 | ) | 29 | ) |
14 | 30 | ||
15 | func badRequest(c echo.Context, e models.AuthorizationError, d string) error { | 31 | func badRequest(c echo.Context, e models.AuthorizationError, d string) error { |
@@ -40,15 +56,18 @@ func (a *OAuth2DeviceController[T]) HandleStart(c echo.Context) error { | |||
40 | client, err := a.OauthClients.Get(ctx, form.ClientId) | 56 | client, err := a.OauthClients.Get(ctx, form.ClientId) |
41 | if err != nil { | 57 | if err != nil { |
42 | a.Logger.Errorf("Unable to find client ID '%s': %s", form.ClientId, err) | 58 | a.Logger.Errorf("Unable to find client ID '%s': %s", form.ClientId, err) |
59 | oauth2DeviceError.With(prometheus.Labels{"type": "invalid_client_id"}).Inc() | ||
43 | return badRequest(c, models.ErrUnauthorizedClient, "") | 60 | return badRequest(c, models.ErrUnauthorizedClient, "") |
44 | } | 61 | } |
45 | 62 | ||
46 | if len(form.Challenge) <= 16 { | 63 | if len(form.Challenge) <= 16 { |
64 | oauth2DeviceError.With(prometheus.Labels{"type": "challenge_length"}).Inc() | ||
47 | return badRequest(c, models.ErrInvalidRequest, | 65 | return badRequest(c, models.ErrInvalidRequest, |
48 | "code_challenge is too short, minimum length is 16 bytes") | 66 | "code_challenge is too short, minimum length is 16 bytes") |
49 | } | 67 | } |
50 | 68 | ||
51 | if form.ChallengeMethod != models.ChallengeS256 { | 69 | if form.ChallengeMethod != models.ChallengeS256 { |
70 | oauth2DeviceError.With(prometheus.Labels{"type": "challenge_type"}).Inc() | ||
52 | return badRequest(c, models.ErrInvalidRequest, | 71 | return badRequest(c, models.ErrInvalidRequest, |
53 | "code_challenge_method invalid, only S256 supported") | 72 | "code_challenge_method invalid, only S256 supported") |
54 | } | 73 | } |
@@ -58,11 +77,13 @@ func (a *OAuth2DeviceController[T]) HandleStart(c echo.Context) error { | |||
58 | session.SetScopeString(form.Scope) | 77 | session.SetScopeString(form.Scope) |
59 | 78 | ||
60 | if !session.HasAnyScopes() { | 79 | if !session.HasAnyScopes() { |
80 | oauth2DeviceError.With(prometheus.Labels{"type": "no_scopes"}).Inc() | ||
61 | return badRequest(c, models.ErrInvalidRequest, "one or more scopes required") | 81 | return badRequest(c, models.ErrInvalidRequest, "one or more scopes required") |
62 | } | 82 | } |
63 | 83 | ||
64 | for _, s := range session.Scope { | 84 | for _, s := range session.Scope { |
65 | if s != "ssh:proxy" && s != "ca:issue" { | 85 | if s != "ssh:proxy" && s != "ca:issue" { |
86 | oauth2DeviceError.With(prometheus.Labels{"type": "invalid_scope"}).Inc() | ||
66 | return badRequest(c, models.ErrInvalidScope, fmt.Sprintf("scope %s is not recognized", s)) | 87 | return badRequest(c, models.ErrInvalidScope, fmt.Sprintf("scope %s is not recognized", s)) |
67 | } | 88 | } |
68 | } | 89 | } |
@@ -93,27 +114,33 @@ func (a *OAuth2DeviceController[T]) HandleToken(c echo.Context) error { | |||
93 | 114 | ||
94 | session, err := a.AuthSessions.Get(ctx, form.DeviceCode) | 115 | session, err := a.AuthSessions.Get(ctx, form.DeviceCode) |
95 | if err != nil { | 116 | if err != nil { |
117 | oauth2DeviceError.With(prometheus.Labels{"type": "no_auth_session"}).Inc() | ||
96 | return c.NoContent(http.StatusNotFound) | 118 | return c.NoContent(http.StatusNotFound) |
97 | } | 119 | } |
98 | 120 | ||
99 | if form.GrantType != models.DEVICE_CODE_GRANT_TYPE { | 121 | if form.GrantType != models.DEVICE_CODE_GRANT_TYPE { |
122 | oauth2DeviceError.With(prometheus.Labels{"type": "invalid_grant_type"}).Inc() | ||
100 | return badRequest(c, models.ErrUnsupportedGrantType, "") | 123 | return badRequest(c, models.ErrUnsupportedGrantType, "") |
101 | } | 124 | } |
102 | 125 | ||
103 | if subtle.ConstantTimeCompare([]byte(session.ClientId), []byte(form.ClientId)) != 1 { | 126 | if subtle.ConstantTimeCompare([]byte(session.ClientId), []byte(form.ClientId)) != 1 { |
127 | oauth2DeviceError.With(prometheus.Labels{"type": "client_id_mismatch"}).Inc() | ||
104 | return badRequest(c, models.ErrUnauthorizedClient, "") | 128 | return badRequest(c, models.ErrUnauthorizedClient, "") |
105 | } | 129 | } |
106 | 130 | ||
107 | if time.Now().After(session.Expires) { | 131 | if time.Now().After(session.Expires) { |
132 | oauth2DeviceError.With(prometheus.Labels{"type": "expired_session"}).Inc() | ||
108 | return badRequest(c, models.ErrExpiredToken, "") | 133 | return badRequest(c, models.ErrExpiredToken, "") |
109 | } | 134 | } |
110 | 135 | ||
111 | verifier := &models.PKCEChallenge{Verifier: form.CodeVerifier} | 136 | verifier := &models.PKCEChallenge{Verifier: form.CodeVerifier} |
112 | if verifier.EqualString(session.Challenge) { | 137 | if verifier.EqualString(session.Challenge) { |
138 | oauth2DeviceError.With(prometheus.Labels{"type": "pkce_mismatch"}).Inc() | ||
113 | return badRequest(c, models.ErrInvalidGrant, "") // Per RFC7636 4.6 | 139 | return badRequest(c, models.ErrInvalidGrant, "") // Per RFC7636 4.6 |
114 | } | 140 | } |
115 | 141 | ||
116 | if session.IsRegistration { | 142 | if session.IsRegistration { |
143 | oauth2DeviceError.With(prometheus.Labels{"type": "is_registration_session"}).Inc() | ||
117 | return badRequest(c, models.ErrInvalidGrant, "") | 144 | return badRequest(c, models.ErrInvalidGrant, "") |
118 | } | 145 | } |
119 | 146 | ||
@@ -121,6 +148,7 @@ func (a *OAuth2DeviceController[T]) HandleToken(c echo.Context) error { | |||
121 | return badRequest(c, models.ErrAuthorizationPending, "") | 148 | return badRequest(c, models.ErrAuthorizationPending, "") |
122 | } | 149 | } |
123 | 150 | ||
151 | oauth2DeviceSuccess.Inc() | ||
124 | return c.JSON(http.StatusOK, models.AccessTokenResponse{ | 152 | return c.JSON(http.StatusOK, models.AccessTokenResponse{ |
125 | AccessToken: session.AccessCode, | 153 | AccessToken: session.AccessCode, |
126 | TokenType: "Bearer", | 154 | TokenType: "Bearer", |
diff --git a/app/controllers/proxy.go b/app/controllers/proxy.go index c8345e8..9e3ec13 100644 --- a/app/controllers/proxy.go +++ b/app/controllers/proxy.go | |||
@@ -12,6 +12,21 @@ import ( | |||
12 | 12 | ||
13 | "github.com/gorilla/websocket" | 13 | "github.com/gorilla/websocket" |
14 | "github.com/labstack/echo/v4" | 14 | "github.com/labstack/echo/v4" |
15 | "github.com/prometheus/client_golang/prometheus" | ||
16 | "github.com/prometheus/client_golang/prometheus/promauto" | ||
17 | ) | ||
18 | |||
19 | var ( | ||
20 | proxyError = promauto.NewCounterVec(prometheus.CounterOpts{ | ||
21 | Namespace: "ssh_proxy", | ||
22 | Name: "proxy_error", | ||
23 | Help: "Total number of errors during proxy setup operation", | ||
24 | }, []string{"type"}) | ||
25 | proxySuccess = promauto.NewCounter(prometheus.CounterOpts{ | ||
26 | Namespace: "ssh_proxy", | ||
27 | Name: "proxy_success", | ||
28 | Help: "Total number of successful proxy sessions", | ||
29 | }) | ||
15 | ) | 30 | ) |
16 | 31 | ||
17 | type ProxyHandler struct { | 32 | type ProxyHandler struct { |
@@ -37,6 +52,7 @@ func (h *ProxyHandler) authorizeRequest(c echo.Context) error { | |||
37 | } | 52 | } |
38 | 53 | ||
39 | if !session.HasScope("ssh:proxy") { | 54 | if !session.HasScope("ssh:proxy") { |
55 | proxyError.With(prometheus.Labels{"type": "token_missing_scope"}).Inc() | ||
40 | return fmt.Errorf("Authorized session does not have scope ssh:proxy") | 56 | return fmt.Errorf("Authorized session does not have scope ssh:proxy") |
41 | } | 57 | } |
42 | 58 | ||
@@ -46,6 +62,7 @@ func (h *ProxyHandler) authorizeRequest(c echo.Context) error { | |||
46 | return nil | 62 | return nil |
47 | } | 63 | } |
48 | 64 | ||
65 | proxyError.With(prometheus.Labels{"type": "not_authorized"}).Inc() | ||
49 | return fmt.Errorf("User %s not authorized for host %s", session.UserId, host) | 66 | return fmt.Errorf("User %s not authorized for host %s", session.UserId, host) |
50 | } | 67 | } |
51 | 68 | ||
@@ -70,6 +87,8 @@ func (h *ProxyHandler) Handle(c echo.Context) error { | |||
70 | errc := make(chan error) | 87 | errc := make(chan error) |
71 | ws := &proxy.WebsocketReadWriter{W: wsconn} | 88 | ws := &proxy.WebsocketReadWriter{W: wsconn} |
72 | 89 | ||
90 | proxySuccess.Inc() | ||
91 | |||
73 | go proxy.CopyWithErrors(proxyconn, ws, errc) | 92 | go proxy.CopyWithErrors(proxyconn, ws, errc) |
74 | go proxy.CopyWithErrors(ws, proxyconn, errc) | 93 | go proxy.CopyWithErrors(ws, proxyconn, errc) |
75 | 94 | ||
diff --git a/app/controllers/register.go b/app/controllers/register.go index 7c1a0f3..312daae 100644 --- a/app/controllers/register.go +++ b/app/controllers/register.go | |||
@@ -15,6 +15,21 @@ import ( | |||
15 | "github.com/go-webauthn/webauthn/protocol" | 15 | "github.com/go-webauthn/webauthn/protocol" |
16 | "github.com/go-webauthn/webauthn/webauthn" | 16 | "github.com/go-webauthn/webauthn/webauthn" |
17 | "github.com/labstack/echo/v4" | 17 | "github.com/labstack/echo/v4" |
18 | "github.com/prometheus/client_golang/prometheus" | ||
19 | "github.com/prometheus/client_golang/prometheus/promauto" | ||
20 | ) | ||
21 | |||
22 | var ( | ||
23 | registerError = promauto.NewCounterVec(prometheus.CounterOpts{ | ||
24 | Namespace: "ssh_proxy", | ||
25 | Name: "register_error", | ||
26 | Help: "Total number of errors during registration", | ||
27 | }, []string{"type"}) | ||
28 | registerSuccess = promauto.NewCounter(prometheus.CounterOpts{ | ||
29 | Namespace: "ssh_proxy", | ||
30 | Name: "register_success", | ||
31 | Help: "Total number of successful registrations", | ||
32 | }) | ||
18 | ) | 33 | ) |
19 | 34 | ||
20 | type RegisterController[T app.AppSession] struct { | 35 | type RegisterController[T app.AppSession] struct { |
@@ -32,18 +47,22 @@ func (a *RegisterController[T]) validateRequest(ctx context.Context, u *models.U | |||
32 | 47 | ||
33 | authSession, err := a.AuthSessions.GetByUserCode(ctx, code) | 48 | authSession, err := a.AuthSessions.GetByUserCode(ctx, code) |
34 | if err != nil { | 49 | if err != nil { |
50 | registerError.With(prometheus.Labels{"type": "no_user_for_code"}).Inc() | ||
35 | return nil, fmt.Errorf("No auth session exists") | 51 | return nil, fmt.Errorf("No auth session exists") |
36 | } | 52 | } |
37 | 53 | ||
38 | if time.Now().After(authSession.Expires) { | 54 | if time.Now().After(authSession.Expires) { |
55 | registerError.With(prometheus.Labels{"type": "session_expired"}).Inc() | ||
39 | return nil, fmt.Errorf("Session is expired") | 56 | return nil, fmt.Errorf("Session is expired") |
40 | } | 57 | } |
41 | 58 | ||
42 | if !authSession.IsRegistration { | 59 | if !authSession.IsRegistration { |
60 | registerError.With(prometheus.Labels{"type": "incorrect_session_type"}).Inc() | ||
43 | return nil, fmt.Errorf("Session is not an invitation to register") | 61 | return nil, fmt.Errorf("Session is not an invitation to register") |
44 | } | 62 | } |
45 | 63 | ||
46 | if authSession.UserId != u.Username { | 64 | if authSession.UserId != u.Username { |
65 | registerError.With(prometheus.Labels{"type": "username_mismatch"}).Inc() | ||
47 | return nil, fmt.Errorf("Session not valid for this user") | 66 | return nil, fmt.Errorf("Session not valid for this user") |
48 | } | 67 | } |
49 | 68 | ||
@@ -56,6 +75,7 @@ func (a *RegisterController[T]) HandleStart(c echo.Context) error { | |||
56 | user, err := a.Users.Get(ctx, c.Param("username")) | 75 | user, err := a.Users.Get(ctx, c.Param("username")) |
57 | if err != nil { | 76 | if err != nil { |
58 | a.Logger.Errorf("Error getting user: %s", err) | 77 | a.Logger.Errorf("Error getting user: %s", err) |
78 | registerError.With(prometheus.Labels{"type": "no_user"}).Inc() | ||
59 | return c.NoContent(http.StatusNotFound) | 79 | return c.NoContent(http.StatusNotFound) |
60 | } | 80 | } |
61 | 81 | ||
@@ -111,6 +131,7 @@ func (a *RegisterController[T]) HandleFinish(c echo.Context) error { | |||
111 | // session in case of other errors | 131 | // session in case of other errors |
112 | if err := a.AuthSessions.Delete(ctx, authSession); err != nil { | 132 | if err := a.AuthSessions.Delete(ctx, authSession); err != nil { |
113 | a.Logger.Errorf("Error deleting auth session: %s", err) | 133 | a.Logger.Errorf("Error deleting auth session: %s", err) |
134 | registerError.With(prometheus.Labels{"type": "db_delete_session"}).Inc() | ||
114 | return c.NoContent(http.StatusInternalServerError) | 135 | return c.NoContent(http.StatusInternalServerError) |
115 | } | 136 | } |
116 | 137 | ||
@@ -141,5 +162,6 @@ func (a *RegisterController[T]) HandleFinish(c echo.Context) error { | |||
141 | return c.NoContent(http.StatusInternalServerError) | 162 | return c.NoContent(http.StatusInternalServerError) |
142 | } | 163 | } |
143 | 164 | ||
165 | registerSuccess.Inc() | ||
144 | return c.NoContent(http.StatusOK) | 166 | return c.NoContent(http.StatusOK) |
145 | } | 167 | } |
@@ -15,6 +15,7 @@ require ( | |||
15 | github.com/gorilla/websocket v1.5.0 | 15 | github.com/gorilla/websocket v1.5.0 |
16 | github.com/labstack/echo/v4 v4.6.1 | 16 | github.com/labstack/echo/v4 v4.6.1 |
17 | github.com/mdp/qrterminal v1.0.1 | 17 | github.com/mdp/qrterminal v1.0.1 |
18 | github.com/prometheus/client_golang v1.11.0 | ||
18 | github.com/spf13/cobra v1.7.0 | 19 | github.com/spf13/cobra v1.7.0 |
19 | go.mongodb.org/mongo-driver v1.7.4 | 20 | go.mongodb.org/mongo-driver v1.7.4 |
20 | golang.org/x/crypto v0.11.0 | 21 | golang.org/x/crypto v0.11.0 |
@@ -75,7 +76,6 @@ require ( | |||
75 | github.com/oklog/run v1.0.0 // indirect | 76 | github.com/oklog/run v1.0.0 // indirect |
76 | github.com/pierrec/lz4 v2.5.2+incompatible // indirect | 77 | github.com/pierrec/lz4 v2.5.2+incompatible // indirect |
77 | github.com/pkg/errors v0.9.1 // indirect | 78 | github.com/pkg/errors v0.9.1 // indirect |
78 | github.com/prometheus/client_golang v1.11.0 // indirect | ||
79 | github.com/prometheus/client_model v0.2.0 // indirect | 79 | github.com/prometheus/client_model v0.2.0 // indirect |
80 | github.com/prometheus/common v0.32.1 // indirect | 80 | github.com/prometheus/common v0.32.1 // indirect |
81 | github.com/prometheus/procfs v0.6.0 // indirect | 81 | github.com/prometheus/procfs v0.6.0 // indirect |