forked from hswaw/hscloud
Serge Bazanski
9f0e1e88f1
This replaces the old clustercfg script with a brand spanking new mostly-equivalent Go reimplementation. But it's not exactly the same, here are the differences: 1. No cluster deployment logic anymore - we expect everyone to use ops/ machine at this point. 2. All certs/keys are Ed25519 and do not expire by default - but support for short-lived certificates is there, and is actually more generic and reusable. Currently it's only used for admincreds. 3. Speaking of admincreds: the new admincreds automatically figure out your username. 4. admincreds also doesn't shell out to kubectl anymore, and doesn't override your default context. The generated creds can live peacefully alongside your normal prodaccess creds. 5. gencerts (the new nodestrap without deployment support) now automatically generates certs for all nodes, based on local Nix modules in ops/. 6. No secretstore support. This will be changed once we rebuild secretstore in Go. For now users are expected to manually run secretstore sync on cluster/secrets. Change-Id: Ida935f44e04fd933df125905eee10121ac078495 Reviewed-on: https://gerrit.hackerspace.pl/c/hscloud/+/1498 Reviewed-by: q3k <q3k@hackerspace.pl>
98 lines
3.9 KiB
Go
98 lines
3.9 KiB
Go
package certs
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/x509"
|
|
"crypto/x509/pkix"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
var (
|
|
// From RFC 5280 Section 4.1.2.5
|
|
unknownNotAfter = time.Unix(253402300799, 0)
|
|
)
|
|
|
|
// compareCertData returns an error if any of the 'important' bits of the two
|
|
// certificates differ. Those are the bits that we template ourselves, and that
|
|
// are not issue-dependent (ie. not time or serial or kid or ...).
|
|
func compareCertData(template, cert *x509.Certificate) error {
|
|
if want, got := template.Subject.String(), cert.Subject.String(); want != got {
|
|
return fmt.Errorf("issued for different subject, wanted %s, got %s", want, got)
|
|
}
|
|
if want, got := strings.Join(template.DNSNames, ","), strings.Join(cert.DNSNames, ","); want != got {
|
|
return fmt.Errorf("issued for different DNS names, wanted %s, got %s", want, got)
|
|
}
|
|
if want, got := len(template.IPAddresses), len(cert.IPAddresses); want != got {
|
|
return fmt.Errorf("issued for different IP addresses, wanted %v, got %v", want, got)
|
|
} else {
|
|
for i := 0; i < len(template.IPAddresses); i++ {
|
|
if want, got := template.IPAddresses[i], cert.IPAddresses[i]; !bytes.Equal(want, got) {
|
|
return fmt.Errorf("issued for different IP addresses, wanted %v, got %v", want, got)
|
|
}
|
|
}
|
|
}
|
|
if want, got := template.KeyUsage, cert.KeyUsage; want != got {
|
|
return fmt.Errorf("issued for different key usage, wanted %d, got %d", want, got)
|
|
}
|
|
if want, got := len(template.ExtKeyUsage), len(cert.ExtKeyUsage); want != got {
|
|
return fmt.Errorf("issued for different ext key usage, wanted %v, got %v", want, got)
|
|
} else {
|
|
for i := 0; i < len(template.ExtKeyUsage); i++ {
|
|
if want, got := template.ExtKeyUsage[i], cert.ExtKeyUsage[i]; want != got {
|
|
return fmt.Errorf("issued for different ext key usage, wanted %v, got %v", want, got)
|
|
}
|
|
}
|
|
}
|
|
if want, got := template.IsCA, cert.IsCA; want != got {
|
|
return fmt.Errorf("issued for different IsCA, wanted %v, got %v", want, got)
|
|
}
|
|
if want, got := template.BasicConstraintsValid, cert.BasicConstraintsValid; want != got {
|
|
return fmt.Errorf("issued for different basic constraints valid, wanted %v, got %v", want, got)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// template builds an x509 'template' certificate, ie. makes an
|
|
// x509.Certificate with all the fields built up from the data contained in
|
|
// Certificate, but without any per-issue fields like times, serial number,
|
|
// etc.
|
|
func (c *Certificate) template() *x509.Certificate {
|
|
template := &x509.Certificate{
|
|
Subject: pkix.Name{
|
|
CommonName: c.cn,
|
|
},
|
|
DNSNames: c.san,
|
|
IPAddresses: c.ips,
|
|
}
|
|
if c.o != "" {
|
|
template.Subject.Organization = []string{c.o}
|
|
}
|
|
switch c.kind {
|
|
case kindServer:
|
|
template.KeyUsage = x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment
|
|
template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}
|
|
template.DNSNames = c.san
|
|
case kindClient:
|
|
template.KeyUsage = x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment
|
|
template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}
|
|
template.DNSNames = c.san
|
|
case kindClientServer:
|
|
template.KeyUsage = x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment
|
|
template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}
|
|
case kindCA:
|
|
template.IsCA = true
|
|
template.BasicConstraintsValid = true
|
|
template.KeyUsage = x509.KeyUsageCertSign | x509.KeyUsageCRLSign | x509.KeyUsageDigitalSignature
|
|
template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageOCSPSigning}
|
|
template.AuthorityKeyId = template.SubjectKeyId
|
|
case kindProdvider:
|
|
template.IsCA = true
|
|
template.BasicConstraintsValid = true
|
|
template.KeyUsage = x509.KeyUsageCertSign | x509.KeyUsageCRLSign | x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment
|
|
template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageOCSPSigning}
|
|
template.AuthorityKeyId = template.SubjectKeyId
|
|
}
|
|
return template
|
|
}
|