Skip to content

Commit 80a856d

Browse files
committed
Add /auth/trouble end-point for certificate validation
1 parent 3eeec59 commit 80a856d

File tree

2 files changed

+110
-0
lines changed

2 files changed

+110
-0
lines changed

trouble.go

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package main
2+
3+
import (
4+
"crypto/x509"
5+
"encoding/json"
6+
"fmt"
7+
"html/template"
8+
"net/http"
9+
"time"
10+
11+
"github.com/dmwm/auth-proxy-server/cric"
12+
"github.com/dmwm/cmsauth"
13+
)
14+
15+
// Dummy check functions — replace with real logic
16+
func isCMSVOMember(cert *x509.Certificate) bool {
17+
// TODO: need proper check VO membership
18+
return true
19+
//return strings.Contains(cert.Subject.String(), "CMS")
20+
}
21+
22+
func userDetails(cert *x509.Certificate) (cmsauth.CricEntry, error) {
23+
dnParts := getDNParts(cert)
24+
rec, err := cric.FindUser(dnParts)
25+
if err != nil {
26+
return rec, err
27+
}
28+
return rec, nil
29+
}
30+
31+
func map2string(roles map[string][]string) string {
32+
data, err := json.MarshalIndent(roles, "", " ")
33+
if err != nil {
34+
return fmt.Sprintf("%+v", roles)
35+
}
36+
return string(data)
37+
}
38+
39+
var tmpl = template.Must(template.New("help").Parse(`
40+
<!DOCTYPE html>
41+
<html>
42+
<head><title>Certificate authentication help</title></head>
43+
<body>
44+
<h2>Certificate authentication help</h2>
45+
<p>Your browser offered valid DN '{{.DN}}'.</p>
46+
<p>Your certificate is valid from {{.NotBefore}} to {{.NotAfter}}; {{.DaysRemaining}} days of validity remain.</p>
47+
<p>Your certificate {{.Passed}} basic validation.</p>
48+
<p>Your certificate is {{.CMSVOMember}}.</p>
49+
<p>Your certificate is mapped to {{.Userdetails}} in CRIC database</p>
50+
<p>For more details please see <a href="https://twiki.cern.ch/twiki/bin/view/CMS/DQMGUIGridCertificate">certificate setup instructions</a> for the most commonly needed steps.</p>
51+
</body>
52+
</html>
53+
`))
54+
55+
func authTroubleHandler(w http.ResponseWriter, r *http.Request) {
56+
if r.TLS == nil || len(r.TLS.PeerCertificates) == 0 {
57+
http.Error(w, "No client certificate provided", http.StatusUnauthorized)
58+
return
59+
}
60+
61+
cert := r.TLS.PeerCertificates[0]
62+
dn := cert.Subject.String()
63+
notBefore := cert.NotBefore.UTC().Format("Jan 2 15:04:05 2006 GMT")
64+
notAfter := cert.NotAfter.UTC().Format("Jan 2 15:04:05 2006 GMT")
65+
daysRemaining := int(time.Until(cert.NotAfter).Hours() / 24)
66+
67+
// validation steps
68+
cmsVOMember := "CMS VO member"
69+
if !isCMSVOMember(cert) {
70+
cmsVOMember = "not CMS VO member"
71+
}
72+
passed := "passed"
73+
if daysRemaining < 0 {
74+
passed = "not passed"
75+
}
76+
77+
var details string
78+
if rec, err := userDetails(cert); err == nil {
79+
details = fmt.Sprintf("<br/><b>Name:</b> %s<br/><b>Login:</b> %s<br/><b>ID:</b> %v<br/><b>Roles:</b> %+v<br/><b>DNs:</b> %v<br/>",
80+
rec.Name, rec.Login, rec.ID, map2string(rec.Roles), rec.DNs)
81+
} else {
82+
details = err.Error()
83+
}
84+
85+
data := struct {
86+
DN string
87+
NotBefore string
88+
NotAfter string
89+
DaysRemaining int
90+
Userdetails template.HTML
91+
Passed string
92+
CMSVOMember string
93+
}{
94+
DN: dn,
95+
NotBefore: notBefore,
96+
NotAfter: notAfter,
97+
DaysRemaining: daysRemaining,
98+
Userdetails: template.HTML(details),
99+
Passed: passed,
100+
CMSVOMember: cmsVOMember,
101+
}
102+
103+
err := tmpl.Execute(w, data)
104+
if err != nil {
105+
http.Error(w, "Internal template error", http.StatusInternalServerError)
106+
}
107+
}

x509.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ func x509ProxyServer() {
117117
// rules handler
118118
http.HandleFunc(fmt.Sprintf("%s/rules", Config.Base), rulesHandler)
119119

120+
// trouble page
121+
http.HandleFunc("/auth/trouble", authTroubleHandler)
122+
120123
// start http server to serve metrics only
121124
if Config.MetricsPort > 0 {
122125
log.Println("Start x509 server metrics on port", Config.MetricsPort)

0 commit comments

Comments
 (0)