Skip to content

Commit e4abd33

Browse files
committed
by now, challenge solving is mostly implemented
1 parent c8840bc commit e4abd33

7 files changed

Lines changed: 60 additions & 58 deletions

File tree

cmd/certmaker/main.go

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ func main() {
4848
fmt.Println("could not execute cleanup func:", err.Error())
4949
}
5050
}()
51+
if err != nil {
52+
fmt.Println("could not set up logging:", err.Error())
53+
return
54+
}
5155

5256
logger.WithFields(logrus.Fields{"application": "certmaker", "version": Version, "versionDate": VersionDate}).Info("app info")
5357

@@ -81,9 +85,14 @@ func main() {
8185
}
8286
// create database service
8387
ds, err := dbservice.New(config)
88+
if err != nil {
89+
logger.WithField("error", err.Error()).Error("could not set up database service")
90+
return
91+
}
92+
8493
err = ds.AutoMigrate()
8594
if err != nil {
86-
logger.WithField("error", err.Error()).Error("could not execute auto migrations")
95+
logger.WithField("error", err.Error()).Error("could not execute schema setup")
8796
return
8897
}
8998

@@ -148,14 +157,14 @@ func setupRoutes(cfg *configuration.AppConfig, logger *logrus.Entry, dbSvc *dbse
148157
Handler(http.StripPrefix(staticDir, http.FileServer(http.FS(assets.GetStaticFS()))))
149158

150159
defaultRouter := router.PathPrefix("/").Subrouter()
151-
defaultRouter.Use(mh.WithSession)
160+
defaultRouter.Use(mh.RequireSession)
152161
defaultRouter.HandleFunc("/", bh.IndexHandler).Methods(http.MethodGet)
153162
defaultRouter.HandleFunc("/favicon.ico", bh.FaviconHandler)
154163
defaultRouter.HandleFunc("/root-certificate/download", bh.RootCertificateDownloadHandler).Methods(http.MethodGet)
155164
defaultRouter.HandleFunc("/privatekey/{id}/download", bh.PrivateKeyDownloadHandler).Methods(http.MethodGet)
156165

157166
userRouter := router.PathPrefix("/user").Subrouter()
158-
userRouter.Use(mh.WithSession)
167+
userRouter.Use(mh.RequireSession)
159168
userRouter.HandleFunc("/profile", bh.ProfileHandler)
160169
userRouter.HandleFunc("/profile/edit", bh.ProfileEditHandler)
161170
userRouter.HandleFunc("/regenerate-key", bh.ProfileRegenerateKeyHandler)
@@ -166,15 +175,15 @@ func setupRoutes(cfg *configuration.AppConfig, logger *logrus.Entry, dbSvc *dbse
166175
authRouter.HandleFunc("/register", bh.RegistrationHandler).Methods(http.MethodGet, http.MethodPost)
167176

168177
certRouter := router.PathPrefix("/certificate").Subrouter()
169-
certRouter.Use(mh.WithSession)
178+
certRouter.Use(mh.RequireSession)
170179
certRouter.HandleFunc("/list", bh.CertificateListHandler).Methods(http.MethodGet)
171180
certRouter.HandleFunc("/add", bh.CertificateAddHandler).Methods(http.MethodGet, http.MethodPost)
172181
certRouter.HandleFunc("/add-with-csr", bh.AddCertificateFromCSRHandler).Methods(http.MethodGet, http.MethodPost)
173182
certRouter.HandleFunc("/{id}/revoke", bh.RevokeCertificateHandler).Methods(http.MethodGet, http.MethodPost)
174183
certRouter.HandleFunc("/{id}/download", bh.CertificateDownloadHandler).Methods(http.MethodGet)
175184

176185
adminRouter := router.PathPrefix("/admin").Subrouter()
177-
adminRouter.Use(mh.WithSession, mh.RequireAdmin)
186+
adminRouter.Use(mh.RequireSession, mh.RequireAdmin)
178187
adminRouter.HandleFunc("/settings", bh.AdminSettingsHandler).Methods(http.MethodGet, http.MethodPost)
179188
adminRouter.HandleFunc("/user/list", bh.AdminUserListHandler).Methods(http.MethodGet)
180189
adminRouter.HandleFunc("/user/add", bh.AdminUserAddHandler).Methods(http.MethodGet, http.MethodPost)
@@ -183,9 +192,9 @@ func setupRoutes(cfg *configuration.AppConfig, logger *logrus.Entry, dbSvc *dbse
183192
}
184193

185194
apiRouter := router.PathPrefix("/api/v1").Subrouter()
186-
apiRouter.Use(mh.WithToken)
195+
apiRouter.Use(mh.RequireToken)
187196
apiRouter.HandleFunc("/root-certificate/obtain", bh.APIRootCertificateDownloadHandler).Methods(http.MethodGet)
188-
apiRouter.HandleFunc("/certificate/request", bh.APIRequestCertificateWithSimpleRequestHandler).Methods(http.MethodPost)
197+
apiRouter.HandleFunc("/certificate/request-with-simplerequest", bh.APIRequestCertificateWithSimpleRequestHandler).Methods(http.MethodPost)
189198
apiRouter.HandleFunc("/certificate/request-with-csr", bh.APIRequestCertificateWithCSRHandler).Methods(http.MethodPost)
190199
apiRouter.HandleFunc("/certificate/{sn}/revoke", bh.APIRevokeCertificateHandler).Methods(http.MethodGet)
191200
apiRouter.HandleFunc("/certificate/{id}/obtain", bh.APIObtainCertificateHandler).Methods(http.MethodGet)
@@ -194,8 +203,8 @@ func setupRoutes(cfg *configuration.AppConfig, logger *logrus.Entry, dbSvc *dbse
194203
apiRouter.HandleFunc("/dns-01/{challengeID}/solve", bh.APISolveHTTP01ChallengeHandler).Methods(http.MethodGet)
195204

196205
ocspRouter := router.PathPrefix("/ocsp").Subrouter()
197-
ocspRouter.HandleFunc("/ocsp/{base64}", bh.APIOSCPRequestHandler).Methods(http.MethodGet, http.MethodPost)
198-
ocspRouter.HandleFunc("/ocsp", bh.APIOSCPRequestHandler).Methods(http.MethodGet, http.MethodPost)
206+
ocspRouter.HandleFunc("/{base64}", bh.APIOCSPRequestHandler).Methods(http.MethodGet)
207+
ocspRouter.HandleFunc("/", bh.APIOCSPRequestHandler).Methods(http.MethodPost)
199208

200209
return router
201210
}
Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package entity
22

33
type CertificateResponse struct {
4-
CertificatePem string `json:"certificate_pem,omitempty"`
5-
PrivateKeyPem string `json:"private_key_pem,omitempty"`
6-
HTTP01Challenge string `json:"http01_challenge,omitempty"`
7-
DNS01Challenge string `json:"dns01_challenge,omitempty"`
4+
CertificatePEM string `json:"certificate_pem,omitempty"`
5+
PrivateKeyPEM string `json:"private_key_pem,omitempty"`
6+
HTTP01Challenge bool `json:"http01_challenge,omitempty"`
7+
DNS01Challenge bool `json:"dns01_challenge,omitempty"`
8+
ChallengeID string `json:"challenge_id,omitempty"`
9+
ChallengeToken string `json:"challenge_token,omitempty"`
810
Error string `json:"error,omitempty"`
911
}

internal/entity/challenge.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ type Challenge struct {
1111
gorm.Model
1212
CreatedFor uint
1313
RequestInfoID uint
14-
PublicID string `gorm:"index:,unique"`
14+
ChallengeID string `gorm:"index:,unique"`
1515
ChallengeType string
1616
Token string
1717
ValidUntil time.Time

internal/entity/simpleRequest.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@ package entity
33
// SimpleRequest (not CSR) describes the content of a certificate request
44
// against the API
55
type SimpleRequest struct {
6-
Domains []string `json:"domains"`
7-
IPs []string `json:"ips"`
8-
EmailAddresses []string `json:"email_addresses"`
9-
Subject Subject `json:"subject,omitempty"`
10-
Days int `json:"days"`
6+
Domains []string `json:"domains"`
7+
IPs []string `json:"ips"`
8+
EmailAddresses []string `json:"email_addresses"`
9+
Subject Subject `json:"subject,omitempty"`
10+
Days int `json:"days"`
11+
PreferredChallenge string `json:"preferred_challenge,omitempty"`
1112
}
1213

1314
type Subject struct {

internal/handler/api.go

Lines changed: 25 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -86,32 +86,34 @@ func (bh *BaseHandler) APIRequestCertificateWithSimpleRequestHandler(w http.Resp
8686
ch := &entity.Challenge{
8787
CreatedFor: user.ID,
8888
RequestInfoID: ri.ID,
89-
PublicID: fmt.Sprintf("%d-%s", user.ID, security.GenerateToken(20)),
89+
ChallengeID: fmt.Sprintf("%d-%s", user.ID, security.GenerateToken(20)),
9090
ChallengeType: "http-01",
9191
ValidUntil: time.Now().Add(global.DefaultChallengeValidity),
92+
Token: security.GenerateToken(80),
9293
}
9394
if err = bh.DBSvc.AddChallenge(ch); err != nil {
9495
logger.Infof("error inserting challenge: %s\n", err.Error())
9596
w.WriteHeader(http.StatusInternalServerError)
9697
return
9798
}
98-
response.HTTP01Challenge = fmt.Sprintf(bh.Config.ServerHost+global.SolveHTTP01ChallengePath, ch.PublicID)
99+
response.HTTP01Challenge = true
99100
}
100101
if dnsChallengeEnabled := bh.DBSvc.GetSetting(global.SettingEnableDNS01Challenge); dnsChallengeEnabled == "true" {
101102
hasChallenge = true
102103
ch := &entity.Challenge{
103104
CreatedFor: user.ID,
104105
RequestInfoID: ri.ID,
105-
PublicID: fmt.Sprintf("%d-%s", user.ID, security.GenerateToken(20)),
106+
ChallengeID: fmt.Sprintf("%d-%s", user.ID, security.GenerateToken(20)),
106107
ChallengeType: "dns-01",
107108
ValidUntil: time.Now().Add(global.DefaultChallengeValidity),
109+
Token: security.GenerateToken(80),
108110
}
109111
if err = bh.DBSvc.AddChallenge(ch); err != nil {
110112
logger.Infof("error inserting challenge: %s\n", err.Error())
111113
w.WriteHeader(http.StatusInternalServerError)
112114
return
113115
}
114-
response.DNS01Challenge = fmt.Sprintf(bh.Config.ServerHost+global.SolvDNS01ChallengePath, ch.PublicID)
116+
response.DNS01Challenge = true
115117
}
116118

117119
if hasChallenge {
@@ -146,8 +148,8 @@ func (bh *BaseHandler) APIRequestCertificateWithSimpleRequestHandler(w http.Resp
146148
return
147149
}
148150

149-
response.CertificatePem = string(certBytes)
150-
response.PrivateKeyPem = string(keyBytes)
151+
response.CertificatePEM = string(certBytes)
152+
response.PrivateKeyPEM = string(keyBytes)
151153

152154
w.Header().Set("Content-Type", "application/json")
153155
w.WriteHeader(http.StatusCreated)
@@ -213,32 +215,34 @@ func (bh *BaseHandler) APIRequestCertificateWithCSRHandler(w http.ResponseWriter
213215
ch := &entity.Challenge{
214216
CreatedFor: user.ID,
215217
RequestInfoID: ri.ID,
216-
PublicID: fmt.Sprintf("%d-%s", user.ID, security.GenerateToken(20)),
218+
ChallengeID: fmt.Sprintf("%d-%s", user.ID, security.GenerateToken(20)),
217219
ChallengeType: "http-01",
218220
ValidUntil: time.Now().Add(global.DefaultChallengeValidity),
221+
Token: security.GenerateToken(80),
219222
}
220223
if err = bh.DBSvc.AddChallenge(ch); err != nil {
221224
logger.Infof("error inserting challenge: %s\n", err.Error())
222225
w.WriteHeader(http.StatusInternalServerError)
223226
return
224227
}
225-
response.HTTP01Challenge = fmt.Sprintf(bh.Config.ServerHost+global.SolveHTTP01ChallengePath, ch.PublicID)
228+
response.HTTP01Challenge = true
226229
}
227230
if dnsChallengeEnabled := bh.DBSvc.GetSetting(global.SettingEnableDNS01Challenge); dnsChallengeEnabled == "true" {
228231
hasChallenge = true
229232
ch := &entity.Challenge{
230233
CreatedFor: user.ID,
231234
RequestInfoID: ri.ID,
232-
PublicID: fmt.Sprintf("%d-%s", user.ID, security.GenerateToken(20)),
235+
ChallengeID: fmt.Sprintf("%d-%s", user.ID, security.GenerateToken(20)),
233236
ChallengeType: "dns-01",
234237
ValidUntil: time.Now().Add(global.DefaultChallengeValidity),
238+
Token: security.GenerateToken(80),
235239
}
236240
if err = bh.DBSvc.AddChallenge(ch); err != nil {
237241
logger.Infof("error inserting challenge: %s\n", err.Error())
238242
w.WriteHeader(http.StatusInternalServerError)
239243
return
240244
}
241-
response.DNS01Challenge = fmt.Sprintf(bh.Config.ServerHost+global.SolvDNS01ChallengePath, ch.PublicID)
245+
response.DNS01Challenge = true
242246
}
243247

244248
if hasChallenge {
@@ -273,7 +277,7 @@ func (bh *BaseHandler) APIRequestCertificateWithCSRHandler(w http.ResponseWriter
273277
return
274278
}
275279

276-
response.CertificatePem = string(certBytes)
280+
response.CertificatePEM = string(certBytes)
277281

278282
w.Header().Set("Content-Type", "application/json")
279283
w.WriteHeader(http.StatusCreated)
@@ -347,9 +351,9 @@ func (bh *BaseHandler) APIObtainPrivateKeyHandler(w http.ResponseWriter, r *http
347351
}
348352
}
349353

350-
// APIOSCPRequestHandler responds to OCSP requests with whether the certificate
354+
// APIOCSPRequestHandler responds to OCSP requests with whether the certificate
351355
// in question is revoked or not
352-
func (bh *BaseHandler) APIOSCPRequestHandler(w http.ResponseWriter, r *http.Request) {
356+
func (bh *BaseHandler) APIOCSPRequestHandler(w http.ResponseWriter, r *http.Request) {
353357
defer r.Body.Close()
354358
var (
355359
err error
@@ -363,27 +367,13 @@ func (bh *BaseHandler) APIOSCPRequestHandler(w http.ResponseWriter, r *http.Requ
363367
return
364368
}
365369

366-
//if r.Header.Get("Accept") != "application/ocsp-response" {
367-
// logger.Debug("incorrect Accept header: " + r.Header.Get("Accept"))
368-
// w.WriteHeader(http.StatusBadRequest)
369-
// return
370-
//}
371-
372-
//if r.Header.Get("Host") == "" {
373-
// logger.Debug("incorrect Host header: empty")
374-
// w.WriteHeader(http.StatusBadRequest)
375-
// return
376-
//}
377-
378370
w.Header().Set("Content-Type", "application/ocsp-response")
379371

380-
b64 := vars["base64"]
381-
382-
var request []byte
372+
var requestData []byte
383373
switch r.Method {
384374
case http.MethodPost:
385375
logger.Debug("POST request")
386-
request, err = io.ReadAll(r.Body)
376+
requestData, err = io.ReadAll(r.Body)
387377
if err != nil {
388378
logger.Debugf("could not read request body: %s", err.Error())
389379
w.WriteHeader(http.StatusBadRequest)
@@ -392,15 +382,15 @@ func (bh *BaseHandler) APIOSCPRequestHandler(w http.ResponseWriter, r *http.Requ
392382
_ = r.Body.Close()
393383
case http.MethodGet:
394384
logger.Debug("GET request")
395-
request, err = base64.StdEncoding.DecodeString(b64)
385+
requestData, err = base64.StdEncoding.DecodeString(vars["base64"])
396386
if err != nil {
397387
logger.Debugf("could not base64 decode: %s", err.Error())
398388
w.WriteHeader(http.StatusBadRequest)
399389
return
400390
}
401391
}
402392

403-
ocspReq, err := ocsp.ParseRequest(request)
393+
ocspReq, err := ocsp.ParseRequest(requestData)
404394
if err != nil {
405395
logger.Debug("could not parse OCSP Request: " + err.Error())
406396
w.WriteHeader(http.StatusBadRequest)
@@ -644,9 +634,9 @@ func (bh *BaseHandler) APISolveHTTP01ChallengeHandler(w http.ResponseWriter, r *
644634
}
645635

646636
// set up response
647-
response.CertificatePem = string(certBytes)
637+
response.CertificatePEM = string(certBytes)
648638
if !fromCSR {
649-
response.PrivateKeyPem = string(keyBytes)
639+
response.PrivateKeyPEM = string(keyBytes)
650640
}
651641

652642
w.Header().Set("Content-Type", "application/json")
@@ -799,9 +789,9 @@ func (bh *BaseHandler) APISolveDNS01ChallengeHandler(w http.ResponseWriter, r *h
799789
}
800790

801791
// set up response
802-
response.CertificatePem = string(certBytes)
792+
response.CertificatePEM = string(certBytes)
803793
if !fromCSR {
804-
response.PrivateKeyPem = string(keyBytes)
794+
response.PrivateKeyPEM = string(keyBytes)
805795
}
806796

807797
w.Header().Set("Content-Type", "application/json")

internal/middleware/api.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ import (
55
"net/http"
66
)
77

8-
// WithToken makes sure that, if enabled, a client must provide his API key
8+
// RequireToken makes sure that, if enabled, a client must provide his API key
99
// within an HTTP header
10-
func (mh *MWHandler) WithToken(next http.Handler) http.Handler {
10+
func (mh *MWHandler) RequireToken(next http.Handler) http.Handler {
1111
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
1212
logger := mh.ContextLogger("middleware")
1313

internal/middleware/ui.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ import (
1111
"gorm.io/gorm"
1212
)
1313

14-
// WithSession requires the client to have a valid session
14+
// RequireSession requires the client to have a valid session
1515
// (to be logged in)
16-
func (mh *MWHandler) WithSession(next http.Handler) http.Handler {
16+
func (mh *MWHandler) RequireSession(next http.Handler) http.Handler {
1717
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
1818
logger := mh.ContextLogger("middleware")
1919

0 commit comments

Comments
 (0)