mirror of
https://codeberg.org/Codeberg/pages-server.git
synced 2024-11-18 18:39:42 +00:00
03881382a4
This PR add the `$NO_DNS_01` option (disabled by default) that removes the DNS ACME provider, and replaces the wildcard certificate by individual certificates obtained using the TLS ACME provider. This option allows an instance to work without having to manage access tokens for the DNS provider. On the flip side, this means that a certificate can be requested for each subdomains. To limit the risk of DOS, the existence of the user/org corresponding to a subdomain is checked before requesting a cert, however, this limitation is not enough for an forge with a high number of users/orgs. Co-authored-by: 6543 <6543@obermui.de> Reviewed-on: https://codeberg.org/Codeberg/pages-server/pulls/290 Reviewed-by: Moritz Marquardt <momar@noreply.codeberg.org> Co-authored-by: Jean-Marie 'Histausse' Mineau <histausse@protonmail.com> Co-committed-by: Jean-Marie 'Histausse' Mineau <histausse@protonmail.com>
138 lines
2.7 KiB
Go
138 lines
2.7 KiB
Go
package database
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/rs/zerolog/log"
|
|
|
|
"github.com/go-acme/lego/v4/certificate"
|
|
"xorm.io/xorm"
|
|
|
|
// register sql driver
|
|
_ "github.com/go-sql-driver/mysql"
|
|
_ "github.com/lib/pq"
|
|
_ "github.com/mattn/go-sqlite3"
|
|
)
|
|
|
|
var _ CertDB = xDB{}
|
|
|
|
var ErrNotFound = errors.New("entry not found")
|
|
|
|
type xDB struct {
|
|
engine *xorm.Engine
|
|
}
|
|
|
|
func NewXormDB(dbType, dbConn string) (CertDB, error) {
|
|
if !supportedDriver(dbType) {
|
|
return nil, fmt.Errorf("not supported db type '%s'", dbType)
|
|
}
|
|
if dbConn == "" {
|
|
return nil, fmt.Errorf("no db connection provided")
|
|
}
|
|
|
|
e, err := xorm.NewEngine(dbType, dbConn)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := e.Sync2(new(Cert)); err != nil {
|
|
return nil, fmt.Errorf("could not sync db model :%w", err)
|
|
}
|
|
|
|
return &xDB{
|
|
engine: e,
|
|
}, nil
|
|
}
|
|
|
|
func (x xDB) Close() error {
|
|
return x.engine.Close()
|
|
}
|
|
|
|
func (x xDB) Put(domain string, cert *certificate.Resource) error {
|
|
log.Trace().Str("domain", cert.Domain).Msg("inserting cert to db")
|
|
|
|
c, err := toCert(domain, cert)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
sess := x.engine.NewSession()
|
|
if err := sess.Begin(); err != nil {
|
|
return err
|
|
}
|
|
defer sess.Close()
|
|
|
|
if exist, _ := sess.ID(c.Domain).Exist(new(Cert)); exist {
|
|
if _, err := sess.ID(c.Domain).Update(c); err != nil {
|
|
return err
|
|
}
|
|
} else {
|
|
if _, err = sess.Insert(c); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return sess.Commit()
|
|
}
|
|
|
|
func (x xDB) Get(domain string) (*certificate.Resource, error) {
|
|
// handle wildcard certs
|
|
if domain[:1] == "." {
|
|
domain = "*" + domain
|
|
}
|
|
|
|
cert := new(Cert)
|
|
log.Trace().Str("domain", domain).Msg("get cert from db")
|
|
if found, err := x.engine.ID(domain).Get(cert); err != nil {
|
|
return nil, err
|
|
} else if !found {
|
|
return nil, fmt.Errorf("%w: name='%s'", ErrNotFound, domain)
|
|
}
|
|
return cert.Raw(), nil
|
|
}
|
|
|
|
func (x xDB) Delete(domain string) error {
|
|
// handle wildcard certs
|
|
if domain[:1] == "." {
|
|
domain = "*" + domain
|
|
}
|
|
|
|
log.Trace().Str("domain", domain).Msg("delete cert from db")
|
|
_, err := x.engine.ID(domain).Delete(new(Cert))
|
|
return err
|
|
}
|
|
|
|
// Items return al certs from db, if pageSize is 0 it does not use limit
|
|
func (x xDB) Items(page, pageSize int) ([]*Cert, error) {
|
|
// paginated return
|
|
if pageSize > 0 {
|
|
certs := make([]*Cert, 0, pageSize)
|
|
if page >= 0 {
|
|
page = 1
|
|
}
|
|
err := x.engine.Limit(pageSize, (page-1)*pageSize).Find(&certs)
|
|
return certs, err
|
|
}
|
|
|
|
// return all
|
|
certs := make([]*Cert, 0, 64)
|
|
err := x.engine.Find(&certs)
|
|
return certs, err
|
|
}
|
|
|
|
// Supported database drivers
|
|
const (
|
|
DriverSqlite = "sqlite3"
|
|
DriverMysql = "mysql"
|
|
DriverPostgres = "postgres"
|
|
)
|
|
|
|
func supportedDriver(driver string) bool {
|
|
switch driver {
|
|
case DriverMysql, DriverPostgres, DriverSqlite:
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|