Adds SelfSigned certificaterequest controller

Signed-off-by: JoshVanL <vleeuwenjoshua@gmail.com>
This commit is contained in:
JoshVanL 2019-07-22 15:43:19 +01:00
parent 8fa48c2148
commit 0ce8aab9d2
7 changed files with 658 additions and 29 deletions

View File

@ -17,12 +17,13 @@ limitations under the License.
package v1alpha1
const (
AltNamesAnnotationKey = "certmanager.k8s.io/alt-names"
IPSANAnnotationKey = "certmanager.k8s.io/ip-sans"
CommonNameAnnotationKey = "certmanager.k8s.io/common-name"
IssuerNameAnnotationKey = "certmanager.k8s.io/issuer-name"
IssuerKindAnnotationKey = "certmanager.k8s.io/issuer-kind"
CertificateNameKey = "certmanager.k8s.io/certificate-name"
AltNamesAnnotationKey = "certmanager.k8s.io/alt-names"
IPSANAnnotationKey = "certmanager.k8s.io/ip-sans"
CommonNameAnnotationKey = "certmanager.k8s.io/common-name"
IssuerNameAnnotationKey = "certmanager.k8s.io/issuer-name"
IssuerKindAnnotationKey = "certmanager.k8s.io/issuer-kind"
CertificateNameKey = "certmanager.k8s.io/certificate-name"
CRPrivateKeyAnnotationKey = "certmanager.k8s.io/private-key-secret-name"
)
// ConditionStatus represents a condition's status.

View File

@ -33,25 +33,6 @@ go_library(
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//pkg/controller/certificaterequests/ca:all-srcs",
"//pkg/controller/certificaterequests/fake:all-srcs",
"//pkg/controller/certificaterequests/util:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
go_test(
name = "go_default_test",
srcs = ["sync_test.go"],
@ -71,3 +52,23 @@ go_test(
"//vendor/k8s.io/utils/clock/testing:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//pkg/controller/certificaterequests/ca:all-srcs",
"//pkg/controller/certificaterequests/fake:all-srcs",
"//pkg/controller/certificaterequests/selfsigned:all-srcs",
"//pkg/controller/certificaterequests/util:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,54 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = ["selfsigned.go"],
importpath = "github.com/jetstack/cert-manager/pkg/controller/certificaterequests/selfsigned",
visibility = ["//visibility:public"],
deps = [
"//pkg/api/util:go_default_library",
"//pkg/apis/certmanager/v1alpha1:go_default_library",
"//pkg/controller:go_default_library",
"//pkg/controller/certificaterequests:go_default_library",
"//pkg/issuer:go_default_library",
"//pkg/logs:go_default_library",
"//pkg/util/kube:go_default_library",
"//pkg/util/pki:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/client-go/listers/core/v1:go_default_library",
"//vendor/k8s.io/client-go/tools/record:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = [
"selfsigned_test.go",
"util_test.go",
],
embed = [":go_default_library"],
deps = [
"//pkg/apis/certmanager/v1alpha1:go_default_library",
"//pkg/controller/test:go_default_library",
"//pkg/issuer:go_default_library",
"//pkg/util/pki:go_default_library",
"//test/unit/gen:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,124 @@
/*
Copyright 2019 The Jetstack cert-manager contributors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package selfsigned
import (
"context"
"errors"
"fmt"
corev1 "k8s.io/api/core/v1"
corelisters "k8s.io/client-go/listers/core/v1"
"k8s.io/client-go/tools/record"
apiutil "github.com/jetstack/cert-manager/pkg/api/util"
"github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha1"
controllerpkg "github.com/jetstack/cert-manager/pkg/controller"
"github.com/jetstack/cert-manager/pkg/controller/certificaterequests"
"github.com/jetstack/cert-manager/pkg/issuer"
logf "github.com/jetstack/cert-manager/pkg/logs"
"github.com/jetstack/cert-manager/pkg/util/kube"
"github.com/jetstack/cert-manager/pkg/util/pki"
)
const (
CRControllerName = "certificaterequests-issuer-selfsigned"
)
var (
errorNoAnnotation = fmt.Errorf("self signed issuer requires '%s' annotation set to secret name holding the private key",
v1alpha1.CRPrivateKeyAnnotationKey)
)
type SelfSigned struct {
// used to record Events about resources to the API
recorder record.EventRecorder
secretsLister corelisters.SecretLister
}
func init() {
// create certificate request controller for selfsigned issuer
controllerpkg.Register(CRControllerName, func(ctx *controllerpkg.Context) (controllerpkg.Interface, error) {
selfsigned := NewSelfSigned(ctx)
controller := certificaterequests.New(apiutil.IssuerCA, selfsigned)
c, err := controllerpkg.New(ctx, CRControllerName, controller)
if err != nil {
return nil, err
}
return c.Run, nil
})
}
func NewSelfSigned(ctx *controllerpkg.Context) *SelfSigned {
return &SelfSigned{
recorder: ctx.Recorder,
secretsLister: ctx.KubeSharedInformerFactory.Core().V1().Secrets().Lister(),
}
}
func (s *SelfSigned) Sign(ctx context.Context, cr *v1alpha1.CertificateRequest) (*issuer.IssueResponse, error) {
log := logf.FromContext(ctx, "sign")
skRef, ok := cr.ObjectMeta.Annotations[v1alpha1.CRPrivateKeyAnnotationKey]
if !ok || skRef == "" {
return nil, errorNoAnnotation
}
sk, err := kube.SecretTLSKey(ctx, s.secretsLister, cr.Namespace, skRef)
if err != nil {
return nil, fmt.Errorf("failed to get private key %s referenced in the annotation '%s': %s",
skRef, v1alpha1.CRPrivateKeyAnnotationKey, err)
}
template, err := pki.GenerateTemplateFromCertificateRequest(cr)
if err != nil {
log.Error(err, "error generating certificate template")
s.recorder.Eventf(cr, corev1.EventTypeWarning, "ErrorSigning", "Error generating certificate template: %v", err)
return nil, err
}
// extract the public component of the key
pk, err := pki.PublicKeyForPrivateKey(sk)
if err != nil {
log.Error(err, "failed to get public key from private key")
return nil, err
}
ok, err = pki.PublicKeyMatchesPublicKey(pk, template.PublicKey)
if err != nil {
log.Error(err, "failed to verify CSR is signed by referenced private key")
return nil, err
}
if !ok {
return nil, errors.New("CSR not signed by referenced private key")
}
// sign and encode the certificate
certPem, _, err := pki.SignCertificate(template, template, pk, sk)
if err != nil {
s.recorder.Eventf(cr, corev1.EventTypeWarning, "ErrorSigning", "Error signing certificate: %v", err)
return nil, err
}
log.Info("self signed certificate issued")
return &issuer.IssueResponse{
Certificate: certPem,
CA: certPem,
}, nil
}

View File

@ -0,0 +1,353 @@
/*
Copyright 2019 The Jetstack cert-manager contributors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package selfsigned
import (
"bytes"
"crypto"
"crypto/rand"
"crypto/x509"
"crypto/x509/pkix"
"encoding/asn1"
"encoding/pem"
"fmt"
"testing"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha1"
testpkg "github.com/jetstack/cert-manager/pkg/controller/test"
"github.com/jetstack/cert-manager/pkg/issuer"
"github.com/jetstack/cert-manager/pkg/util/pki"
"github.com/jetstack/cert-manager/test/unit/gen"
)
func generateCSR(t *testing.T, secretKey crypto.Signer, alg x509.SignatureAlgorithm) []byte {
asn1Subj, _ := asn1.Marshal(pkix.Name{
CommonName: "test",
}.ToRDNSequence())
template := x509.CertificateRequest{
RawSubject: asn1Subj,
SignatureAlgorithm: alg,
}
csrBytes, err := x509.CreateCertificateRequest(rand.Reader, &template, secretKey)
if err != nil {
t.Error(err)
t.FailNow()
}
csr := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE REQUEST", Bytes: csrBytes})
return csr
}
func TestSign(t *testing.T) {
skRSA, err := pki.GenerateRSAPrivateKey(2048)
if err != nil {
t.Errorf("failed to generate RSA private key: %s", err)
t.FailNow()
}
skEC, err := pki.GenerateECPrivateKey(256)
if err != nil {
t.Errorf("failed to generate ECDA private key: %s", err)
t.FailNow()
}
skAnotherRSA, err := pki.GenerateRSAPrivateKey(2048)
if err != nil {
t.Errorf("failed to generate RSA private key: %s", err)
t.FailNow()
}
csrBytes := generateCSR(t, skRSA, x509.SHA256WithRSA)
csrECBytes := generateCSR(t, skEC, x509.ECDSAWithSHA256)
skRSAPEMBytes := pki.EncodePKCS1PrivateKey(skRSA)
skAnotherRSAPEMBytes := pki.EncodePKCS1PrivateKey(skAnotherRSA)
skECPEMBytes, err := pki.EncodeECPrivateKey(skEC)
if err != nil {
t.Error(err)
t.FailNow()
}
rsaKeySecret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "test-rsa-key",
Namespace: gen.DefaultTestNamespace,
},
Data: map[string][]byte{
corev1.TLSPrivateKeyKey: skRSAPEMBytes,
},
}
anotherRSAKeySecret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "test-another-rsa-key",
Namespace: gen.DefaultTestNamespace,
},
Data: map[string][]byte{
corev1.TLSPrivateKeyKey: skAnotherRSAPEMBytes,
},
}
ecKeySecret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "test-ecdsa-key",
Namespace: gen.DefaultTestNamespace,
},
Data: map[string][]byte{
corev1.TLSPrivateKeyKey: skECPEMBytes,
},
}
badKeySecret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "test-bad-key",
Namespace: gen.DefaultTestNamespace,
},
Data: map[string][]byte{
corev1.TLSPrivateKeyKey: []byte("this is a bad key"),
},
}
tests := map[string]selfsignedFixture{
"a CertificateRequest with no certmanager.k8s.io/selfsigned-private-key annotation errors": {
Issuer: gen.Issuer("selfsigned-issuer",
gen.SetIssuerSelfSigned(v1alpha1.SelfSignedIssuer{}),
),
// no data in annotation
CertificateRequest: gen.CertificateRequest("test-cr"),
Builder: &testpkg.Builder{
KubeObjects: []runtime.Object{},
CertManagerObjects: []runtime.Object{},
},
Err: true,
CheckFn: func(t *testing.T, s *selfsignedFixture, args ...interface{}) {
err := args[2].(error)
if err == nil || err != errorNoAnnotation {
t.Errorf("unexpected error, exp='%s' got='%+v'", errorNoAnnotation, err)
}
},
},
"a CertificateRequest with a certmanager.k8s.io/private-key-secret-name annotation but empty string should error": {
Issuer: gen.Issuer("selfsigned-issuer",
gen.SetIssuerSelfSigned(v1alpha1.SelfSignedIssuer{}),
),
// no data in annotation
CertificateRequest: gen.CertificateRequest("test-cr",
gen.AddCertificateRequestAnnotations(map[string]string{
v1alpha1.CRPrivateKeyAnnotationKey: "",
}),
),
Builder: &testpkg.Builder{
KubeObjects: []runtime.Object{},
CertManagerObjects: []runtime.Object{},
},
Err: true,
CheckFn: func(t *testing.T, s *selfsignedFixture, args ...interface{}) {
err := args[2].(error)
if err == nil || err != errorNoAnnotation {
t.Errorf("unexpected error, exp='%s' got='%+v'", errorNoAnnotation, err)
}
},
},
"a CertificateRequest with a certmanager.k8s.io/private-key-secret-name annotation but the referenced secret doesn't exist should error": {
Issuer: gen.Issuer("selfsigned-issuer",
gen.SetIssuerSelfSigned(v1alpha1.SelfSignedIssuer{}),
),
CertificateRequest: gen.CertificateRequest("test-cr",
gen.AddCertificateRequestAnnotations(map[string]string{
v1alpha1.CRPrivateKeyAnnotationKey: "a-non-existent-secret",
}),
),
Builder: &testpkg.Builder{
KubeObjects: []runtime.Object{},
CertManagerObjects: []runtime.Object{},
},
Err: true,
CheckFn: func(t *testing.T, s *selfsignedFixture, args ...interface{}) {
notFoundError := `failed to get private key a-non-existent-secret referenced in the annotation 'certmanager.k8s.io/private-key-secret-name': secret "a-non-existent-secret" not found`
err := args[2].(error)
if err == nil || err.Error() != notFoundError {
t.Errorf("unexpected error, exp='%s' got='%+v'", notFoundError, err)
}
},
},
"a CertificateRequest with a bad CSR should error": {
Issuer: gen.Issuer("selfsigned-issuer",
gen.SetIssuerSelfSigned(v1alpha1.SelfSignedIssuer{}),
),
CertificateRequest: gen.CertificateRequest("test-cr",
gen.AddCertificateRequestAnnotations(map[string]string{
v1alpha1.CRPrivateKeyAnnotationKey: "test-rsa-key",
}),
gen.SetCertificateRequestCSR([]byte("this is a bad CSR")),
),
Builder: &testpkg.Builder{
KubeObjects: []runtime.Object{rsaKeySecret},
CertManagerObjects: []runtime.Object{},
},
Err: true,
CheckFn: func(t *testing.T, s *selfsignedFixture, args ...interface{}) {
parseCSRError := fmt.Sprintf("failed to decode csr from certificate request resource %s/test-cr", gen.DefaultTestNamespace)
err := args[2].(error)
if err == nil || err.Error() != parseCSRError {
t.Errorf("unexpected error, exp='%s' got='%+v'", parseCSRError, err)
}
},
},
"a CertificateRequest referencing a bad key should error": {
Issuer: gen.Issuer("selfsigned-issuer",
gen.SetIssuerSelfSigned(v1alpha1.SelfSignedIssuer{}),
),
CertificateRequest: gen.CertificateRequest("test-cr",
gen.AddCertificateRequestAnnotations(map[string]string{
v1alpha1.CRPrivateKeyAnnotationKey: "test-bad-key",
}),
gen.SetCertificateRequestCSR(csrBytes),
),
Builder: &testpkg.Builder{
KubeObjects: []runtime.Object{badKeySecret},
CertManagerObjects: []runtime.Object{},
},
Err: true,
CheckFn: func(t *testing.T, s *selfsignedFixture, args ...interface{}) {
badKeyError := "failed to get private key test-bad-key referenced in the annotation 'certmanager.k8s.io/private-key-secret-name': error decoding private key PEM block"
err := args[2].(error)
if err == nil || err.Error() != badKeyError {
t.Errorf("unexpected error, exp='%s' got='%+v'", badKeyError, err)
}
},
},
"a CertificateRequest referencing a key which did not sign the CSR should error": {
Issuer: gen.Issuer("selfsigned-issuer",
gen.SetIssuerSelfSigned(v1alpha1.SelfSignedIssuer{}),
),
CertificateRequest: gen.CertificateRequest("test-cr",
gen.AddCertificateRequestAnnotations(map[string]string{
v1alpha1.CRPrivateKeyAnnotationKey: "test-another-rsa-key",
}),
gen.SetCertificateRequestCSR(csrBytes),
),
Builder: &testpkg.Builder{
KubeObjects: []runtime.Object{anotherRSAKeySecret},
CertManagerObjects: []runtime.Object{},
},
Err: true,
CheckFn: func(t *testing.T, s *selfsignedFixture, args ...interface{}) {
badKeyError := "CSR not signed by referenced private key"
err := args[2].(error)
if err == nil || err.Error() != badKeyError {
t.Errorf("unexpected error, exp='%s' got='%+v'", badKeyError, err)
}
},
},
"a valid RSA key should sign a self signed certificate": {
Issuer: gen.Issuer("selfsigned-issuer",
gen.SetIssuerSelfSigned(v1alpha1.SelfSignedIssuer{}),
),
CertificateRequest: gen.CertificateRequest("test-cr",
gen.AddCertificateRequestAnnotations(map[string]string{
v1alpha1.CRPrivateKeyAnnotationKey: "test-rsa-key",
}),
gen.SetCertificateRequestCSR(csrBytes),
),
Builder: &testpkg.Builder{
KubeObjects: []runtime.Object{rsaKeySecret},
CertManagerObjects: []runtime.Object{},
},
Err: false,
CheckFn: func(t *testing.T, s *selfsignedFixture, args ...interface{}) {
resp := args[1].(*issuer.IssueResponse)
// CA and cert should be the same.
if !bytes.Equal(resp.CA, resp.Certificate) {
t.Errorf("expected CA and cert to be the same but got:\nCA: %s\nCert: %s",
resp.CA, resp.Certificate)
}
// No private key should be returned.
if len(resp.PrivateKey) > 0 {
t.Errorf("expected to private key returned but got: %s",
resp.PrivateKey)
}
},
},
"a valid ECDSA key should sign a self signed certificate": {
Issuer: gen.Issuer("selfsigned-issuer",
gen.SetIssuerSelfSigned(v1alpha1.SelfSignedIssuer{}),
),
CertificateRequest: gen.CertificateRequest("test-cr",
gen.AddCertificateRequestAnnotations(map[string]string{
v1alpha1.CRPrivateKeyAnnotationKey: "test-ecdsa-key",
}),
gen.SetCertificateRequestCSR(csrECBytes),
),
Builder: &testpkg.Builder{
KubeObjects: []runtime.Object{ecKeySecret},
CertManagerObjects: []runtime.Object{},
},
Err: false,
CheckFn: func(t *testing.T, s *selfsignedFixture, args ...interface{}) {
resp := args[1].(*issuer.IssueResponse)
if resp == nil {
t.Errorf("expected a response but got: %+v",
args[1])
return
}
// CA and cert should be the same.
if !bytes.Equal(resp.CA, resp.Certificate) {
t.Errorf("expected CA and cert to be the same but got:\nCA: %s\nCert: %s",
resp.CA, resp.Certificate)
}
// No private key should be returned.
if len(resp.PrivateKey) > 0 {
t.Errorf("expected to private key returned but got: %s",
resp.PrivateKey)
}
},
},
}
for name, test := range tests {
t.Run(name, func(t *testing.T) {
if test.Builder == nil {
test.Builder = &testpkg.Builder{}
}
test.Setup(t)
crCopy := test.CertificateRequest.DeepCopy()
resp, err := test.SelfSigned.Sign(test.Ctx, crCopy)
if err != nil && !test.Err {
t.Errorf("Expected function to not error, but got: %v", err)
}
if err == nil && test.Err {
t.Errorf("Expected function to get an error, but got: %v", err)
}
if test.Err && resp != nil {
t.Errorf("unexpected response, exp=nil got='%+v'", resp)
}
if !test.Err && resp == nil {
t.Errorf("expected response but got nil")
}
test.Finish(t, crCopy, resp, err)
})
}
}

View File

@ -0,0 +1,92 @@
/*
Copyright 2019 The Jetstack cert-manager contributors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package selfsigned
import (
"context"
"testing"
"github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha1"
"github.com/jetstack/cert-manager/pkg/controller/test"
)
type selfsignedFixture struct {
SelfSigned *SelfSigned
*test.Builder
Issuer v1alpha1.GenericIssuer
Certificate *v1alpha1.Certificate
CertificateRequest *v1alpha1.CertificateRequest
PreFn func(*testing.T, *selfsignedFixture)
CheckFn func(*testing.T, *selfsignedFixture, ...interface{})
Err bool
Ctx context.Context
}
func (s *selfsignedFixture) Setup(t *testing.T) {
if s.Issuer == nil {
s.Issuer = &v1alpha1.Issuer{
Spec: v1alpha1.IssuerSpec{
IssuerConfig: v1alpha1.IssuerConfig{
SelfSigned: &v1alpha1.SelfSignedIssuer{},
},
},
}
}
if s.Ctx == nil {
s.Ctx = context.Background()
}
if s.Builder == nil {
// TODO: set default IssuerOptions
// defaultTestAcmeClusterResourceNamespace,
// defaultTestSolverImage,
// default dns01 nameservers
// ambient credentials settings
s.Builder = &test.Builder{}
}
if s.Builder.T == nil {
s.Builder.T = t
}
s.SelfSigned = s.buildFakeSelfSigned(s.Builder, s.Issuer)
if s.PreFn != nil {
s.PreFn(t, s)
s.Builder.Sync()
}
}
func (s *selfsignedFixture) Finish(t *testing.T, args ...interface{}) {
defer s.Builder.Stop()
if err := s.Builder.AllReactorsCalled(); err != nil {
t.Errorf("Not all expected reactors were called: %v", err)
}
if err := s.Builder.AllActionsExecuted(); err != nil {
t.Errorf(err.Error())
}
// resync listers before running checks
s.Builder.Sync()
// run custom checks
if s.CheckFn != nil {
s.CheckFn(t, s, args...)
}
}
func (s *selfsignedFixture) buildFakeSelfSigned(b *test.Builder, issuer v1alpha1.GenericIssuer) *SelfSigned {
b.Start()
selfsignedStruct := NewSelfSigned(b.Context)
b.Sync()
return selfsignedStruct
}

View File

@ -210,9 +210,13 @@ func PublicKeyMatchesCertificate(check crypto.PublicKey, crt *x509.Certificate)
// It will return an error if either of the passed parameters are of an
// unrecognised type (i.e. non RSA/ECDSA)
func PublicKeyMatchesCSR(check crypto.PublicKey, csr *x509.CertificateRequest) (bool, error) {
switch pub := csr.PublicKey.(type) {
return PublicKeyMatchesPublicKey(check, csr.PublicKey)
}
func PublicKeyMatchesPublicKey(a, b crypto.PublicKey) (bool, error) {
switch pub := a.(type) {
case *rsa.PublicKey:
rsaCheck, ok := check.(*rsa.PublicKey)
rsaCheck, ok := b.(*rsa.PublicKey)
if !ok {
return false, nil
}
@ -221,7 +225,7 @@ func PublicKeyMatchesCSR(check crypto.PublicKey, csr *x509.CertificateRequest) (
}
return true, nil
case *ecdsa.PublicKey:
ecdsaCheck, ok := check.(*ecdsa.PublicKey)
ecdsaCheck, ok := b.(*ecdsa.PublicKey)
if !ok {
return false, nil
}
@ -230,6 +234,6 @@ func PublicKeyMatchesCSR(check crypto.PublicKey, csr *x509.CertificateRequest) (
}
return true, nil
default:
return false, fmt.Errorf("unrecognised Certificate public key type")
return false, fmt.Errorf("unrecognised public key type")
}
}