summaryrefslogtreecommitdiff
path: root/app/controllers/ca.go
diff options
context:
space:
mode:
Diffstat (limited to 'app/controllers/ca.go')
-rw-r--r--app/controllers/ca.go22
1 files changed, 22 insertions, 0 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
19var (
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
17type CASecret struct { 32type 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}