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