handle multidomains, modified schema structure
This commit is contained in:
parent
90650aacfa
commit
7c7a6a2e35
@ -5,7 +5,7 @@ import "time"
|
||||
// Entry is the main struct for stored certificates
|
||||
type Entry struct {
|
||||
ID int `xorm:"pk autoincr"`
|
||||
Domain string `xorm:"notnull"`
|
||||
Domains string `xorm:"notnull"`
|
||||
Certificate string `xorm:"text notnull"`
|
||||
PrivateKey string `xorm:"text notnull"`
|
||||
AuthURL string
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.paulbsd.com/paulbsd/pki/src/cert"
|
||||
@ -29,14 +30,15 @@ func (u *User) Init(cfg *config.Config) (err error) {
|
||||
}
|
||||
|
||||
// GetEntry returns requested acme ressource in database relative to domain
|
||||
func (u *User) GetEntry(cfg *config.Config, domain string) (Entry cert.Entry, err error) {
|
||||
todaydate := time.Now().Format("2006-01-02")
|
||||
func (u *User) GetEntry(cfg *config.Config, domains []string) (Entry cert.Entry, err error) {
|
||||
requireddate := time.Now().AddDate(0, 0, -cfg.ACME.MaxDaysBefore).Format("2006-01-02")
|
||||
|
||||
has, err := cfg.Db.Where("domain = ?", domain).Where(
|
||||
"validity_begin < ?::date", todaydate).Where(
|
||||
"validity_end > ?::date", requireddate).Where(
|
||||
"auth_url = ?", cfg.ACME.AuthURL).Get(&Entry)
|
||||
has, err := cfg.Db.Where("domains = ?", strings.Join(domains, ",")).Where(
|
||||
"validity_begin <= now()").Where(
|
||||
"validity_end >= ?::timestamp", requireddate).Where(
|
||||
"auth_url = ?", cfg.ACME.AuthURL).Desc(
|
||||
"id").Get(&Entry)
|
||||
|
||||
if !has {
|
||||
err = fmt.Errorf("Entry doesn't exists")
|
||||
}
|
||||
@ -67,7 +69,7 @@ func (u *User) HandleRegistration(cfg *config.Config, client *lego.Client) (err
|
||||
}
|
||||
|
||||
// RequestNewCert returns a newly requested certificate to letsencrypt
|
||||
func (u *User) RequestNewCert(cfg *config.Config, domain string) (certificates *certificate.Resource, err error) {
|
||||
func (u *User) RequestNewCert(cfg *config.Config, domains []string) (certificates *certificate.Resource, err error) {
|
||||
legoconfig := lego.NewConfig(u)
|
||||
legoconfig.CADirURL = cfg.ACME.AuthURL
|
||||
legoconfig.Certificate.KeyType = certcrypto.RSA2048
|
||||
@ -93,7 +95,7 @@ func (u *User) RequestNewCert(cfg *config.Config, domain string) (certificates *
|
||||
}
|
||||
|
||||
request := certificate.ObtainRequest{
|
||||
Domains: []string{domain},
|
||||
Domains: domains,
|
||||
Bundle: true,
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"git.paulbsd.com/paulbsd/pki/src/config"
|
||||
"git.paulbsd.com/paulbsd/pki/src/pki"
|
||||
@ -27,18 +28,25 @@ func RunServer(cfg *config.Config) (err error) {
|
||||
e.HideBanner = cfg.Options.HideBanner
|
||||
|
||||
e.GET("/", func(c echo.Context) error {
|
||||
return c.String(http.StatusOK, "Welcome to PKI software")
|
||||
return c.String(http.StatusOK, "Welcome to PKI software (https://git.paulbsd.com/paulbsd/pki)")
|
||||
})
|
||||
e.GET("/domain/:domain", func(c echo.Context) (err error) {
|
||||
e.GET("/domain/:domains", func(c echo.Context) (err error) {
|
||||
var result EntryResponse
|
||||
log.Println(fmt.Sprintf("Providing %s to user %s at %s", c.Param("domain"), c.Get("username"), c.RealIP()))
|
||||
result, err = GetCertificate(cfg, c.Get("user").(*pki.User), c.Param("domain"))
|
||||
var domains = strings.Split(c.Param("domains"), ",")
|
||||
|
||||
log.Println(fmt.Sprintf("Providing %s to user %s at %s", domains, c.Get("username"), c.RealIP()))
|
||||
|
||||
result, err = GetCertificate(cfg, c.Get("user").(*pki.User), domains)
|
||||
if err != nil {
|
||||
return c.String(http.StatusInternalServerError, fmt.Sprintf("%s %s", result, err))
|
||||
return c.String(http.StatusInternalServerError, fmt.Sprintf("%s", err))
|
||||
}
|
||||
return c.JSON(http.StatusOK, result)
|
||||
})
|
||||
|
||||
e.Logger.Fatal(e.Start(fmt.Sprintf(":%d", cfg.Switchs.Port)))
|
||||
e.Logger.Fatal(
|
||||
e.Start(
|
||||
fmt.Sprintf(":%d",
|
||||
cfg.Switchs.Port)))
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.paulbsd.com/paulbsd/pki/src/cert"
|
||||
@ -14,15 +15,15 @@ import (
|
||||
)
|
||||
|
||||
// GetCertificate get certificate from database if exists, of request it from ACME
|
||||
func GetCertificate(cfg *config.Config, user *pki.User, domain string) (result EntryResponse, err error) {
|
||||
err = CheckDomain(domain)
|
||||
func GetCertificate(cfg *config.Config, user *pki.User, domains []string) (result EntryResponse, err error) {
|
||||
err = CheckDomains(domains)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
entry, err := user.GetEntry(cfg, domain)
|
||||
entry, err := user.GetEntry(cfg, domains)
|
||||
if err != nil {
|
||||
certs, err := user.RequestNewCert(cfg, domain)
|
||||
certs, err := user.RequestNewCert(cfg, domains)
|
||||
if err != nil {
|
||||
log.Println(fmt.Sprintf("Error fetching new certificate %s", err))
|
||||
return result, err
|
||||
@ -32,7 +33,7 @@ func GetCertificate(cfg *config.Config, user *pki.User, domain string) (result E
|
||||
log.Println("Error where parsing dates")
|
||||
return result, err
|
||||
}
|
||||
entry := cert.Entry{Domain: domain,
|
||||
entry := cert.Entry{Domains: strings.Join(domains, ","),
|
||||
Certificate: string(certs.Certificate),
|
||||
PrivateKey: string(certs.PrivateKey),
|
||||
ValidityBegin: NotBefore,
|
||||
@ -46,11 +47,14 @@ func GetCertificate(cfg *config.Config, user *pki.User, domain string) (result E
|
||||
return
|
||||
}
|
||||
|
||||
// CheckDomain check if requested domain is valid
|
||||
func CheckDomain(domain string) (err error) {
|
||||
res, err := regexp.Match(`^[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,6}$`, []byte(domain))
|
||||
// CheckDomains check if requested domains are valid
|
||||
func CheckDomains(domains []string) (err error) {
|
||||
for _, d := range domains {
|
||||
res, err := regexp.Match(`^[a-z0-9\*]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,6}$`, []byte(d))
|
||||
if !res {
|
||||
return fmt.Errorf("Domain has not a valid syntax")
|
||||
fmt.Println(res, err)
|
||||
return fmt.Errorf(fmt.Sprintf("Domain has not a valid syntax %s, please verify", err))
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -71,20 +75,22 @@ func GetDates(cert []byte) (NotBefore time.Time, NotAfter time.Time, err error)
|
||||
|
||||
// convertEntryToResponse converts database ACME entry to JSON ACME entry
|
||||
func convertEntryToResponse(in cert.Entry) (out EntryResponse) {
|
||||
out.Domain = in.Domain
|
||||
timeformatstring := "2006-01-02 15:04:05"
|
||||
|
||||
out.Domains = in.Domains
|
||||
out.Certificate = in.Certificate
|
||||
out.PrivateKey = in.PrivateKey
|
||||
out.ValidityBegin = in.ValidityBegin
|
||||
out.ValidityEnd = in.ValidityEnd
|
||||
out.ValidityBegin = in.ValidityBegin.Format(timeformatstring)
|
||||
out.ValidityEnd = in.ValidityEnd.Format(timeformatstring)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// EntryResponse is the struct defining JSON response from webservice
|
||||
type EntryResponse struct {
|
||||
Domain string `json:"domain"`
|
||||
Domains string `json:"domains"`
|
||||
Certificate string `json:"certificate"`
|
||||
PrivateKey string `json:"privatekey"`
|
||||
ValidityBegin time.Time `json:"validitybegin"`
|
||||
ValidityEnd time.Time `json:"validityend"`
|
||||
ValidityBegin string `json:"validitybegin"`
|
||||
ValidityEnd string `json:"validityend"`
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
// Auth make authentication to webservice
|
||||
func Auth(cfg *config.Config, username string, password string, c echo.Context) (res bool, user *pki.User, err error) {
|
||||
user = &pki.User{Username: username}
|
||||
|
||||
_, err = cfg.Db.Get(user)
|
||||
if err != nil {
|
||||
res = false
|
||||
|
Loading…
Reference in New Issue
Block a user