diff --git a/account.go b/account.go index f5f6241..3eac8d3 100644 --- a/account.go +++ b/account.go @@ -5,8 +5,8 @@ import ( "crypto/ecdsa" "crypto/elliptic" "crypto/rand" - "encoding/json" "encoding/base64" + "encoding/json" "io/ioutil" "github.com/go-acme/lego/v4/acme" @@ -16,9 +16,9 @@ import ( ) type AcmeAccount struct { - Email string + Email string Registration *registration.Resource - Key crypto.PrivateKey + Key crypto.PrivateKey } func (a *AcmeAccount) GetEmail() string { @@ -36,7 +36,7 @@ func (a *AcmeAccount) GetRegistration() *registration.Resource { func (a *AcmeAccount) FlushToDisk(storage string) { data := map[string]interface{}{ "email": a.Email, - "reg": a.Registration, + "reg": a.Registration, "private_key_encoded": base64.StdEncoding.EncodeToString( certcrypto.PEMEncode(a.Key), ), @@ -61,22 +61,21 @@ func ClientFromFile(storage, acmeServer string) (*lego.Client, error) { contacts = append(contacts, v.(string)) } - registration := registration.Resource{ URI: reg["uri"].(string), Body: acme.Account{ - Status: accountRaw["status"].(string), - Contact: contacts, + Status: accountRaw["status"].(string), + Contact: contacts, TermsOfServiceAgreed: true, //Orders: accountRaw["orders"].(string), }, } - + pkEncoded, err := base64.StdEncoding.DecodeString(data["private_key_encoded"].(string)) pk, err := certcrypto.ParsePEMPrivateKey(pkEncoded) account := AcmeAccount{ - Email: data["email"].(string), - Key: pk.(*ecdsa.PrivateKey), + Email: data["email"].(string), + Key: pk.(*ecdsa.PrivateKey), Registration: ®istration, } config := lego.NewConfig(&account) @@ -99,7 +98,7 @@ func GenerateNewAccount(email, storage, acmeServer string) (*lego.Client, error) account := AcmeAccount{ Email: email, - Key: privateKey, + Key: privateKey, } config := lego.NewConfig(&account) config.CADirURL = acmeServer @@ -109,7 +108,7 @@ func GenerateNewAccount(email, storage, acmeServer string) (*lego.Client, error) if err != nil { return nil, err } - + // Register it req, err := client.Registration.Register( registration.RegisterOptions{ @@ -121,6 +120,6 @@ func GenerateNewAccount(email, storage, acmeServer string) (*lego.Client, error) } account.Registration = req account.FlushToDisk(storage) - + return client, nil } diff --git a/acme.go b/acme.go index 1e53e3e..70d309a 100644 --- a/acme.go +++ b/acme.go @@ -31,7 +31,7 @@ const ( var ( // Well-known -> Challenge solution runningChallenges = make(map[string]string) - Certificates = CertificatesCache{ + Certificates = CertificatesCache{ Certificates: make(map[string]CertificateWrapper), } @@ -63,30 +63,30 @@ func unlockDomain(domain string) { } type CertificateWrapper struct { - TlsCertificate *tls.Certificate `json:"-"` - Domain string `json:"domain"` - NotAfter time.Time `json:"not_after"` - PrivateKeyEncoded string `json:"private_key"` - Certificate []byte `json:"certificate"` - IssuerCertificate []byte `json:"issuer_certificate"` - CertificateUrl string `json:"certificate_url"` + TlsCertificate *tls.Certificate `json:"-"` + Domain string `json:"domain"` + NotAfter time.Time `json:"not_after"` + PrivateKeyEncoded string `json:"private_key"` + Certificate []byte `json:"certificate"` + IssuerCertificate []byte `json:"issuer_certificate"` + CertificateUrl string `json:"certificate_url"` } func (c *CertificateWrapper) GetPrivateKey() *rsa.PrivateKey { data, _ := base64.StdEncoding.DecodeString(c.PrivateKeyEncoded) - pk, _ := certcrypto.ParsePEMPrivateKey(data); + pk, _ := certcrypto.ParsePEMPrivateKey(data) return pk.(*rsa.PrivateKey) } type CertificatesCache struct { FallbackCertificate *CertificateWrapper - Certificates map[string]CertificateWrapper + Certificates map[string]CertificateWrapper } type CertificatesStore struct { - FallbackCertificate CertificateWrapper `json:"fallback"` - Certificates []CertificateWrapper `json:"certificates"` + FallbackCertificate CertificateWrapper `json:"fallback"` + Certificates []CertificateWrapper `json:"certificates"` } func (c *CertificatesCache) toStoreData() string { @@ -97,7 +97,7 @@ func (c *CertificatesCache) toStoreData() string { result, err := json.Marshal(CertificatesStore{ FallbackCertificate: *c.FallbackCertificate, - Certificates: certs, + Certificates: certs, }) if err != nil { log.Errorf("Failed to Marshal cache: %v", err) @@ -129,7 +129,7 @@ func CertificateFromStoreData(rawJson string) CertificatesCache { certs[cert.Domain] = cert } cache.Certificates = certs - + return cache } @@ -160,17 +160,17 @@ func fallbackCert(pagesDomain string) (*CertificateWrapper, error) { return nil, err } - notAfter := time.Now().Add(time.Hour*24*7); + notAfter := time.Now().Add(time.Hour * 24 * 7) cert := x509.Certificate{ SerialNumber: big.NewInt(1), Subject: pkix.Name{ - CommonName: pagesDomain, + CommonName: pagesDomain, Organization: []string{"Pages Server"}, }, - NotAfter: notAfter, - NotBefore: time.Now(), - KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + NotAfter: notAfter, + NotBefore: time.Now(), + KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, BasicConstraintsValid: true, } certBytes, err := x509.CreateCertificate( @@ -187,7 +187,7 @@ func fallbackCert(pagesDomain string) (*CertificateWrapper, error) { out := &bytes.Buffer{} err = pem.Encode(out, &pem.Block{ Bytes: certBytes, - Type: "CERTIFICATE", + Type: "CERTIFICATE", }) if err != nil { return nil, err @@ -195,23 +195,23 @@ func fallbackCert(pagesDomain string) (*CertificateWrapper, error) { outBytes := out.Bytes() res := &certificate.Resource{ - PrivateKey: certcrypto.PEMEncode(key), - Certificate: outBytes, + PrivateKey: certcrypto.PEMEncode(key), + Certificate: outBytes, IssuerCertificate: outBytes, - Domain: pagesDomain, + Domain: pagesDomain, } tlsCertificate, err := tls.X509KeyPair(res.Certificate, res.PrivateKey) if err != nil { return nil, err } return &CertificateWrapper{ - TlsCertificate: &tlsCertificate, - Domain: pagesDomain, - NotAfter: notAfter, + TlsCertificate: &tlsCertificate, + Domain: pagesDomain, + NotAfter: notAfter, PrivateKeyEncoded: base64.StdEncoding.EncodeToString(certcrypto.PEMEncode(key)), - Certificate: outBytes, + Certificate: outBytes, IssuerCertificate: outBytes, - CertificateUrl: "localhost", + CertificateUrl: "localhost", }, nil } @@ -222,7 +222,7 @@ func isCertStillValid(cert CertificateWrapper) bool { func makeTlsConfig(pagesDomain, path string, acmeClient *lego.Client) *tls.Config { return &tls.Config{ InsecureSkipVerify: true, - GetCertificate: func (info *tls.ClientHelloInfo) (*tls.Certificate, error) { + GetCertificate: func(info *tls.ClientHelloInfo) (*tls.Certificate, error) { // Validate that we should even care about this domain if !strings.HasSuffix(info.ServerName, pagesDomain) { // Note: We do not check err here because err != nil diff --git a/certificate.go b/certificate.go index 8b8bf33..d80cb99 100644 --- a/certificate.go +++ b/certificate.go @@ -13,7 +13,7 @@ import ( func ObtainNewCertificate(domains []string, path string, acmeClient *lego.Client) error { req := certificate.ObtainRequest{ Domains: domains, - Bundle: true, + Bundle: true, } cert, err := acmeClient.Certificate.Obtain(req) if err != nil { @@ -27,13 +27,13 @@ func ObtainNewCertificate(domains []string, path string, acmeClient *lego.Client wrapper := CertificateWrapper{ TlsCertificate: &tlsCert, - Domain: cert.Domain, + Domain: cert.Domain, //NotAfter: tlsCert.Leaf.NotAfter, - NotAfter: time.Now().Add(time.Hour * 24 * 60), + NotAfter: time.Now().Add(time.Hour * 24 * 60), PrivateKeyEncoded: base64.StdEncoding.EncodeToString(cert.PrivateKey), - Certificate: cert.Certificate, + Certificate: cert.Certificate, IssuerCertificate: cert.IssuerCertificate, - CertificateUrl: cert.CertURL, + CertificateUrl: cert.CertURL, } Certificates.Certificates[cert.Domain] = wrapper FlushCertificateStoreToFile(path) diff --git a/dns.go b/dns.go index 6c4b42f..ec1059e 100644 --- a/dns.go +++ b/dns.go @@ -14,8 +14,8 @@ const ( ) var ( - cnameCache = cache.New(1 * time.Hour, 1 * time.Hour) - txtRepoCache = cache.New(1 * time.Hour, 1 * time.Hour) + cnameCache = cache.New(1*time.Hour, 1*time.Hour) + txtRepoCache = cache.New(1*time.Hour, 1*time.Hour) ) func lookupRepoTXT(domain string) (string, error) { diff --git a/main.go b/main.go index 6a75cef..f326025 100644 --- a/main.go +++ b/main.go @@ -2,18 +2,18 @@ package main import ( "crypto/tls" - "os" "errors" "fmt" "net" "net/http" + "os" "strings" "time" "code.gitea.io/sdk/gitea" - "github.com/urfave/cli/v2" "github.com/go-acme/lego/v4/challenge/http01" log "github.com/sirupsen/logrus" + "github.com/urfave/cli/v2" ) const ( @@ -35,7 +35,6 @@ func handleSubdomain(domain string, cname string, path, giteaUrl string, giteaCl cname, path, giteaClient, - ) if err != nil { log.Errorf("Failed to get repo: %s", err) @@ -50,7 +49,7 @@ func Handler(pagesDomain, giteaUrl string, giteaClient *gitea.Client) http.Handl return func(w http.ResponseWriter, req *http.Request) { w.Header().Set("Server", "rio") - if strings.HasSuffix(req.Host, pagesDomain){ + if strings.HasSuffix(req.Host, pagesDomain) { if handleLetsEncryptChallenge(w, req) { return } @@ -59,7 +58,7 @@ func Handler(pagesDomain, giteaUrl string, giteaClient *gitea.Client) http.Handl handleSubdomain(req.Host, "", req.URL.Path, giteaUrl, giteaClient, w) return } - + cname, err := lookupCNAME(req.Host) if err != nil { log.Warningf("CNAME request failed, we don't handle %s", req.Host) @@ -177,68 +176,68 @@ func main() { Action: runServer, Flags: []cli.Flag{ &cli.StringFlag{ - Name: "gitea-url", - Usage: "The (HTTPS) URL to the serving Gitea instance", - EnvVars: []string{"GITEA_URL"}, + Name: "gitea-url", + Usage: "The (HTTPS) URL to the serving Gitea instance", + EnvVars: []string{"GITEA_URL"}, Required: true, }, &cli.StringFlag{ - Name: "listen-host", - Usage: "The host to listen on", + Name: "listen-host", + Usage: "The host to listen on", EnvVars: []string{"HOST"}, - Value: "127.0.0.1", + Value: "127.0.0.1", }, &cli.StringFlag{ - Name: "listen-port", - Usage: "The port to listen on", + Name: "listen-port", + Usage: "The port to listen on", EnvVars: []string{"PORT"}, - Value: "8888", + Value: "8888", }, &cli.StringFlag{ - Name: "acme-host", - Usage: "The host to bind to for ACME challenges", + Name: "acme-host", + Usage: "The host to bind to for ACME challenges", EnvVars: []string{"ACME_HOST"}, - Value: "", + Value: "", }, &cli.StringFlag{ - Name: "acme-port", - Usage: "The port to listen on for ACME challenges", + Name: "acme-port", + Usage: "The port to listen on for ACME challenges", EnvVars: []string{"ACME_PORT"}, - Value: "8889", + Value: "8889", }, &cli.StringFlag{ - Name: "pages-domain", - Usage: "The domain on which the server is reachable", - EnvVars: []string{"PAGES_DOMAIN"}, + Name: "pages-domain", + Usage: "The domain on which the server is reachable", + EnvVars: []string{"PAGES_DOMAIN"}, Required: true, }, &cli.StringFlag{ - Name: "certs-file", - Usage: "File to store certificates in", + Name: "certs-file", + Usage: "File to store certificates in", EnvVars: []string{"CERTS_FILE"}, - Value: "", + Value: "", }, &cli.StringFlag{ - Name: "acme-file", - Usage: "File to store ACME configuration in", + Name: "acme-file", + Usage: "File to store ACME configuration in", EnvVars: []string{"ACME_FILE"}, - Value: "", + Value: "", }, &cli.StringFlag{ - Name: "acme-email", - Usage: "Email to use for an ACME account", + Name: "acme-email", + Usage: "Email to use for an ACME account", EnvVars: []string{"ACME_EMAIL"}, - Value: "", + Value: "", }, &cli.StringFlag{ - Name: "acme-server", - Usage: "CA Directory to use", + Name: "acme-server", + Usage: "CA Directory to use", EnvVars: []string{"ACME_SERVER"}, - Value: "https://acme-staging-v02.api.letsencrypt.org/directory", + Value: "https://acme-staging-v02.api.letsencrypt.org/directory", }, &cli.BoolFlag{ - Name: "acme-disable", - Usage: "Whether to disable automatic ACME certificates", + Name: "acme-disable", + Usage: "Whether to disable automatic ACME certificates", EnvVars: []string{"ACME_DISABLE"}, }, }, diff --git a/pages.go b/pages.go index 326a099..443fb51 100644 --- a/pages.go +++ b/pages.go @@ -13,12 +13,12 @@ import ( ) var ( - pageCache = cache.New(6 * time.Hour, 1 * time.Hour) + pageCache = cache.New(6*time.Hour, 1*time.Hour) ) type PageContentCache struct { - Content []byte - mimeType string + Content []byte + mimeType string RequestedAt time.Time } @@ -98,7 +98,7 @@ func serveFile(username, reponame, path, giteaUrl string, w http.ResponseWriter) } pathParts := strings.Split(path, ".") - ext := pathParts[len(pathParts) - 1] + ext := pathParts[len(pathParts)-1] mimeType = mime.TypeByExtension("." + ext) now := time.Now() diff --git a/repo.go b/repo.go index 05b5e32..1207417 100644 --- a/repo.go +++ b/repo.go @@ -11,23 +11,22 @@ import ( ) var ( - pathCache = cache.New(1 * time.Hour, 1 * time.Hour) + pathCache = cache.New(1*time.Hour, 1*time.Hour) ) - type PageCacheEntry struct { Repository *gitea.Repository - Path string + Path string } func makePageCacheKey(domain, path string) string { return domain + "/" + path } -/// Try to find the repository with name @reponame of the user @username. If @cname -/// is not "", then it also verifies that the repository contains a "CNAME" with -/// the value of @cname as its content. @host, @domain, and @path are passed for -/// caching on success. +// / Try to find the repository with name @reponame of the user @username. If @cname +// / is not "", then it also verifies that the repository contains a "CNAME" with +// / the value of @cname as its content. @host, @domain, and @path are passed for +// / caching on success. func lookupRepositoryAndCache(username, reponame, host, domain, path, cname string, giteaClient *gitea.Client) (*gitea.Repository, error) { log.Debugf("Looking up repository %s/%s", username, reponame) repo, _, err := giteaClient.GetRepo(username, reponame) @@ -113,9 +112,9 @@ func RepoFromPath(username, host, cname, path string, giteaClient *gitea.Client) repoLookup, ) reponame = repoLookup - } else if (cname != "") { + } else if cname != "" { // Allow naming the repository "example.org" (But give the TXT record preference) - reponame = cname; + reponame = cname } log.Debugf("Trying repository %s/%s", username, reponame)