@@ -20,6 +20,7 @@ import (
20
20
weakrand "math/rand"
21
21
"net"
22
22
"net/http"
23
+ "net/url"
23
24
"os"
24
25
"path/filepath"
25
26
"regexp"
@@ -52,6 +53,10 @@ type Handler struct {
52
53
// the default ID is "local".
53
54
CA string `json:"ca,omitempty"`
54
55
56
+ // The connection string of the database used for
57
+ // the account data of the ACME clients
58
+ Database string `json:"database,omitempty"`
59
+
55
60
// The lifetime for issued certificates
56
61
Lifetime caddy.Duration `json:"lifetime,omitempty"`
57
62
@@ -153,6 +158,12 @@ func (ash *Handler) Provision(ctx caddy.Context) error {
153
158
return fmt .Errorf ("certificate lifetime (%s) should be less than intermediate certificate lifetime (%s)" , time .Duration (ash .Lifetime ), time .Duration (ca .IntermediateLifetime ))
154
159
}
155
160
161
+ repl , ok := ctx .Context .Value (caddy .ReplacerCtxKey ).(* caddy.Replacer )
162
+ if ! ok {
163
+ repl = caddy .NewReplacer ()
164
+ ctx .Context = context .WithValue (ctx .Context , caddy .ReplacerCtxKey , repl )
165
+ }
166
+ ash .Database = repl .ReplaceKnown (ash .Database , "" )
156
167
database , err := ash .openDatabase ()
157
168
if err != nil {
158
169
return err
@@ -248,17 +259,38 @@ func (ash Handler) Cleanup() error {
248
259
func (ash Handler ) openDatabase () (* db.AuthDB , error ) {
249
260
key := ash .getDatabaseKey ()
250
261
database , loaded , err := databasePool .LoadOrNew (key , func () (caddy.Destructor , error ) {
251
- dbFolder := filepath .Join (caddy .AppDataDir (), "acme_server" , key )
252
- dbPath := filepath .Join (dbFolder , "db" )
253
-
254
- err := os .MkdirAll (dbFolder , 0o755 )
262
+ var dsn string
263
+ dburl , err := url .Parse (ash .Database )
255
264
if err != nil {
256
- return nil , fmt .Errorf ("making folder for CA database: %v" , err )
265
+ return nil , err
266
+ }
267
+ if dburl .Scheme == "" {
268
+ dburl .Scheme = "bbolt"
269
+ }
270
+ var dbtype string
271
+ switch dburl .Scheme {
272
+ case "postgresql" , "postgres" , "psql" :
273
+ dbtype = nosql .PostgreSQLDriver // normalize the postgres identifier
274
+ dsn = ash .Database
275
+ case "mysql" :
276
+ dbtype = nosql .MySQLDriver
277
+ dsn = ash .Database
278
+ case "bbolt" :
279
+ dbtype = nosql .BBoltDriver
280
+ dbFolder := filepath .Join (caddy .AppDataDir (), "acme_server" , key )
281
+ dsn = filepath .Join (dbFolder , "db" )
282
+ if err := os .MkdirAll (dbFolder , 0o755 ); err != nil {
283
+ return nil , fmt .Errorf ("making folder for CA database: %v" , err )
284
+ }
285
+ default :
286
+ // Although smallstep/nosql rejects unrecognized database, we
287
+ // reject them here to avoid surprises. We also reject 'badger'.
288
+ return nil , fmt .Errorf ("unsupported database type: %s" , dburl .Scheme )
257
289
}
258
290
259
291
dbConfig := & db.Config {
260
- Type : "bbolt" ,
261
- DataSource : dbPath ,
292
+ Type : dbtype ,
293
+ DataSource : dsn ,
262
294
}
263
295
database , err := db .New (dbConfig )
264
296
return databaseCloser {& database }, err
0 commit comments