...

Source file src/github.com/prometheus/common/config/generate.go

Documentation: github.com/prometheus/common/config

     1  // Copyright 2020 The Prometheus-operator Authors
     2  // Copyright 2022 The Prometheus 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  //go:build ignore
    17  // +build ignore
    18  
    19  // Program generating TLS certificates and keys for the tests.
    20  package main
    21  
    22  import (
    23  	"bytes"
    24  	"crypto/rand"
    25  	"crypto/rsa"
    26  	"crypto/x509"
    27  	"crypto/x509/pkix"
    28  	"encoding/pem"
    29  	"fmt"
    30  	"io"
    31  	"log"
    32  	"math/big"
    33  	"net"
    34  	"os"
    35  	"time"
    36  )
    37  
    38  const (
    39  	validityPeriod = 50 * 365 * 24 * time.Hour
    40  )
    41  
    42  func EncodeCertificate(w io.Writer, cert *x509.Certificate) error {
    43  	return pem.Encode(w, &pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw})
    44  }
    45  
    46  func EncodeKey(w io.Writer, priv *rsa.PrivateKey) error {
    47  	b, err := x509.MarshalPKCS8PrivateKey(priv)
    48  	if err != nil {
    49  		return fmt.Errorf("failed to marshal private key: %v", err)
    50  	}
    51  
    52  	return pem.Encode(w, &pem.Block{Type: "PRIVATE KEY", Bytes: b})
    53  }
    54  
    55  var serialNumber *big.Int
    56  
    57  func init() {
    58  	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
    59  
    60  	var err error
    61  	serialNumber, err = rand.Int(rand.Reader, serialNumberLimit)
    62  	if err != nil {
    63  		panic(fmt.Errorf("failed to generate  serial number: %v", err))
    64  	}
    65  }
    66  
    67  func SerialNumber() *big.Int {
    68  	var serial big.Int
    69  
    70  	serial.Set(serialNumber)
    71  	serialNumber.Add(&serial, big.NewInt(1))
    72  
    73  	return &serial
    74  }
    75  
    76  func GenerateCertificateAuthority(commonName string, parentCert *x509.Certificate, parentKey *rsa.PrivateKey) (*x509.Certificate, *rsa.PrivateKey, error) {
    77  	now := time.Now()
    78  
    79  	caKey, err := rsa.GenerateKey(rand.Reader, 4096)
    80  	if err != nil {
    81  		return nil, nil, fmt.Errorf("failed to generate CA private key: %v", err)
    82  	}
    83  
    84  	caCert := &x509.Certificate{
    85  		SerialNumber: SerialNumber(),
    86  		Subject: pkix.Name{
    87  			Country:            []string{"US"},
    88  			Organization:       []string{"Prometheus"},
    89  			OrganizationalUnit: []string{"Prometheus Certificate Authority"},
    90  			CommonName:         commonName,
    91  		},
    92  		NotBefore:             now,
    93  		NotAfter:              now.Add(validityPeriod),
    94  		KeyUsage:              x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment | x509.KeyUsageCertSign,
    95  		IsCA:                  true,
    96  		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageAny},
    97  		BasicConstraintsValid: true,
    98  	}
    99  
   100  	if parentCert == nil && parentKey == nil {
   101  		parentCert = caCert
   102  		parentKey = caKey
   103  	}
   104  
   105  	b, err := x509.CreateCertificate(rand.Reader, caCert, parentCert, &caKey.PublicKey, parentKey)
   106  	if err != nil {
   107  		return nil, nil, fmt.Errorf("failed to create CA certificate: %v", err)
   108  	}
   109  
   110  	caCert, err = x509.ParseCertificate(b)
   111  	if err != nil {
   112  		return nil, nil, fmt.Errorf("failed to decode CA certificate: %v", err)
   113  	}
   114  
   115  	return caCert, caKey, nil
   116  }
   117  
   118  func GenerateCertificate(caCert *x509.Certificate, caKey *rsa.PrivateKey, server bool, name string, ipAddresses ...net.IP) (*x509.Certificate, *rsa.PrivateKey, error) {
   119  	now := time.Now()
   120  
   121  	key, err := rsa.GenerateKey(rand.Reader, 4096)
   122  	if err != nil {
   123  		return nil, nil, fmt.Errorf("failed to generate private key: %v", err)
   124  	}
   125  
   126  	cert := &x509.Certificate{
   127  		SerialNumber: SerialNumber(),
   128  		Subject: pkix.Name{
   129  			Country:      []string{"US"},
   130  			Organization: []string{"Prometheus"},
   131  			CommonName:   name,
   132  		},
   133  		NotBefore:             now,
   134  		NotAfter:              now.Add(validityPeriod),
   135  		KeyUsage:              x509.KeyUsageKeyEncipherment,
   136  		BasicConstraintsValid: true,
   137  	}
   138  
   139  	if server {
   140  		cert.DNSNames = []string{name}
   141  		cert.IPAddresses = ipAddresses
   142  		cert.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}
   143  	} else {
   144  		cert.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}
   145  	}
   146  
   147  	if caCert == nil && caKey == nil {
   148  		caCert = cert
   149  		caKey = key
   150  	}
   151  
   152  	b, err := x509.CreateCertificate(rand.Reader, cert, caCert, &key.PublicKey, caKey)
   153  	if err != nil {
   154  		return nil, nil, fmt.Errorf("failed to create certificate: %v", err)
   155  	}
   156  
   157  	cert, err = x509.ParseCertificate(b)
   158  	if err != nil {
   159  		return nil, nil, fmt.Errorf("failed to decode certificate: %v", err)
   160  	}
   161  
   162  	return cert, key, nil
   163  }
   164  
   165  func writeCertificateAndKey(path string, cert *x509.Certificate, key *rsa.PrivateKey) error {
   166  	var b bytes.Buffer
   167  
   168  	if err := EncodeCertificate(&b, cert); err != nil {
   169  		return err
   170  	}
   171  
   172  	if err := os.WriteFile(fmt.Sprintf("%s.crt", path), b.Bytes(), 0o644); err != nil {
   173  		return err
   174  	}
   175  
   176  	b.Reset()
   177  	if err := EncodeKey(&b, key); err != nil {
   178  		return err
   179  	}
   180  
   181  	if err := os.WriteFile(fmt.Sprintf("%s.key", path), b.Bytes(), 0o644); err != nil {
   182  		return err
   183  	}
   184  
   185  	return nil
   186  }
   187  
   188  func main() {
   189  	log.Println("Generating root CA")
   190  	rootCert, rootKey, err := GenerateCertificateAuthority("Prometheus Root CA", nil, nil)
   191  	if err != nil {
   192  		log.Fatal(err)
   193  	}
   194  
   195  	log.Println("Generating CA")
   196  	caCert, caKey, err := GenerateCertificateAuthority("Prometheus TLS CA", rootCert, rootKey)
   197  	if err != nil {
   198  		log.Fatal(err)
   199  	}
   200  
   201  	log.Println("Generating server certificate")
   202  	cert, key, err := GenerateCertificate(caCert, caKey, true, "localhost", net.IPv4(127, 0, 0, 1), net.IPv4(127, 0, 0, 0))
   203  	if err != nil {
   204  		log.Fatal(err)
   205  	}
   206  
   207  	if err := writeCertificateAndKey("testdata/server", cert, key); err != nil {
   208  		log.Fatal(err)
   209  	}
   210  
   211  	log.Println("Generating client certificate")
   212  	cert, key, err = GenerateCertificate(caCert, caKey, false, "localhost")
   213  	if err != nil {
   214  		log.Fatal(err)
   215  	}
   216  
   217  	if err := writeCertificateAndKey("testdata/client", cert, key); err != nil {
   218  		log.Fatal(err)
   219  	}
   220  
   221  	log.Println("Generating self-signed client certificate")
   222  	cert, key, err = GenerateCertificate(nil, nil, false, "localhost")
   223  	if err != nil {
   224  		log.Fatal(err)
   225  	}
   226  
   227  	if err := writeCertificateAndKey("testdata/self-signed-client", cert, key); err != nil {
   228  		log.Fatal(err)
   229  	}
   230  
   231  	log.Println("Generating CA bundle")
   232  	var b bytes.Buffer
   233  	if err := EncodeCertificate(&b, caCert); err != nil {
   234  		log.Fatal(err)
   235  	}
   236  
   237  	if err := EncodeCertificate(&b, rootCert); err != nil {
   238  		log.Fatal(err)
   239  	}
   240  
   241  	if err := os.WriteFile("testdata/tls-ca-chain.pem", b.Bytes(), 0o644); err != nil {
   242  		log.Fatal(err)
   243  	}
   244  }
   245  

View as plain text