-
Notifications
You must be signed in to change notification settings - Fork 8
/
router_make.go
204 lines (153 loc) · 12.1 KB
/
router_make.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
package app
import (
"net/http"
"github.com/julienschmidt/httprouter"
)
// base path
const baseUrlPath = "/certwarden"
// backend api paths
const apiUrlPath = baseUrlPath + "/api"
const apiKeyDownloadUrlPath = apiUrlPath + "/v1/download"
// frontend React app path (e.g. Vite config `base`)
const frontendUrlPath = baseUrlPath + "/app"
// makeRouterAndRoutes creates the application's router and adds the routes. It also
// inserts the common CORS middleware before assigning the router to app
func (app *Application) makeRouterAndRoutes() {
router := &router{
logger: app.logger.SugaredLogger,
output: app.output,
auth: app.auth,
permittedCrossOrigins: app.config.CORSPermittedCrossOrigins,
r: httprouter.New(),
}
// health check (HEAD or GET) - insecure for docker probing
router.handleAPIRouteInsecure(http.MethodHead, apiUrlPath+"/health", healthHandler)
router.handleAPIRouteInsecure(http.MethodGet, apiUrlPath+"/health", healthHandler)
// app auth - insecure as these give clients the access_token to access secure routes
// validates with user/password
router.handleAPIRouteInsecure(http.MethodPost, apiUrlPath+"/v1/app/auth/login", app.auth.LoginUsingUserPwPayload)
// validates with cookie
router.handleAPIRouteInsecure(http.MethodPost, apiUrlPath+"/v1/app/auth/refresh", app.auth.RefreshUsingCookie)
// app auth - secure
router.handleAPIRouteSecure(http.MethodPut, apiUrlPath+"/v1/app/auth/changepassword", app.auth.ChangePassword)
router.handleAPIRouteSecure(http.MethodPost, apiUrlPath+"/v1/app/auth/logout", app.auth.Logout)
// status
router.handleAPIRouteSecure(http.MethodGet, apiUrlPath+"/status", app.statusHandler)
// app
router.handleAPIRouteSecure(http.MethodGet, apiUrlPath+"/v1/app/log", app.viewCurrentLogHandler)
router.handleAPIRouteSecure(http.MethodGet, apiUrlPath+"/v1/app/logs", app.downloadLogsHandler)
// app control
router.handleAPIRouteSecure(http.MethodPost, apiUrlPath+"/v1/app/control/shutdown", app.doShutdownHandler)
router.handleAPIRouteSecure(http.MethodPost, apiUrlPath+"/v1/app/control/restart", app.doRestartHandler)
// app updater
router.handleAPIRouteSecure(http.MethodGet, apiUrlPath+"/v1/app/updater/new-version", app.updater.GetNewVersionInfo)
router.handleAPIRouteSecure(http.MethodPost, apiUrlPath+"/v1/app/updater/new-version", app.updater.CheckForNewVersion)
// app backup and restore
router.handleAPIRouteSecure(http.MethodGet, apiUrlPath+"/v1/app/backup/disk", app.backup.ListDiskBackupsHandler)
router.handleAPIRouteSecureSensitive(http.MethodPost, apiUrlPath+"/v1/app/backup/disk", app.backup.MakeDiskBackupNowHandler)
router.handleAPIRouteSecureSensitive(http.MethodDelete, apiUrlPath+"/v1/app/backup/disk/:filename", app.backup.DeleteDiskBackupHandler)
router.handleAPIRouteSecureDownload(http.MethodGet, apiUrlPath+"/v1/app/backup", app.backup.DownloadBackupNowHandler)
router.handleAPIRouteSecureDownload(http.MethodGet, apiUrlPath+"/v1/app/backup/disk/:filename", app.backup.DownloadDiskBackupHandler)
// challenges (config)
// router.handleAPIRouteSecure(http.MethodGet, apiUrlPath+"/v1/app/challenges/providers/domains", app.challenges.Providers.GetAllDomains)
router.handleAPIRouteSecure(http.MethodGet, apiUrlPath+"/v1/app/challenges/providers/services", app.challenges.Providers.GetAllProviders)
router.handleAPIRouteSecure(http.MethodGet, apiUrlPath+"/v1/app/challenges/providers/services/:id", app.challenges.Providers.GetOneProvider)
router.handleAPIRouteSecure(http.MethodPost, apiUrlPath+"/v1/app/challenges/providers/services", app.challenges.Providers.CreateProvider)
router.handleAPIRouteSecure(http.MethodPut, apiUrlPath+"/v1/app/challenges/providers/services/:id", app.challenges.Providers.ModifyProvider)
router.handleAPIRouteSecure(http.MethodDelete, apiUrlPath+"/v1/app/challenges/providers/services/:id", app.challenges.Providers.DeleteProvider)
// acme_servers
router.handleAPIRouteSecure(http.MethodGet, apiUrlPath+"/v1/acmeservers", app.acmeServers.GetAllServers)
router.handleAPIRouteSecure(http.MethodGet, apiUrlPath+"/v1/acmeservers/:id", app.acmeServers.GetOneServer)
router.handleAPIRouteSecure(http.MethodPost, apiUrlPath+"/v1/acmeservers", app.acmeServers.PostNewServer)
router.handleAPIRouteSecure(http.MethodPut, apiUrlPath+"/v1/acmeservers/:id", app.acmeServers.PutServerUpdate)
router.handleAPIRouteSecure(http.MethodDelete, apiUrlPath+"/v1/acmeservers/:id", app.acmeServers.DeleteServer)
// private_keys
router.handleAPIRouteSecure(http.MethodGet, apiUrlPath+"/v1/privatekeys", app.keys.GetAllKeys)
router.handleAPIRouteSecure(http.MethodGet, apiUrlPath+"/v1/privatekeys/:id", app.keys.GetOneKey)
router.handleAPIRouteSecureDownload(http.MethodGet, apiUrlPath+"/v1/privatekeys/:id/download", app.keys.DownloadOneKey)
router.handleAPIRouteSecure(http.MethodPost, apiUrlPath+"/v1/privatekeys", app.keys.PostNewKey)
router.handleAPIRouteSecure(http.MethodPost, apiUrlPath+"/v1/privatekeys/:id/apikey", app.keys.StageNewApiKey)
router.handleAPIRouteSecure(http.MethodDelete, apiUrlPath+"/v1/privatekeys/:id/apikey", app.keys.RemoveOldApiKey)
router.handleAPIRouteSecure(http.MethodPut, apiUrlPath+"/v1/privatekeys/:id", app.keys.PutKeyUpdate)
router.handleAPIRouteSecure(http.MethodDelete, apiUrlPath+"/v1/privatekeys/:id", app.keys.DeleteKey)
// acme_accounts
router.handleAPIRouteSecure(http.MethodGet, apiUrlPath+"/v1/acmeaccounts", app.accounts.GetAllAccounts)
router.handleAPIRouteSecure(http.MethodGet, apiUrlPath+"/v1/acmeaccounts/:id", app.accounts.GetOneAccount)
router.handleAPIRouteSecure(http.MethodPost, apiUrlPath+"/v1/acmeaccounts", app.accounts.PostNewAccount)
router.handleAPIRouteSecure(http.MethodPut, apiUrlPath+"/v1/acmeaccounts/:id", app.accounts.PutNameDescAccount)
router.handleAPIRouteSecure(http.MethodPut, apiUrlPath+"/v1/acmeaccounts/:id/email", app.accounts.ChangeEmail)
router.handleAPIRouteSecure(http.MethodPut, apiUrlPath+"/v1/acmeaccounts/:id/key-change", app.accounts.RolloverKey)
router.handleAPIRouteSecure(http.MethodPost, apiUrlPath+"/v1/acmeaccounts/:id/register", app.accounts.NewAcmeAccount)
router.handleAPIRouteSecure(http.MethodPost, apiUrlPath+"/v1/acmeaccounts/:id/refresh", app.accounts.RefreshAcmeAccount)
router.handleAPIRouteSecure(http.MethodPost, apiUrlPath+"/v1/acmeaccounts/:id/deactivate", app.accounts.Deactivate)
router.handleAPIRouteSecure(http.MethodDelete, apiUrlPath+"/v1/acmeaccounts/:id", app.accounts.DeleteAccount)
// certificates
router.handleAPIRouteSecure(http.MethodGet, apiUrlPath+"/v1/certificates", app.certificates.GetAllCerts)
router.handleAPIRouteSecure(http.MethodGet, apiUrlPath+"/v1/certificates/:certid", app.certificates.GetOneCert)
router.handleAPIRouteSecure(http.MethodPost, apiUrlPath+"/v1/certificates", app.certificates.PostNewCert)
router.handleAPIRouteSecure(http.MethodPost, apiUrlPath+"/v1/certificates/:certid/apikey", app.certificates.StageNewApiKey)
router.handleAPIRouteSecure(http.MethodDelete, apiUrlPath+"/v1/certificates/:certid/apikey", app.certificates.RemoveOldApiKey)
router.handleAPIRouteSecure(http.MethodPost, apiUrlPath+"/v1/certificates/:certid/clientkey", app.certificates.MakeNewClientKey)
router.handleAPIRouteSecure(http.MethodDelete, apiUrlPath+"/v1/certificates/:certid/clientkey", app.certificates.DisableClientKey)
router.handleAPIRouteSecure(http.MethodPut, apiUrlPath+"/v1/certificates/:certid", app.certificates.PutDetailsCert)
router.handleAPIRouteSecure(http.MethodDelete, apiUrlPath+"/v1/certificates/:certid", app.certificates.DeleteCert)
// orders (for certificates)
router.handleAPIRouteSecure(http.MethodGet, apiUrlPath+"/v1/orders/currentvalid", app.orders.GetAllValidCurrentOrders)
router.handleAPIRouteSecure(http.MethodGet, apiUrlPath+"/v1/orders/fulfilling/status", app.orders.GetFulfillWorkStatus)
router.handleAPIRouteSecure(http.MethodGet, apiUrlPath+"/v1/orders/post-process/status", app.orders.GetPostProcessWorkStatus)
router.handleAPIRouteSecure(http.MethodGet, apiUrlPath+"/v1/certificates/:certid/orders", app.orders.GetCertOrders)
router.handleAPIRouteSecure(http.MethodPost, apiUrlPath+"/v1/certificates/:certid/orders", app.orders.NewOrder)
router.handleAPIRouteSecureDownload(http.MethodGet, apiUrlPath+"/v1/certificates/:certid/download", app.orders.DownloadCertNewestOrder)
router.handleAPIRouteSecureDownload(http.MethodGet, apiUrlPath+"/v1/certificates/:certid/orders/:orderid/download", app.orders.DownloadOneOrder)
router.handleAPIRouteSecure(http.MethodPost, apiUrlPath+"/v1/certificates/:certid/orders/:orderid", app.orders.FulfillExistingOrder)
router.handleAPIRouteSecure(http.MethodPost, apiUrlPath+"/v1/certificates/:certid/orders/:orderid/revoke", app.orders.RevokeOrder)
router.handleAPIRouteSecure(http.MethodPost, apiUrlPath+"/v1/certificates/:certid/orders/:orderid/postprocess", app.orders.PostProcessOrder)
// download keys and certs
router.handleAPIRouteDownloadWithAPIKey(http.MethodGet, apiKeyDownloadUrlPath+"/privatekeys/:name", app.download.DownloadKeyViaHeader)
router.handleAPIRouteDownloadWithAPIKey(http.MethodGet, apiKeyDownloadUrlPath+"/certificates/:name", app.download.DownloadCertViaHeader)
router.handleAPIRouteDownloadWithAPIKey(http.MethodGet, apiKeyDownloadUrlPath+"/privatecerts/:name", app.download.DownloadPrivateCertViaHeader)
router.handleAPIRouteDownloadWithAPIKey(http.MethodGet, apiKeyDownloadUrlPath+"/privatecertchains/:name", app.download.DownloadPrivateCertChainViaHeader)
router.handleAPIRouteDownloadWithAPIKey(http.MethodGet, apiKeyDownloadUrlPath+"/certrootchains/:name", app.download.DownloadCertRootChainViaHeader)
// download keys and certs - via URL routes
router.handleAPIRouteDownloadWithAPIKey(http.MethodGet, apiKeyDownloadUrlPath+"/privatekeys/:name/*apiKey", app.download.DownloadKeyViaUrl)
router.handleAPIRouteDownloadWithAPIKey(http.MethodGet, apiKeyDownloadUrlPath+"/certificates/:name/*apiKey", app.download.DownloadCertViaUrl)
router.handleAPIRouteDownloadWithAPIKey(http.MethodGet, apiKeyDownloadUrlPath+"/privatecerts/:name/*apiKey", app.download.DownloadPrivateCertViaUrl)
router.handleAPIRouteDownloadWithAPIKey(http.MethodGet, apiKeyDownloadUrlPath+"/privatecertchains/:name/*apiKey", app.download.DownloadPrivateCertChainViaUrl)
router.handleAPIRouteDownloadWithAPIKey(http.MethodGet, apiKeyDownloadUrlPath+"/certrootchains/:name/*apiKey", app.download.DownloadCertRootChainViaUrl)
// frontend (if enabled)
if *app.config.FrontendServe {
// log availability
app.logger.Infof("frontend hosting enabled and available at: %s", frontendUrlPath)
// configure environment file
setFrontendEnv(app.config.FrontendShowDebugInfo)
// redirect root to frontend app
router.handleFrontend(http.MethodGet, "/", redirectToFrontendHandler)
// redirect base path to frontend app
router.handleFrontend(http.MethodGet, baseUrlPath, redirectToFrontendHandler)
// add file server route for frontend
router.handleFrontend(http.MethodGet, frontendUrlPath+"/*anything(unused)", app.frontendFileHandler)
}
// redirect for old LeGo routes (only GET as only clients should be impacted and they only use GET)
// TODO: Remove eventually.
router.r.HandlerFunc(http.MethodGet, "/legocerthub/*restOfPath", app.redirectOldLeGoName)
// router.r.HandlerFunc(http.MethodPost, "/legocerthub/*restOfPath", app.redirectOldLeGoName)
// router.r.HandlerFunc(http.MethodPut, "/legocerthub/*restOfPath", app.redirectOldLeGoName)
// router.r.HandlerFunc(http.MethodDelete, "/legocerthub/*restOfPath", app.redirectOldLeGoName)
// invalid route
router.r.NotFound = app.handlerNotFound()
// options route
router.r.HandleOPTIONS = true
router.r.GlobalOPTIONS = app.handlerGlobalOptions()
// wrong method
router.r.HandleMethodNotAllowed = false
// convert to handler and apply common (universal) middlewares
appRouter := http.Handler(router)
// browser security headers (for all routes, not just frontend)
appRouter = middlewareApplyBrowserSecurityHeaders(appRouter)
// HSTS header (only is HTTPS and config option to disable isn't true)
if app.IsHttps() && (app.config.DisableHSTS != nil || !*app.config.DisableHSTS) {
appRouter = middlewareApplyHSTS(appRouter)
}
// set app's router
app.router = appRouter
}