forked from TrueCloudLab/lego
Add a function to check cert expiration dates.
This commit is contained in:
parent
9160122ebe
commit
34910bd541
3 changed files with 74 additions and 32 deletions
|
@ -6,6 +6,8 @@ import (
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"crypto/x509/pkix"
|
"crypto/x509/pkix"
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
|
"math/big"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func generatePrivateKey(keyLength int) (*rsa.PrivateKey, error) {
|
func generatePrivateKey(keyLength int) (*rsa.PrivateKey, error) {
|
||||||
|
@ -31,3 +33,49 @@ func pemEncode(data interface{}) []byte {
|
||||||
|
|
||||||
return pem.EncodeToMemory(pemBlock)
|
return pem.EncodeToMemory(pemBlock)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetCertExpiration(cert []byte) (time.Time, error) {
|
||||||
|
pCert, err := x509.ParseCertificate(cert)
|
||||||
|
if err != nil {
|
||||||
|
return time.Time{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return pCert.NotAfter, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func generatePemCert(privKey *rsa.PrivateKey, domain string) ([]byte, error) {
|
||||||
|
derBytes, err := generateDerCert(privKey, time.Time{}, domain)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes}), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateDerCert(privKey *rsa.PrivateKey, expiration time.Time, domain string) ([]byte, error) {
|
||||||
|
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
|
||||||
|
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
zero := time.Time{}
|
||||||
|
if expiration == zero {
|
||||||
|
expiration = time.Now().Add(365)
|
||||||
|
}
|
||||||
|
|
||||||
|
template := x509.Certificate{
|
||||||
|
SerialNumber: serialNumber,
|
||||||
|
Subject: pkix.Name{
|
||||||
|
CommonName: "ACME Challenge TEMP",
|
||||||
|
},
|
||||||
|
NotBefore: time.Now(),
|
||||||
|
NotAfter: expiration,
|
||||||
|
|
||||||
|
KeyUsage: x509.KeyUsageKeyEncipherment,
|
||||||
|
BasicConstraintsValid: true,
|
||||||
|
DNSNames: []string{domain},
|
||||||
|
}
|
||||||
|
|
||||||
|
return x509.CreateCertificate(rand.Reader, &template, &template, &privKey.PublicKey, privKey)
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGeneratePrivateKey(t *testing.T) {
|
func TestGeneratePrivateKey(t *testing.T) {
|
||||||
|
@ -50,6 +51,30 @@ func TestPEMEncode(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCertExpiration(t *testing.T) {
|
||||||
|
privKey, err := generatePrivateKey(2048)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Error generating private key:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
expiration := time.Now().Add(365)
|
||||||
|
expiration = expiration.Round(time.Second)
|
||||||
|
certBytes, err := generateDerCert(privKey, expiration, "test.com")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Error generating cert:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := bytes.NewBufferString("TestingRSAIsSoMuchFun")
|
||||||
|
|
||||||
|
if ctime, err := GetCertExpiration(buf.Bytes()); err == nil {
|
||||||
|
t.Errorf("Expected getCertExpiration to return an error for garbage string but returned %v", ctime)
|
||||||
|
}
|
||||||
|
|
||||||
|
if ctime, err := GetCertExpiration(certBytes); err != nil || ctime != expiration.UTC() {
|
||||||
|
t.Errorf("Expected getCertExpiration to return %v but returned: %v, err: %v", expiration.UTC(), ctime, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type MockRandReader struct {
|
type MockRandReader struct {
|
||||||
b *bytes.Buffer
|
b *bytes.Buffer
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,16 +2,13 @@ package acme
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/rsa"
|
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"crypto/x509/pkix"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math/big"
|
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -122,7 +119,7 @@ func (s *simpleHTTPChallenge) startHTTPSServer(domain string, token string) (net
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
tempCertPEM, err := generateCert(tempPrivKey, domain)
|
tempCertPEM, err := generatePemCert(tempPrivKey, domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -190,31 +187,3 @@ func getRandomString(length int) string {
|
||||||
}
|
}
|
||||||
return string(bytes)
|
return string(bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateCert(privKey *rsa.PrivateKey, domain string) ([]byte, error) {
|
|
||||||
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
|
|
||||||
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
template := x509.Certificate{
|
|
||||||
SerialNumber: serialNumber,
|
|
||||||
Subject: pkix.Name{
|
|
||||||
CommonName: "ACME Challenge TEMP",
|
|
||||||
},
|
|
||||||
NotBefore: time.Now(),
|
|
||||||
NotAfter: time.Now().Add(365),
|
|
||||||
|
|
||||||
KeyUsage: x509.KeyUsageKeyEncipherment,
|
|
||||||
BasicConstraintsValid: true,
|
|
||||||
DNSNames: []string{domain},
|
|
||||||
}
|
|
||||||
|
|
||||||
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &privKey.PublicKey, privKey)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes}), nil
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue