| package main |
| |
| import ( |
| "crypto/ed25519" |
| "crypto/rand" |
| "crypto/tls" |
| "crypto/x509" |
| "crypto/x509/pkix" |
| "encoding/pem" |
| "fmt" |
| "math/big" |
| "net" |
| "time" |
| |
| "github.com/golang/glog" |
| "google.golang.org/grpc" |
| "google.golang.org/grpc/credentials" |
| ) |
| |
| func serializeCert(der []byte) []byte { |
| return pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: der}) |
| } |
| |
| func serializeKey(priv ed25519.PrivateKey) []byte { |
| pkcs8, err := x509.MarshalPKCS8PrivateKey(priv) |
| if err != nil { |
| return nil |
| } |
| |
| block := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: pkcs8}) |
| return block |
| } |
| |
| func (p *prodvider) selfCreds() grpc.ServerOption { |
| glog.Infof("Bootstrapping certificate for self (%q)...", flagProdviderCN) |
| |
| // Create a cert |
| keyRaw, certRaw, err := p.makeSelfCertificate() |
| if err != nil { |
| glog.Exitf("Could not sign certificate for self: %v", err) |
| } |
| |
| serverCert, err := tls.X509KeyPair(serializeCert(certRaw), serializeKey(keyRaw)) |
| if err != nil { |
| glog.Exitf("Could not use gRPC certificate: %v", err) |
| } |
| |
| serverCert.Certificate = append(serverCert.Certificate, p.intermediateCACert.Raw) |
| |
| return grpc.Creds(credentials.NewTLS(&tls.Config{ |
| Certificates: []tls.Certificate{serverCert}, |
| })) |
| } |
| |
| func (p *prodvider) makeSelfCertificate() (ed25519.PrivateKey, []byte, error) { |
| serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 127) |
| serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) |
| if err != nil { |
| return nil, nil, err |
| } |
| template := &x509.Certificate{ |
| Subject: pkix.Name{ |
| CommonName: flagProdviderCN, |
| }, |
| NotBefore: time.Now(), |
| NotAfter: time.Now().Add(30 * 24 * time.Hour), |
| KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, |
| ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, |
| SerialNumber: serialNumber, |
| DNSNames: []string{flagProdviderCN}, |
| IPAddresses: []net.IP{ |
| {127, 0, 0, 1}, |
| }, |
| } |
| |
| pkey, skey, err := ed25519.GenerateKey(rand.Reader) |
| if err != nil { |
| return nil, nil, err |
| } |
| bytes, err := x509.CreateCertificate(rand.Reader, template, p.intermediateCACert, pkey, p.intermediateCAKey) |
| if err != nil { |
| return nil, nil, err |
| } |
| return skey, bytes, nil |
| } |
| |
| func (p *prodvider) makeKubernetesCertificate(username, o string, notAfter time.Time) (ed25519.PrivateKey, []byte, error) { |
| serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 127) |
| serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) |
| if err != nil { |
| return nil, nil, err |
| } |
| template := &x509.Certificate{ |
| Subject: pkix.Name{ |
| Organization: []string{o}, |
| OrganizationalUnit: []string{fmt.Sprintf("Prodvider Kubernetes Cert for %s/%s", username, o)}, |
| CommonName: username, |
| }, |
| NotBefore: time.Now(), |
| NotAfter: notAfter, |
| KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, |
| ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, |
| DNSNames: []string{ |
| username, |
| }, |
| SerialNumber: serialNumber, |
| } |
| |
| pkey, skey, err := ed25519.GenerateKey(rand.Reader) |
| if err != nil { |
| return nil, nil, err |
| } |
| bytes, err := x509.CreateCertificate(rand.Reader, template, p.intermediateCACert, pkey, p.intermediateCAKey) |
| if err != nil { |
| return nil, nil, err |
| } |
| return skey, bytes, nil |
| } |