Skip to content

Commit d92cf91

Browse files
committed
pkg/util/tlsutil: add tls primitives functions
1 parent 1f9f02d commit d92cf91

File tree

3 files changed

+232
-4
lines changed

3 files changed

+232
-4
lines changed

pkg/tlsutil/primatives.go

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
// Copyright 2018 The Operator-SDK Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package tlsutil
16+
17+
import (
18+
"crypto/rand"
19+
"crypto/rsa"
20+
"crypto/x509"
21+
"crypto/x509/pkix"
22+
"encoding/pem"
23+
"fmt"
24+
"math"
25+
"math/big"
26+
"time"
27+
28+
"k8s.io/api/core/v1"
29+
)
30+
31+
const (
32+
rsaKeySize = 2048
33+
duration365d = time.Hour * 24 * 365
34+
)
35+
36+
// NewPrivateKey returns randomly generated RSA private key.
37+
func NewPrivateKey() (*rsa.PrivateKey, error) {
38+
return rsa.GenerateKey(rand.Reader, rsaKeySize)
39+
}
40+
41+
// EncodePrivateKeyPEM encodes the given private key pem and returns bytes (base64).
42+
func EncodePrivateKeyPEM(key *rsa.PrivateKey) []byte {
43+
return pem.EncodeToMemory(&pem.Block{
44+
Type: "RSA PRIVATE KEY",
45+
Bytes: x509.MarshalPKCS1PrivateKey(key),
46+
})
47+
}
48+
49+
// EncodeCertificatePEM encodes the given certificate pem and returns bytes (base64).
50+
func EncodeCertificatePEM(cert *x509.Certificate) []byte {
51+
return pem.EncodeToMemory(&pem.Block{
52+
Type: "CERTIFICATE",
53+
Bytes: cert.Raw,
54+
})
55+
}
56+
57+
// NewSelfSignedCACertificate returns a self-signed CA certificate based on given configuration and private key.
58+
// The certificate has one-year lease.
59+
func NewSelfSignedCACertificate(key *rsa.PrivateKey) (*x509.Certificate, error) {
60+
serial, err := rand.Int(rand.Reader, new(big.Int).SetInt64(math.MaxInt64))
61+
if err != nil {
62+
return nil, err
63+
}
64+
now := time.Now()
65+
tmpl := x509.Certificate{
66+
SerialNumber: serial,
67+
NotBefore: now.UTC(),
68+
NotAfter: now.Add(duration365d).UTC(),
69+
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
70+
BasicConstraintsValid: true,
71+
IsCA: true,
72+
}
73+
certDERBytes, err := x509.CreateCertificate(rand.Reader, &tmpl, &tmpl, key.Public(), key)
74+
if err != nil {
75+
return nil, err
76+
}
77+
return x509.ParseCertificate(certDERBytes)
78+
}
79+
80+
// NewSignedCertificate signs a certificate using the given private key, CA and returns a signed certificate.
81+
// The certificate could be used for both client and server auth.
82+
// The certificate has one-year lease.
83+
func NewSignedCertificate(cfg *CertConfig, service *v1.Service, key *rsa.PrivateKey, caCert *x509.Certificate, caKey *rsa.PrivateKey) (*x509.Certificate, error) {
84+
serial, err := rand.Int(rand.Reader, new(big.Int).SetInt64(math.MaxInt64))
85+
if err != nil {
86+
return nil, err
87+
}
88+
eku := []x509.ExtKeyUsage{}
89+
switch cfg.CertType {
90+
case ClientCert:
91+
eku = append(eku, x509.ExtKeyUsageClientAuth)
92+
case ServingCert:
93+
eku = append(eku, x509.ExtKeyUsageServerAuth)
94+
case ClientAndServingCert:
95+
eku = append(eku, x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth)
96+
}
97+
certTmpl := x509.Certificate{
98+
Subject: pkix.Name{
99+
CommonName: cfg.CommonName,
100+
Organization: cfg.Organization,
101+
},
102+
DNSNames: []string{fmt.Sprintf("%s.%s.svc.cluster.local", service.Name, service.Namespace)},
103+
SerialNumber: serial,
104+
NotBefore: caCert.NotBefore,
105+
NotAfter: time.Now().Add(duration365d).UTC(),
106+
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
107+
ExtKeyUsage: eku,
108+
}
109+
certDERBytes, err := x509.CreateCertificate(rand.Reader, &certTmpl, caCert, key.Public(), caKey)
110+
if err != nil {
111+
return nil, err
112+
}
113+
return x509.ParseCertificate(certDERBytes)
114+
}

pkg/tlsutil/tls.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@ import (
2323
type CertType int
2424

2525
const (
26-
// ClientCert defines a client cert.
27-
ClientCert CertType = iota
26+
// ClientAndServingCert defines both client and serving cert.
27+
ClientAndServingCert CertType = iota
2828
// ServingCert defines a serving cert.
2929
ServingCert
30-
// ClientAndServingCert defines both client and serving cert.
31-
ClientAndServingCert
30+
// ClientCert defines a client cert.
31+
ClientCert
3232
)
3333

3434
// CertConfig configures how to generate the Cert.

pkg/util/tlsutil/primative.go

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
// Copyright 2018 The Operator-SDK Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package tlsutil
16+
17+
import (
18+
"crypto/rand"
19+
"crypto/rsa"
20+
"crypto/x509"
21+
"crypto/x509/pkix"
22+
"encoding/pem"
23+
"fmt"
24+
"math"
25+
"math/big"
26+
"time"
27+
28+
"k8s.io/api/core/v1"
29+
)
30+
31+
const (
32+
rsaKeySize = 2048
33+
duration365d = time.Hour * 24 * 365
34+
)
35+
36+
// NewPrivateKey returns randomly generated RSA private key.
37+
func NewPrivateKey() (*rsa.PrivateKey, error) {
38+
return rsa.GenerateKey(rand.Reader, rsaKeySize)
39+
}
40+
41+
// EncodePrivateKeyPEM encodes the given private key pem and returns bytes (base64).
42+
func EncodePrivateKeyPEM(key *rsa.PrivateKey) []byte {
43+
return pem.EncodeToMemory(&pem.Block{
44+
Type: "RSA PRIVATE KEY",
45+
Bytes: x509.MarshalPKCS1PrivateKey(key),
46+
})
47+
}
48+
49+
// EncodeCertificatePEM encodes the given certificate pem and returns bytes (base64).
50+
func EncodeCertificatePEM(cert *x509.Certificate) []byte {
51+
return pem.EncodeToMemory(&pem.Block{
52+
Type: "CERTIFICATE",
53+
Bytes: cert.Raw,
54+
})
55+
}
56+
57+
// NewSelfSignedCACertificate returns a self-signed CA certificate based on given configuration and private key.
58+
// The certificate has one-year lease.
59+
func NewSelfSignedCACertificate(key *rsa.PrivateKey) (*x509.Certificate, error) {
60+
serial, err := rand.Int(rand.Reader, new(big.Int).SetInt64(math.MaxInt64))
61+
if err != nil {
62+
return nil, err
63+
}
64+
65+
now := time.Now()
66+
tmpl := x509.Certificate{
67+
SerialNumber: serial,
68+
NotBefore: now.UTC(),
69+
NotAfter: now.Add(duration365d).UTC(),
70+
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
71+
BasicConstraintsValid: true,
72+
IsCA: true,
73+
}
74+
75+
certDERBytes, err := x509.CreateCertificate(rand.Reader, &tmpl, &tmpl, key.Public(), key)
76+
if err != nil {
77+
return nil, err
78+
}
79+
80+
return x509.ParseCertificate(certDERBytes)
81+
}
82+
83+
// NewSignedCertificate signs a certificate using the given private key, CA and returns a signed certificate.
84+
// The certificate could be used for both client and server auth.
85+
// The certificate has one-year lease.
86+
func NewSignedCertificate(cfg *CertConfig, service *v1.Service, key *rsa.PrivateKey, caCert *x509.Certificate, caKey *rsa.PrivateKey) (*x509.Certificate, error) {
87+
if caCert == nil || caKey == nil {
88+
panic("caCert or caKey is nil")
89+
}
90+
91+
serial, err := rand.Int(rand.Reader, new(big.Int).SetInt64(math.MaxInt64))
92+
if err != nil {
93+
return nil, err
94+
}
95+
96+
certTmpl := x509.Certificate{
97+
Subject: pkix.Name{
98+
CommonName: cfg.CommonName,
99+
Organization: cfg.Organization,
100+
},
101+
DNSNames: []string{fmt.Sprintf("%s.%s.svc.cluster.local", service.Name, service.Namespace)},
102+
SerialNumber: serial,
103+
NotBefore: caCert.NotBefore,
104+
NotAfter: time.Now().Add(duration365d).UTC(),
105+
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
106+
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
107+
}
108+
certDERBytes, err := x509.CreateCertificate(rand.Reader, &certTmpl, caCert, key.Public(), caKey)
109+
if err != nil {
110+
return nil, err
111+
}
112+
113+
return x509.ParseCertificate(certDERBytes)
114+
}

0 commit comments

Comments
 (0)