Compare commits

..

No commits in common. "b2761a3a894f02a8fa5bcdd7dd151c1ad3c84b58" and "5181aed0b8947b003026cd17803c10e547594869" have entirely different histories.

5 changed files with 10 additions and 105 deletions

View File

@ -1,7 +0,0 @@
steps:
build: golang/1.21.5-alpine
commands:
- go get
- go build ./cmd/rio
- go fmt $(go list ./... | grep -v /vendor/)
- go vet $(go list ./... | grep -v /vendor/)

View File

@ -97,7 +97,7 @@ func runServer(ctx *cli.Context) error {
// Setup the Gitea stuff // Setup the Gitea stuff
httpClient := http.Client{Timeout: 10 * time.Second} httpClient := http.Client{Timeout: 10 * time.Second}
giteaClient, err := gitea.NewClient( client, err := gitea.NewClient(
giteaUrl, giteaUrl,
gitea.SetHTTPClient(&httpClient), gitea.SetHTTPClient(&httpClient),
gitea.SetToken(""), gitea.SetToken(""),
@ -108,8 +108,7 @@ func runServer(ctx *cli.Context) error {
addr := ctx.String("listen-host") + ":" + ctx.String("listen-port") addr := ctx.String("listen-host") + ":" + ctx.String("listen-port")
listener, err := net.Listen("tcp", addr) listener, err := net.Listen("tcp", addr)
if err != nil { if err != nil {
errMsg := fmt.Errorf("Failed to create listener: %v", err) fmt.Errorf("Failed to create listener: %v", err)
fmt.Println(errMsg.Error())
return err return err
} }
@ -163,12 +162,11 @@ func runServer(ctx *cli.Context) error {
certsFile, certsFile,
&cache, &cache,
acmeClient, acmeClient,
giteaClient,
) )
listener = tls.NewListener(listener, tlsConfig) listener = tls.NewListener(listener, tlsConfig)
} }
if err := http.Serve(listener, Handler(domain, giteaUrl, giteaClient)); err != nil { if err := http.Serve(listener, Handler(domain, giteaUrl, client)); err != nil {
fmt.Printf("Listening failed") fmt.Printf("Listening failed")
return err return err
} }

View File

@ -15,9 +15,6 @@ import (
var ( var (
pathCache = cache.New(1*time.Hour, 1*time.Hour) pathCache = cache.New(1*time.Hour, 1*time.Hour)
// Caching the existence of an user
userCache = cache.New(24*time.Hour, 12*time.Hour)
) )
type PageCacheEntry struct { type PageCacheEntry struct {
@ -135,19 +132,3 @@ func RepoFromPath(username, host, cname, path string, giteaClient *gitea.Client)
) )
return repo, path, err return repo, path, err
} }
// Checks if the username exists as an organisation or an user on the Gitea
// instance, so that an attacker can't just request certificates for random
// usernames.
func CanRequestCertificate(username string, giteaClient *gitea.Client) bool {
if _, found := userCache.Get(username); found {
return true
}
user, _, err := giteaClient.GetUserInfo(username)
if user != nil && err == nil {
userCache.Set(username, true, cache.DefaultExpiration)
return true
}
return false
}

View File

@ -1,39 +0,0 @@
package repo
import (
"net/http"
"testing"
"time"
"code.gitea.io/sdk/gitea"
)
var (
giteaClient, _ = gitea.NewClient(
"https://git.polynom.me",
gitea.SetHTTPClient(&http.Client{Timeout: 10 * time.Second}),
gitea.SetToken(""),
gitea.SetUserAgent("rio/testing"),
)
)
func TestCanRequestCertificatePositiveUser(t *testing.T) {
res := CanRequestCertificate("papatutuwawa", giteaClient)
if !res {
t.Fatalf("User papatutuwawa should be servable")
}
}
func TestCanRequestCertificatePositiveOrganisation(t *testing.T) {
res := CanRequestCertificate("moxxy", giteaClient)
if !res {
t.Fatalf("Organisation moxxy should be servable")
}
}
func TestCanRequestCertificateNegative(t *testing.T) {
res := CanRequestCertificate("user-who-does-not-exist", giteaClient)
if res {
t.Fatalf("User user-who-does-not-exist should not be servable")
}
}

View File

@ -7,9 +7,7 @@ import (
"git.polynom.me/rio/internal/certificates" "git.polynom.me/rio/internal/certificates"
"git.polynom.me/rio/internal/dns" "git.polynom.me/rio/internal/dns"
"git.polynom.me/rio/internal/repo"
"code.gitea.io/sdk/gitea"
"github.com/go-acme/lego/v4/lego" "github.com/go-acme/lego/v4/lego"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
@ -43,16 +41,16 @@ func unlockDomain(domain string) {
delete(workingDomains, domain) delete(workingDomains, domain)
} }
func MakeTlsConfig(pagesDomain, cachePath string, cache *certificates.CertificatesCache, acmeClient *lego.Client, giteaClient *gitea.Client) *tls.Config { func MakeTlsConfig(pagesDomain, cachePath string, cache *certificates.CertificatesCache, acmeClient *lego.Client) *tls.Config {
return &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 // Validate that we should even care about this domain
cname := ""
if !strings.HasSuffix(info.ServerName, pagesDomain) { if !strings.HasSuffix(info.ServerName, pagesDomain) {
// Note: We do not check err here because err != nil // Note: We do not check err here because err != nil
// always implies that cname == "", which does not have // always implies that cname == "", which does not have
// pagesDomain as a suffix. // pagesDomain as a suffix.
cname, _ = dns.LookupCNAME(info.ServerName) cname, _ := dns.LookupCNAME(info.ServerName)
if !strings.HasSuffix(cname, pagesDomain) { if !strings.HasSuffix(cname, pagesDomain) {
log.Warnf("Got ServerName for Domain %s that we're not responsible for", info.ServerName) log.Warnf("Got ServerName for Domain %s that we're not responsible for", info.ServerName)
return cache.FallbackCertificate.TlsCertificate, nil return cache.FallbackCertificate.TlsCertificate, nil
@ -66,31 +64,11 @@ func MakeTlsConfig(pagesDomain, cachePath string, cache *certificates.Certificat
domain = "*." + pagesDomain domain = "*." + pagesDomain
}*/ }*/
// Figure out a username for later username checks
username := ""
if cname == "" {
// domain ends on pagesDomain
username = strings.Split(domain, ".")[0]
} else {
// cname ends on pagesDomain
username = strings.Split(cname, ".")[0]
}
// Find the correct certificate
cert, found := cache.Certificates[info.ServerName] cert, found := cache.Certificates[info.ServerName]
if found { if found {
if cert.IsValid() { if cert.IsValid() {
return cert.TlsCertificate, nil return cert.TlsCertificate, nil
} else { } else {
if !repo.CanRequestCertificate(username, giteaClient) {
log.Warnf(
"Cannot renew certificate for %s because CanRequestCertificate(%s) returned false",
domain,
username,
)
return cert.TlsCertificate, nil
}
// If we're already working on the domain, // If we're already working on the domain,
// return the old certificate // return the old certificate
if lockIfUnlockedDomain(domain) { if lockIfUnlockedDomain(domain) {
@ -98,7 +76,7 @@ func MakeTlsConfig(pagesDomain, cachePath string, cache *certificates.Certificat
} }
defer unlockDomain(domain) defer unlockDomain(domain)
// Renew the certificate // Renew
log.Infof("Certificate for %s expired, renewing", domain) log.Infof("Certificate for %s expired, renewing", domain)
newCert, err := certificates.RenewCertificate(&cert, acmeClient) newCert, err := certificates.RenewCertificate(&cert, acmeClient)
if err != nil { if err != nil {
@ -111,15 +89,6 @@ func MakeTlsConfig(pagesDomain, cachePath string, cache *certificates.Certificat
return newCert.TlsCertificate, nil return newCert.TlsCertificate, nil
} }
} else { } else {
if !repo.CanRequestCertificate(username, giteaClient) {
log.Warnf(
"Cannot request certificate for %s because CanRequestCertificate(%s) returned false",
domain,
username,
)
return cache.FallbackCertificate.TlsCertificate, nil
}
// Don't request if we're already requesting. // Don't request if we're already requesting.
if lockIfUnlockedDomain(domain) { if lockIfUnlockedDomain(domain) {
return cache.FallbackCertificate.TlsCertificate, nil return cache.FallbackCertificate.TlsCertificate, nil
@ -146,6 +115,9 @@ func MakeTlsConfig(pagesDomain, cachePath string, cache *certificates.Certificat
cache.AddCert(cert, cachePath) cache.AddCert(cert, cachePath)
return cert.TlsCertificate, nil return cert.TlsCertificate, nil
} }
log.Debugf("TLS ServerName: %s", info.ServerName)
return cache.FallbackCertificate.TlsCertificate, nil
}, },
NextProtos: []string{ NextProtos: []string{
"http/0.9", "http/0.9",