-
Notifications
You must be signed in to change notification settings - Fork 119
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update TLS certificates, generate certificate if not found.
We now notice that a TLS certificate on disk has changed, and we generate a self-signed certificate if none is found.
- Loading branch information
Showing
3 changed files
with
121 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
package webserver | ||
|
||
import ( | ||
"crypto/rand" | ||
"crypto/rsa" | ||
"crypto/tls" | ||
"crypto/x509" | ||
"log" | ||
"math/big" | ||
"os" | ||
"path/filepath" | ||
"sync/atomic" | ||
"time" | ||
) | ||
|
||
type certInfo struct { | ||
certificate *tls.Certificate | ||
keyTime time.Time | ||
certTime time.Time | ||
} | ||
|
||
var certificate atomic.Value | ||
|
||
func generateCertificate(dataDir string) (tls.Certificate, error) { | ||
priv, err := rsa.GenerateKey(rand.Reader, 2048) | ||
if err != nil { | ||
return tls.Certificate{}, err | ||
} | ||
|
||
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) | ||
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) | ||
now := time.Now() | ||
|
||
template := x509.Certificate{ | ||
SerialNumber: serialNumber, | ||
NotBefore: now, | ||
NotAfter: now.Add(365 * 24 * time.Hour), | ||
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, | ||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, | ||
BasicConstraintsValid: true, | ||
} | ||
bytes, err := x509.CreateCertificate( | ||
rand.Reader, &template, &template, &priv.PublicKey, priv, | ||
) | ||
if err != nil { | ||
return tls.Certificate{}, err | ||
} | ||
|
||
return tls.Certificate{ | ||
Certificate: [][]byte{bytes}, | ||
PrivateKey: priv, | ||
}, nil | ||
} | ||
|
||
func fileTime(filename string) time.Time { | ||
fi, err := os.Stat(filename) | ||
if err != nil { | ||
if !os.IsNotExist(err) { | ||
log.Printf("%v: %v", filename, err) | ||
} | ||
return time.Time{} | ||
} | ||
return fi.ModTime() | ||
} | ||
|
||
func getCertificate(dataDir string) (*tls.Certificate, error) { | ||
info, ok := certificate.Load().(*certInfo) | ||
|
||
certFile := filepath.Join(dataDir, "cert.pem") | ||
keyFile := filepath.Join(dataDir, "key.pem") | ||
certTime := fileTime(certFile) | ||
keyTime := fileTime(keyFile) | ||
|
||
if !ok || !info.certTime.Equal(certTime) || !info.keyTime.Equal(keyTime) { | ||
var cert tls.Certificate | ||
if certTime.Equal(time.Time{}) || keyTime.Equal(time.Time{}) { | ||
log.Printf("Generating self-signed certificate") | ||
var err error | ||
cert, err = generateCertificate(dataDir) | ||
if err != nil { | ||
return nil, err | ||
} | ||
} else { | ||
var err error | ||
cert, err = tls.LoadX509KeyPair(certFile, keyFile) | ||
if err != nil { | ||
return nil, err | ||
} | ||
} | ||
info = &certInfo{ | ||
certificate: &cert, | ||
certTime: certTime, | ||
keyTime: keyTime, | ||
} | ||
certificate.Store(info) | ||
} | ||
return info.certificate, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters