Skip to content

Commit a08cda9

Browse files
authored
Merge pull request #245 from mengqiy/sscp
implement SelfSignedCertProvisioner
2 parents fea9e3a + 6c9013c commit a08cda9

File tree

6 files changed

+145
-50
lines changed

6 files changed

+145
-50
lines changed

pkg/webhook/internal/certprovisioner/certprovisioner.go renamed to pkg/webhook/certprovisioner/certprovisioner.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,16 @@ limitations under the License.
1616

1717
package certprovisioner
1818

19+
// Certs hosts a private key, its corresponding serving certificate and
20+
// the CA certificate that signs the serving certificate.
21+
type Certs struct {
22+
Key []byte
23+
Cert []byte
24+
CACert []byte
25+
}
26+
1927
// CertProvisioner is an interface to provision the serving certificate.
2028
type CertProvisioner interface {
21-
// ProvisionServingCert returns the key, serving certificate and the CA certificate.
22-
ProvisionServingCert() (key []byte, cert []byte, caCert []byte, err error)
29+
// ProvisionServingCert returns a Certs struct.
30+
ProvisionServingCert() (*Certs, error)
2331
}

pkg/webhook/internal/certprovisioner/example_test.go renamed to pkg/webhook/certprovisioner/certprovisioner_test.go

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,9 @@ limitations under the License.
1616

1717
package certprovisioner
1818

19-
func ExampleSelfSignedCertProvisioner() {
20-
cp := SelfSignedCertProvisioner{
21-
Organization: "k8s.io",
22-
DNSNames: []string{"myDNSName"},
23-
ValidDays: 365,
24-
}
19+
import "fmt"
2520

26-
key, cert, caCert, err := cp.ProvisionServingCert()
27-
if err != nil {
28-
// handle error
29-
}
21+
func ExampleServiceToCommonName() {
22+
fmt.Println(ServiceToCommonName("myservicenamespace", "myservicename"))
23+
// Output: myservicename.myservicenamespace.svc
3024
}

pkg/webhook/internal/certprovisioner/doc.go renamed to pkg/webhook/certprovisioner/doc.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ Package certprovisioner provides an interface and implementation to provision ce
2020
Create a implementation instance of certprovisioner.
2121
2222
cp := SelfSignedCertProvisioner{
23-
// your configuration
23+
CommonName: "foo.bar.com"
2424
}
2525
2626
Provision the certificates.
27-
key, cert, caCert, err := cp.ProvisionServingCert()
27+
certs, err := cp.ProvisionServingCert()
2828
if err != nil {
2929
// handle error
3030
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
Copyright 2018 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package certprovisioner
18+
19+
import (
20+
"crypto/x509"
21+
"fmt"
22+
23+
"k8s.io/client-go/util/cert"
24+
)
25+
26+
// ServiceToCommonName generates the CommonName for the certificate when using a k8s service.
27+
func ServiceToCommonName(serviceNamespace, serviceName string) string {
28+
return fmt.Sprintf("%s.%s.svc", serviceName, serviceNamespace)
29+
}
30+
31+
// SelfSignedCertProvisioner implements the CertProvisioner interface.
32+
// It provisions self-signed certificates.
33+
type SelfSignedCertProvisioner struct {
34+
// Required Common Name
35+
CommonName string
36+
}
37+
38+
var _ CertProvisioner = &SelfSignedCertProvisioner{}
39+
40+
// ProvisionServingCert creates and returns a CA certificate, certificate and
41+
// key for the server. serverKey and serverCert are used by the server
42+
// to establish trust for clients, CA certificate is used by the
43+
// client to verify the server authentication chain.
44+
// The cert will be valid for 365 days.
45+
func (cp *SelfSignedCertProvisioner) ProvisionServingCert() (*Certs, error) {
46+
signingKey, err := cert.NewPrivateKey()
47+
if err != nil {
48+
return nil, fmt.Errorf("failed to create the CA private key: %v", err)
49+
}
50+
signingCert, err := cert.NewSelfSignedCACert(cert.Config{CommonName: "webhook-cert-ca"}, signingKey)
51+
if err != nil {
52+
return nil, fmt.Errorf("failed to create the CA cert: %v", err)
53+
}
54+
key, err := cert.NewPrivateKey()
55+
if err != nil {
56+
return nil, fmt.Errorf("failed to create the private key: %v", err)
57+
}
58+
signedCert, err := cert.NewSignedCert(
59+
cert.Config{
60+
CommonName: cp.CommonName,
61+
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
62+
},
63+
key, signingCert, signingKey,
64+
)
65+
if err != nil {
66+
return nil, fmt.Errorf("failed to create the cert: %v", err)
67+
}
68+
return &Certs{
69+
Key: cert.EncodePrivateKeyPEM(key),
70+
Cert: cert.EncodeCertPEM(signedCert),
71+
CACert: cert.EncodeCertPEM(signingCert),
72+
}, nil
73+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
Copyright 2018 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package certprovisioner
18+
19+
import (
20+
"crypto/x509"
21+
"encoding/pem"
22+
"testing"
23+
)
24+
25+
func TestProvisionServingCert(t *testing.T) {
26+
cn := "mysvc.myns.svc"
27+
cp := SelfSignedCertProvisioner{CommonName: cn}
28+
certs, err := cp.ProvisionServingCert()
29+
30+
// First, create the set of root certificates. For this example we only
31+
// have one. It's also possible to omit this in order to use the
32+
// default root set of the current operating system.
33+
roots := x509.NewCertPool()
34+
ok := roots.AppendCertsFromPEM(certs.CACert)
35+
if !ok {
36+
t.Fatalf("failed to parse root certificate: %s", certs.CACert)
37+
}
38+
39+
block, _ := pem.Decode(certs.Cert)
40+
if block == nil {
41+
t.Fatalf("failed to parse certificate PEM: %s", certs.Cert)
42+
}
43+
cert, err := x509.ParseCertificate(block.Bytes)
44+
if err != nil {
45+
t.Fatalf("failed to parse certificate: %v", err)
46+
}
47+
48+
opts := x509.VerifyOptions{
49+
DNSName: cn,
50+
Roots: roots,
51+
}
52+
53+
if _, err := cert.Verify(opts); err != nil {
54+
t.Fatalf("failed to verify certificate: %v", err)
55+
}
56+
}

pkg/webhook/internal/certprovisioner/selfsignedcertprovisioner.go

Lines changed: 0 additions & 36 deletions
This file was deleted.

0 commit comments

Comments
 (0)