mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			168 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			168 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
/*
 | 
						|
Copyright 2014 The Kubernetes Authors All rights reserved.
 | 
						|
 | 
						|
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 util
 | 
						|
 | 
						|
import (
 | 
						|
	"bytes"
 | 
						|
	"crypto/rand"
 | 
						|
	"crypto/rsa"
 | 
						|
	"crypto/x509"
 | 
						|
	"crypto/x509/pkix"
 | 
						|
	"encoding/pem"
 | 
						|
	"errors"
 | 
						|
	"fmt"
 | 
						|
	"io/ioutil"
 | 
						|
	"math/big"
 | 
						|
	"net"
 | 
						|
	"os"
 | 
						|
	"path/filepath"
 | 
						|
	"time"
 | 
						|
)
 | 
						|
 | 
						|
// GenerateSelfSignedCert creates a self-signed certificate and key for the given host.
 | 
						|
// Host may be an IP or a DNS name
 | 
						|
// You may also specify additional subject alt names (either ip or dns names) for the certificate
 | 
						|
// The certificate will be created with file mode 0644. The key will be created with file mode 0600.
 | 
						|
// If the certificate or key files already exist, they will be overwritten.
 | 
						|
// Any parent directories of the certPath or keyPath will be created as needed with file mode 0755.
 | 
						|
func GenerateSelfSignedCert(host, certPath, keyPath string, alternateIPs []net.IP, alternateDNS []string) error {
 | 
						|
	priv, err := rsa.GenerateKey(rand.Reader, 2048)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	template := x509.Certificate{
 | 
						|
		SerialNumber: big.NewInt(1),
 | 
						|
		Subject: pkix.Name{
 | 
						|
			CommonName: fmt.Sprintf("%s@%d", host, time.Now().Unix()),
 | 
						|
		},
 | 
						|
		NotBefore: time.Now(),
 | 
						|
		NotAfter:  time.Now().Add(time.Hour * 24 * 365),
 | 
						|
 | 
						|
		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
 | 
						|
		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
 | 
						|
		BasicConstraintsValid: true,
 | 
						|
		IsCA: true,
 | 
						|
	}
 | 
						|
 | 
						|
	if ip := net.ParseIP(host); ip != nil {
 | 
						|
		template.IPAddresses = append(template.IPAddresses, ip)
 | 
						|
	} else {
 | 
						|
		template.DNSNames = append(template.DNSNames, host)
 | 
						|
	}
 | 
						|
 | 
						|
	template.IPAddresses = append(template.IPAddresses, alternateIPs...)
 | 
						|
	template.DNSNames = append(template.DNSNames, alternateDNS...)
 | 
						|
 | 
						|
	derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	// Generate cert
 | 
						|
	certBuffer := bytes.Buffer{}
 | 
						|
	if err := pem.Encode(&certBuffer, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	// Generate key
 | 
						|
	keyBuffer := bytes.Buffer{}
 | 
						|
	if err := pem.Encode(&keyBuffer, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)}); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	// Write cert
 | 
						|
	if err := os.MkdirAll(filepath.Dir(certPath), os.FileMode(0755)); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	if err := ioutil.WriteFile(certPath, certBuffer.Bytes(), os.FileMode(0644)); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	// Write key
 | 
						|
	if err := os.MkdirAll(filepath.Dir(keyPath), os.FileMode(0755)); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	if err := ioutil.WriteFile(keyPath, keyBuffer.Bytes(), os.FileMode(0600)); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// CertPoolFromFile returns an x509.CertPool containing the certificates in the given PEM-encoded file.
 | 
						|
// Returns an error if the file could not be read, a certificate could not be parsed, or if the file does not contain any certificates
 | 
						|
func CertPoolFromFile(filename string) (*x509.CertPool, error) {
 | 
						|
	certs, err := certificatesFromFile(filename)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	pool := x509.NewCertPool()
 | 
						|
	for _, cert := range certs {
 | 
						|
		pool.AddCert(cert)
 | 
						|
	}
 | 
						|
	return pool, nil
 | 
						|
}
 | 
						|
 | 
						|
// certificatesFromFile returns the x509.Certificates contained in the given PEM-encoded file.
 | 
						|
// Returns an error if the file could not be read, a certificate could not be parsed, or if the file does not contain any certificates
 | 
						|
func certificatesFromFile(file string) ([]*x509.Certificate, error) {
 | 
						|
	if len(file) == 0 {
 | 
						|
		return nil, errors.New("error reading certificates from an empty filename")
 | 
						|
	}
 | 
						|
	pemBlock, err := ioutil.ReadFile(file)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	certs, err := CertsFromPEM(pemBlock)
 | 
						|
	if err != nil {
 | 
						|
		return nil, fmt.Errorf("error reading %s: %s", file, err)
 | 
						|
	}
 | 
						|
	return certs, nil
 | 
						|
}
 | 
						|
 | 
						|
// CertsFromPEM returns the x509.Certificates contained in the given PEM-encoded byte array
 | 
						|
// Returns an error if a certificate could not be parsed, or if the data does not contain any certificates
 | 
						|
func CertsFromPEM(pemCerts []byte) ([]*x509.Certificate, error) {
 | 
						|
	ok := false
 | 
						|
	certs := []*x509.Certificate{}
 | 
						|
	for len(pemCerts) > 0 {
 | 
						|
		var block *pem.Block
 | 
						|
		block, pemCerts = pem.Decode(pemCerts)
 | 
						|
		if block == nil {
 | 
						|
			break
 | 
						|
		}
 | 
						|
		// Only use PEM "CERTIFICATE" blocks without extra headers
 | 
						|
		if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
 | 
						|
		cert, err := x509.ParseCertificate(block.Bytes)
 | 
						|
		if err != nil {
 | 
						|
			return certs, err
 | 
						|
		}
 | 
						|
 | 
						|
		certs = append(certs, cert)
 | 
						|
		ok = true
 | 
						|
	}
 | 
						|
 | 
						|
	if !ok {
 | 
						|
		return certs, errors.New("could not read any certificates")
 | 
						|
	}
 | 
						|
	return certs, nil
 | 
						|
}
 |