Skip to content

Commit c745b80

Browse files
author
Mengqi Yu
committed
address comments
1 parent 43f54a4 commit c745b80

23 files changed

+1359
-1040
lines changed

pkg/admission/certgenerator/certgenerator.go renamed to pkg/admission/cert/generator/certgenerator.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,18 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
package certgenerator
17+
package generator
1818

19-
// CertArtifacts hosts a private key, its corresponding serving certificate and
19+
// Artifacts hosts a private key, its corresponding serving certificate and
2020
// the CA certificate that signs the serving certificate.
21-
type CertArtifacts struct {
21+
type Artifacts struct {
2222
Key []byte
2323
Cert []byte
2424
CACert []byte
2525
}
2626

2727
// CertGenerator is an interface to provision the serving certificate.
2828
type CertGenerator interface {
29-
// Generate returns a CertArtifacts struct.
30-
Generate(CommonName string) (*CertArtifacts, error)
29+
// Generate returns a Artifacts struct.
30+
Generate(CommonName string) (*Artifacts, error)
3131
}

pkg/admission/certgenerator/certgenerator_test.go renamed to pkg/admission/cert/generator/certgenerator_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
package certgenerator
17+
package generator
1818

1919
import "fmt"
2020

pkg/admission/certgenerator/doc.go renamed to pkg/admission/cert/generator/doc.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,16 @@ limitations under the License.
1515
*/
1616

1717
/*
18-
Package certgenerator provides an interface and implementation to provision certificates.
18+
Package generator provides an interface and implementation to provision certificates.
1919
2020
Create an instance of CertGenerator.
2121
2222
cg := SelfSignedCertGenerator{}
2323
2424
Generate the certificates.
25-
certs, err := cp.Generate("foo.bar.com")
25+
certs, err := cg.Generate("foo.bar.com")
2626
if err != nil {
2727
// handle error
2828
}
2929
*/
30-
package certgenerator
30+
package generator

pkg/admission/certgenerator/fake/certgenerator.go renamed to pkg/admission/cert/generator/fake/certgenerator.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,21 @@ package fake
1919
import (
2020
"fmt"
2121

22-
"sigs.k8s.io/controller-runtime/pkg/admission/certgenerator"
22+
"sigs.k8s.io/controller-runtime/pkg/admission/cert/generator"
2323
)
2424

25-
// FakeCertGenerator is a CertGenerator for testing.
26-
type FakeCertGenerator struct {
27-
DnsNameToCertArtifacts map[string]*certgenerator.CertArtifacts
25+
// CertGenerator is a CertGenerator for testing.
26+
type CertGenerator struct {
27+
DNSNameToCertArtifacts map[string]*generator.Artifacts
2828
}
2929

30-
var _ certgenerator.CertGenerator = &FakeCertGenerator{}
30+
var _ generator.CertGenerator = &CertGenerator{}
3131

32-
func (cp *FakeCertGenerator) Generate(commonName string) (*certgenerator.CertArtifacts, error) {
33-
certs, found := cp.DnsNameToCertArtifacts[commonName]
32+
// Generate generates certificates by matching a common name.
33+
func (cp *CertGenerator) Generate(commonName string) (*generator.Artifacts, error) {
34+
certs, found := cp.DNSNameToCertArtifacts[commonName]
3435
if !found {
35-
return nil, fmt.Errorf("failed to find common name %q in the FakeCertGenerator", commonName)
36+
return nil, fmt.Errorf("failed to find common name %q in the CertGenerator", commonName)
3637
}
3738
return certs, nil
3839
}

pkg/admission/certgenerator/selfsigned.go renamed to pkg/admission/cert/generator/selfsigned.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
package certgenerator
17+
package generator
1818

1919
import (
2020
"crypto/x509"
@@ -39,7 +39,7 @@ var _ CertGenerator = &SelfSignedCertGenerator{}
3939
// to establish trust for clients, CA certificate is used by the
4040
// client to verify the server authentication chain.
4141
// The cert will be valid for 365 days.
42-
func (cp *SelfSignedCertGenerator) Generate(commonName string) (*CertArtifacts, error) {
42+
func (cp *SelfSignedCertGenerator) Generate(commonName string) (*Artifacts, error) {
4343
signingKey, err := cert.NewPrivateKey()
4444
if err != nil {
4545
return nil, fmt.Errorf("failed to create the CA private key: %v", err)
@@ -62,7 +62,7 @@ func (cp *SelfSignedCertGenerator) Generate(commonName string) (*CertArtifacts,
6262
if err != nil {
6363
return nil, fmt.Errorf("failed to create the cert: %v", err)
6464
}
65-
return &CertArtifacts{
65+
return &Artifacts{
6666
Key: cert.EncodePrivateKeyPEM(key),
6767
Cert: cert.EncodeCertPEM(signedCert),
6868
CACert: cert.EncodeCertPEM(signingCert),

pkg/admission/certgenerator/selfsigned_test.go renamed to pkg/admission/cert/generator/selfsigned_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
package certgenerator
17+
package generator
1818

1919
import (
2020
"crypto/x509"

pkg/admission/certwriter/certwriter.go renamed to pkg/admission/cert/writer/certwriter.go

Lines changed: 85 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,21 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
package certwriter
17+
package writer
1818

1919
import (
2020
"bytes"
21+
"crypto/tls"
22+
"errors"
2123
"fmt"
24+
"log"
2225
"net/url"
2326

2427
admissionregistrationv1beta1 "k8s.io/api/admissionregistration/v1beta1"
2528
apierrors "k8s.io/apimachinery/pkg/api/errors"
2629
"k8s.io/apimachinery/pkg/runtime"
27-
28-
"crypto/tls"
29-
30-
"sigs.k8s.io/controller-runtime/pkg/admission/certgenerator"
30+
"sigs.k8s.io/controller-runtime/pkg/admission/cert/generator"
31+
"sigs.k8s.io/controller-runtime/pkg/client"
3132
)
3233

3334
const (
@@ -41,31 +42,60 @@ const (
4142

4243
// CertWriter provides method to handle webhooks.
4344
type CertWriter interface {
44-
// EnsureCert ensures that the webhooks it manages have the right certificates.
45-
EnsureCert() error
45+
// EnsureCert ensures that the webhooks have proper certificates.
46+
EnsureCerts(runtime.Object) error
47+
}
48+
49+
// Options are options for configuring a CertWriter.
50+
type Options struct {
51+
Client client.Client
52+
CertGenerator generator.CertGenerator
53+
}
54+
55+
// NewCertWriter builds a new CertWriter using the provided options.
56+
// By default, it builds a MultiCertWriter that is composed of a SecretCertWriter and a FSCertWriter.
57+
func NewCertWriter(ops Options) (CertWriter, error) {
58+
if ops.CertGenerator == nil {
59+
ops.CertGenerator = &generator.SelfSignedCertGenerator{}
60+
}
61+
if ops.Client == nil {
62+
// TODO: default the client if possible
63+
return nil, errors.New("Options.Client is required")
64+
}
65+
s := &SecretCertWriter{
66+
Client: ops.Client,
67+
CertGenerator: ops.CertGenerator,
68+
}
69+
//f := &FSCertWriter{
70+
// CertGenerator: ops.CertGenerator,
71+
//}
72+
return &MultiCertWriter{
73+
CertWriters: []CertWriter{
74+
s,
75+
//f,
76+
},
77+
}, nil
4678
}
4779

80+
// handleCommon ensures the given webhook has a proper certificate.
81+
// It uses the given certReadWriter to read and (or) write the certificate.
4882
func handleCommon(webhook *admissionregistrationv1beta1.Webhook, ch certReadWriter) error {
49-
webhookName := webhook.Name
50-
certs, err := ch.read(webhookName)
51-
if apierrors.IsNotFound(err) {
52-
certs, err = ch.write(webhookName)
53-
switch {
54-
case apierrors.IsAlreadyExists(err):
55-
certs, err = ch.read(webhookName)
56-
if err != nil {
57-
return err
58-
}
59-
case err != nil:
60-
return err
61-
}
62-
} else if err != nil {
83+
if webhook == nil {
84+
return nil
85+
}
86+
if ch == nil {
87+
return errors.New("certReaderWriter should not be nil")
88+
}
89+
90+
certs, err := createIfNotExists(webhook.Name, ch)
91+
if err != nil {
6392
return err
6493
}
6594

6695
// Recreate the cert if it's invalid.
6796
if !validCert(certs) {
68-
certs, err = ch.overwrite(webhookName)
97+
log.Printf("cert is invalid or expiring, regenerating a new one")
98+
certs, err = ch.overwrite(webhook.Name)
6999
if err != nil {
70100
return err
71101
}
@@ -80,17 +110,39 @@ func handleCommon(webhook *admissionregistrationv1beta1.Webhook, ch certReadWrit
80110
return nil
81111
}
82112

83-
// certReadWriter provides methods for handling certificates for webhook.
113+
func createIfNotExists(webhookName string, ch certReadWriter) (*generator.Artifacts, error) {
114+
// Try to read first
115+
certs, err := ch.read(webhookName)
116+
if apierrors.IsNotFound(err) {
117+
// Create if not exists
118+
certs, err = ch.write(webhookName)
119+
switch {
120+
// This may happen if there is another racer.
121+
case apierrors.IsAlreadyExists(err):
122+
certs, err = ch.read(webhookName)
123+
if err != nil {
124+
return certs, err
125+
}
126+
case err != nil:
127+
return certs, err
128+
}
129+
} else if err != nil {
130+
return certs, err
131+
}
132+
return certs, nil
133+
}
134+
135+
// certReadWriter provides methods for reading and writing certificates.
84136
type certReadWriter interface {
85137
// read reads a wehbook name and returns the certs for it.
86-
read(webhookName string) (*certgenerator.CertArtifacts, error)
138+
read(webhookName string) (*generator.Artifacts, error)
87139
// write writes the certs and return the certs it wrote.
88-
write(webhookName string) (*certgenerator.CertArtifacts, error)
140+
write(webhookName string) (*generator.Artifacts, error)
89141
// overwrite overwrites the existing certs and return the certs it wrote.
90-
overwrite(webhookName string) (*certgenerator.CertArtifacts, error)
142+
overwrite(webhookName string) (*generator.Artifacts, error)
91143
}
92144

93-
func validCert(certs *certgenerator.CertArtifacts) bool {
145+
func validCert(certs *generator.Artifacts) bool {
94146
// TODO:
95147
// 1) validate the key and the cert are valid pair e.g. call crypto/tls.X509KeyPair()
96148
// 2) validate the cert with the CA cert
@@ -118,19 +170,18 @@ func getWebhooksFromObject(obj runtime.Object) ([]admissionregistrationv1beta1.W
118170
}
119171
}
120172

121-
func webhookClientConfigToCommonName(config *admissionregistrationv1beta1.WebhookClientConfig) (string, error) {
173+
func dnsNameForWebhook(config *admissionregistrationv1beta1.WebhookClientConfig) (string, error) {
122174
if config.Service != nil && config.URL != nil {
123175
return "", fmt.Errorf("service and URL can't be set at the same time in a webhook: %v", config)
124176
}
125177
if config.Service == nil && config.URL == nil {
126178
return "", fmt.Errorf("one of service and URL need to be set in a webhook: %v", config)
127179
}
128180
if config.Service != nil {
129-
return certgenerator.ServiceToCommonName(config.Service.Namespace, config.Service.Name), nil
181+
return generator.ServiceToCommonName(config.Service.Namespace, config.Service.Name), nil
130182
}
131-
if config.URL != nil {
132-
u, err := url.Parse(*config.URL)
133-
return u.Host, err
134-
}
135-
return "", nil
183+
// config.URL != nil
184+
u, err := url.Parse(*config.URL)
185+
return u.Host, err
186+
136187
}

0 commit comments

Comments
 (0)