internal/test.go accepts fixed clock and Shares
generaleLocallySignedCertificate Signed-off-by: JoshVanL <vleeuwenjoshua@gmail.com>
This commit is contained in:
parent
7d1d94fedb
commit
c115e6c2bf
@ -12,7 +12,6 @@ go_library(
|
||||
"//pkg/api/util:go_default_library",
|
||||
"//pkg/apis/certmanager/v1alpha2:go_default_library",
|
||||
"//pkg/apis/meta/v1:go_default_library",
|
||||
"//pkg/controller:go_default_library",
|
||||
"//pkg/util/pki:go_default_library",
|
||||
"@com_github_pavel_v_chernykh_keystore_go//:go_default_library",
|
||||
"@com_sslmate_software_src_go_pkcs12//:go_default_library",
|
||||
@ -45,6 +44,7 @@ go_test(
|
||||
"@io_k8s_apimachinery//pkg/apis/meta/v1:go_default_library",
|
||||
"@io_k8s_apimachinery//pkg/runtime:go_default_library",
|
||||
"@io_k8s_client_go//testing:go_default_library",
|
||||
"@io_k8s_utils//clock/testing:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@ -31,7 +31,6 @@ import (
|
||||
apiutil "github.com/jetstack/cert-manager/pkg/api/util"
|
||||
cmapi "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha2"
|
||||
cmmeta "github.com/jetstack/cert-manager/pkg/apis/meta/v1"
|
||||
controllerpkg "github.com/jetstack/cert-manager/pkg/controller"
|
||||
utilpki "github.com/jetstack/cert-manager/pkg/util/pki"
|
||||
)
|
||||
|
||||
@ -58,12 +57,12 @@ type SecretData struct {
|
||||
func New(
|
||||
kubeClient kubernetes.Interface,
|
||||
secretLister corelisters.SecretLister,
|
||||
CertificateificateControllerOptions controllerpkg.CertificateOptions,
|
||||
enableSecretOwnerReferences bool,
|
||||
) *SecretsManager {
|
||||
return &SecretsManager{
|
||||
kubeClient: kubeClient,
|
||||
secretLister: secretLister,
|
||||
enableSecretOwnerReferences: CertificateificateControllerOptions.EnableOwnerRef,
|
||||
enableSecretOwnerReferences: enableSecretOwnerReferences,
|
||||
}
|
||||
}
|
||||
|
||||
@ -131,7 +130,7 @@ func (s *SecretsManager) setValues(crt *cmapi.Certificate, secret *corev1.Secret
|
||||
secret.Data = make(map[string][]byte)
|
||||
}
|
||||
|
||||
// Only write a new PKCS12/JKS file if any of the private key/Certificateificate/CA
|
||||
// Only write a new PKCS12/JKS file if any of the private key/Certificate/CA
|
||||
// data has actually changed.
|
||||
if data.PrivateKey != nil && data.Certificate != nil &&
|
||||
(!bytes.Equal(secret.Data[corev1.TLSPrivateKeyKey], data.PrivateKey) ||
|
||||
@ -212,7 +211,7 @@ func (s *SecretsManager) setValues(crt *cmapi.Certificate, secret *corev1.Secret
|
||||
secret.Annotations[cmapi.DeprecatedIssuerKindAnnotationKey] = apiutil.IssuerKind(crt.Spec.IssuerRef)
|
||||
}
|
||||
|
||||
// if the Certificateificate data is empty, clear the subject related annotations
|
||||
// if the Certificate data is empty, clear the subject related annotations
|
||||
if len(data.Certificate) == 0 {
|
||||
delete(secret.Annotations, cmapi.CommonNameAnnotationKey)
|
||||
delete(secret.Annotations, cmapi.AltNamesAnnotationKey)
|
||||
|
||||
@ -26,6 +26,7 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
coretesting "k8s.io/client-go/testing"
|
||||
fakeclock "k8s.io/utils/clock/testing"
|
||||
|
||||
cmapi "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha2"
|
||||
cmmeta "github.com/jetstack/cert-manager/pkg/apis/meta/v1"
|
||||
@ -36,6 +37,11 @@ import (
|
||||
"github.com/jetstack/cert-manager/test/unit/gen"
|
||||
)
|
||||
|
||||
var (
|
||||
fixedClockStart = time.Now()
|
||||
fixedClock = fakeclock.NewFakeClock(fixedClockStart)
|
||||
)
|
||||
|
||||
func TestSecretsManager(t *testing.T) {
|
||||
type testT struct {
|
||||
builder *testpkg.Builder
|
||||
@ -55,7 +61,7 @@ func TestSecretsManager(t *testing.T) {
|
||||
)
|
||||
exampleBundle := internaltest.MustCreateCryptoBundle(t, gen.CertificateFrom(baseCert,
|
||||
gen.SetCertificateDNSNames("example.com"),
|
||||
))
|
||||
), fixedClock)
|
||||
|
||||
tests := map[string]testT{
|
||||
"if secret does not exists and unable to decode certificate, then error": {
|
||||
@ -271,7 +277,8 @@ func TestSecretsManager(t *testing.T) {
|
||||
|
||||
for name, test := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
test.builder.Clock = internaltest.FixedClock
|
||||
fixedClock.SetTime(fixedClockStart)
|
||||
test.builder.Clock = fixedClock
|
||||
test.builder.T = t
|
||||
test.builder.Init()
|
||||
defer test.builder.Stop()
|
||||
@ -282,7 +289,7 @@ func TestSecretsManager(t *testing.T) {
|
||||
testManager := New(
|
||||
kubeClient,
|
||||
secretsLister,
|
||||
test.certificateOptions,
|
||||
test.certificateOptions.EnableOwnerRef,
|
||||
)
|
||||
|
||||
test.builder.Start()
|
||||
|
||||
@ -9,6 +9,7 @@ go_library(
|
||||
"//pkg/api/util:go_default_library",
|
||||
"//pkg/apis/certmanager/v1alpha2:go_default_library",
|
||||
"//pkg/apis/meta/v1:go_default_library",
|
||||
"//pkg/controller/expcertificates:go_default_library",
|
||||
"//pkg/util/pki:go_default_library",
|
||||
"//test/unit/gen:go_default_library",
|
||||
"@io_k8s_apimachinery//pkg/apis/meta/v1:go_default_library",
|
||||
|
||||
@ -21,7 +21,6 @@ import (
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@ -31,17 +30,13 @@ import (
|
||||
apiutil "github.com/jetstack/cert-manager/pkg/api/util"
|
||||
cmapi "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha2"
|
||||
cmmeta "github.com/jetstack/cert-manager/pkg/apis/meta/v1"
|
||||
certificates "github.com/jetstack/cert-manager/pkg/controller/expcertificates"
|
||||
"github.com/jetstack/cert-manager/pkg/util/pki"
|
||||
"github.com/jetstack/cert-manager/test/unit/gen"
|
||||
)
|
||||
|
||||
const staticTemporarySerialNumber = 0x1234567890
|
||||
|
||||
var (
|
||||
certificateGvk = cmapi.SchemeGroupVersion.WithKind("Certificate")
|
||||
|
||||
FixedClockStart = time.Now()
|
||||
FixedClock = fakeclock.NewFakeClock(FixedClockStart)
|
||||
)
|
||||
|
||||
type CryptoBundle struct {
|
||||
@ -73,17 +68,19 @@ type CryptoBundle struct {
|
||||
CertBytes []byte
|
||||
|
||||
LocalTemporaryCertificateBytes []byte
|
||||
|
||||
FixedClock *fakeclock.FakeClock
|
||||
}
|
||||
|
||||
func MustCreateCryptoBundle(t *testing.T, crt *cmapi.Certificate) CryptoBundle {
|
||||
c, err := createCryptoBundle(crt)
|
||||
func MustCreateCryptoBundle(t *testing.T, crt *cmapi.Certificate, fixedClock *fakeclock.FakeClock) CryptoBundle {
|
||||
c, err := createCryptoBundle(crt, fixedClock)
|
||||
if err != nil {
|
||||
t.Fatalf("error generating crypto bundle: %v", err)
|
||||
}
|
||||
return *c
|
||||
}
|
||||
|
||||
func createCryptoBundle(crt *cmapi.Certificate) (*CryptoBundle, error) {
|
||||
func createCryptoBundle(crt *cmapi.Certificate, fixedClock *fakeclock.FakeClock) (*CryptoBundle, error) {
|
||||
reqName, err := apiutil.ComputeCertificateRequestName(crt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -177,7 +174,7 @@ func createCryptoBundle(crt *cmapi.Certificate) (*CryptoBundle, error) {
|
||||
}),
|
||||
)
|
||||
|
||||
tempCertBytes, err := generateLocallySignedTemporaryCertificate(crt, privateKeyBytes)
|
||||
tempCertBytes, err := certificates.GenerateLocallySignedTemporaryCertificate(crt, privateKeyBytes)
|
||||
if err != nil {
|
||||
panic("failed to generate test fixture: " + err.Error())
|
||||
}
|
||||
@ -197,6 +194,7 @@ func createCryptoBundle(crt *cmapi.Certificate) (*CryptoBundle, error) {
|
||||
Cert: cert,
|
||||
CertBytes: certBytes,
|
||||
LocalTemporaryCertificateBytes: tempCertBytes,
|
||||
FixedClock: fixedClock,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -253,7 +251,7 @@ func (c *CryptoBundle) generateCertificateExpiring1H(crt *cmapi.Certificate) []b
|
||||
panic("failed to generate test fixture: " + err.Error())
|
||||
}
|
||||
|
||||
nowTime := FixedClock.Now()
|
||||
nowTime := c.FixedClock.Now()
|
||||
duration := unsignedCert.NotAfter.Sub(unsignedCert.NotBefore)
|
||||
unsignedCert.NotBefore = nowTime.Add(time.Hour).Add(-1 * duration)
|
||||
unsignedCert.NotAfter = nowTime.Add(time.Hour)
|
||||
@ -282,7 +280,7 @@ func (c *CryptoBundle) generateCertificateExpired(crt *cmapi.Certificate) []byte
|
||||
panic("failed to generate test fixture: " + err.Error())
|
||||
}
|
||||
|
||||
nowTime := FixedClock.Now()
|
||||
nowTime := c.FixedClock.Now()
|
||||
duration := unsignedCert.NotAfter.Sub(unsignedCert.NotBefore)
|
||||
unsignedCert.NotBefore = nowTime.Add(-1 * time.Hour).Add(-1 * duration)
|
||||
unsignedCert.NotAfter = nowTime.Add(-1 * time.Hour)
|
||||
@ -317,43 +315,3 @@ func generateCSRImpl(crt *cmapi.Certificate, pk []byte) ([]byte, error) {
|
||||
|
||||
return csrPEM, nil
|
||||
}
|
||||
|
||||
func generateLocallySignedTemporaryCertificate(crt *cmapi.Certificate, pkData []byte) ([]byte, error) {
|
||||
// generate a throwaway self-signed root CA
|
||||
caPk, err := pki.GenerateECPrivateKey(pki.ECCurve521)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
caCertTemplate, err := pki.GenerateTemplate(&cmapi.Certificate{
|
||||
Spec: cmapi.CertificateSpec{
|
||||
CommonName: "cert-manager.local",
|
||||
IsCA: true,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, caCert, err := pki.SignCertificate(caCertTemplate, caCertTemplate, caPk.Public(), caPk)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// sign a temporary certificate using the root CA
|
||||
template, err := pki.GenerateTemplate(crt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
template.SerialNumber = big.NewInt(staticTemporarySerialNumber)
|
||||
|
||||
signeeKey, err := pki.DecodePrivateKeyBytes(pkData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b, _, err := pki.SignCertificate(template, caCert, signeeKey.Public(), caPk)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
@ -203,3 +203,52 @@ func SecretDataAltNamesMatchSpec(secret *corev1.Secret, spec cmapi.CertificateSp
|
||||
|
||||
return violations, nil
|
||||
}
|
||||
|
||||
// staticTemporarySerialNumber is a fixed serial number we use for temporary certificates
|
||||
const staticTemporarySerialNumber = "1234567890"
|
||||
|
||||
// GenerateLocallySignedTemporaryCertificate signs a temporary certificate for
|
||||
// the given certificate resource using a one-use temporary CA that is then
|
||||
// discarded afterwards.
|
||||
// This is to mitigate a potential attack against x509 certificates that use a
|
||||
// predictable serial number and weak MD5 hashing algorithms.
|
||||
// In practice, this shouldn't really be a concern anyway.
|
||||
func GenerateLocallySignedTemporaryCertificate(crt *cmapi.Certificate, pkData []byte) ([]byte, error) {
|
||||
// generate a throwaway self-signed root CA
|
||||
caPk, err := pki.GenerateECPrivateKey(pki.ECCurve521)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
caCertTemplate, err := pki.GenerateTemplate(&cmapi.Certificate{
|
||||
Spec: cmapi.CertificateSpec{
|
||||
CommonName: "cert-manager.local",
|
||||
IsCA: true,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, caCert, err := pki.SignCertificate(caCertTemplate, caCertTemplate, caPk.Public(), caPk)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// sign a temporary certificate using the root CA
|
||||
template, err := pki.GenerateTemplate(crt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
template.Subject.SerialNumber = staticTemporarySerialNumber
|
||||
|
||||
signeeKey, err := pki.DecodePrivateKeyBytes(pkData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b, _, err := pki.SignCertificate(template, caCert, signeeKey.Public(), caPk)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user