Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support subject alternative URIs when generating cryptographic certificates. #341

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 41 additions & 7 deletions crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"io"
"math/big"
"net"
"net/url"
"time"

"strings"
Expand Down Expand Up @@ -341,7 +342,7 @@ func generateCertificateAuthorityWithKeyInternal(
) (certificate, error) {
ca := certificate{}

template, err := getBaseCertTemplate(cn, nil, nil, daysValid)
template, err := getBaseCertTemplate(cn, nil, nil, nil, daysValid)
if err != nil {
return ca, err
}
Expand All @@ -360,39 +361,42 @@ func generateSelfSignedCertificate(
cn string,
ips []interface{},
alternateDNS []interface{},
alternateURIs []interface{},
daysValid int,
) (certificate, error) {
priv, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return certificate{}, fmt.Errorf("error generating rsa key: %s", err)
}
return generateSelfSignedCertificateWithKeyInternal(cn, ips, alternateDNS, daysValid, priv)
return generateSelfSignedCertificateWithKeyInternal(cn, ips, alternateDNS, alternateURIs, daysValid, priv)
}

func generateSelfSignedCertificateWithPEMKey(
cn string,
ips []interface{},
alternateDNS []interface{},
alternateURIs []interface{},
daysValid int,
privPEM string,
) (certificate, error) {
priv, err := parsePrivateKeyPEM(privPEM)
if err != nil {
return certificate{}, fmt.Errorf("parsing private key: %s", err)
}
return generateSelfSignedCertificateWithKeyInternal(cn, ips, alternateDNS, daysValid, priv)
return generateSelfSignedCertificateWithKeyInternal(cn, ips, alternateDNS, alternateURIs, daysValid, priv)
}

func generateSelfSignedCertificateWithKeyInternal(
cn string,
ips []interface{},
alternateDNS []interface{},
alternateURIs []interface{},
daysValid int,
priv crypto.PrivateKey,
) (certificate, error) {
cert := certificate{}

template, err := getBaseCertTemplate(cn, ips, alternateDNS, daysValid)
template, err := getBaseCertTemplate(cn, ips, alternateDNS, alternateURIs, daysValid)
if err != nil {
return cert, err
}
Expand All @@ -406,20 +410,22 @@ func generateSignedCertificate(
cn string,
ips []interface{},
alternateDNS []interface{},
alternateURIs []interface{},
daysValid int,
ca certificate,
) (certificate, error) {
priv, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return certificate{}, fmt.Errorf("error generating rsa key: %s", err)
}
return generateSignedCertificateWithKeyInternal(cn, ips, alternateDNS, daysValid, ca, priv)
return generateSignedCertificateWithKeyInternal(cn, ips, alternateDNS, alternateURIs, daysValid, ca, priv)
}

func generateSignedCertificateWithPEMKey(
cn string,
ips []interface{},
alternateDNS []interface{},
alternateURIs []interface{},
daysValid int,
ca certificate,
privPEM string,
Expand All @@ -428,13 +434,14 @@ func generateSignedCertificateWithPEMKey(
if err != nil {
return certificate{}, fmt.Errorf("parsing private key: %s", err)
}
return generateSignedCertificateWithKeyInternal(cn, ips, alternateDNS, daysValid, ca, priv)
return generateSignedCertificateWithKeyInternal(cn, ips, alternateDNS, alternateURIs, daysValid, ca, priv)
}

func generateSignedCertificateWithKeyInternal(
cn string,
ips []interface{},
alternateDNS []interface{},
alternateURIs []interface{},
daysValid int,
ca certificate,
priv crypto.PrivateKey,
Expand All @@ -460,7 +467,7 @@ func generateSignedCertificateWithKeyInternal(
)
}

template, err := getBaseCertTemplate(cn, ips, alternateDNS, daysValid)
template, err := getBaseCertTemplate(cn, ips, alternateDNS, alternateURIs, daysValid)
if err != nil {
return cert, err
}
Expand Down Expand Up @@ -519,6 +526,7 @@ func getBaseCertTemplate(
cn string,
ips []interface{},
alternateDNS []interface{},
alternateURIs []interface{},
daysValid int,
) (*x509.Certificate, error) {
ipAddresses, err := getNetIPs(ips)
Expand All @@ -529,6 +537,10 @@ func getBaseCertTemplate(
if err != nil {
return nil, err
}
uris, err := getURIs(alternateURIs)
if err != nil {
return nil, err
}
serialNumberUpperBound := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, err := rand.Int(rand.Reader, serialNumberUpperBound)
if err != nil {
Expand All @@ -541,6 +553,7 @@ func getBaseCertTemplate(
},
IPAddresses: ipAddresses,
DNSNames: dnsNames,
URIs: uris,
NotBefore: time.Now(),
NotAfter: time.Now().Add(time.Hour * 24 * time.Duration(daysValid)),
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
Expand Down Expand Up @@ -594,6 +607,27 @@ func getAlternateDNSStrs(alternateDNS []interface{}) ([]string, error) {
return alternateDNSStrs, nil
}

func getURIs(uris []interface{}) ([]*url.URL, error) {
if uris == nil {
return []*url.URL{}, nil
}
var uriStr string
var ok bool
urlURIs := make([]*url.URL, len(uris))
for i, uri := range uris {
uriStr, ok = uri.(string)
if !ok {
return nil, fmt.Errorf("error parsing uri: %v is not a string", uri)
}
u, err := url.Parse(uriStr)
if err != nil {
return nil, err
}
urlURIs[i] = u
}
return urlURIs, nil
}

func encryptAES(password string, plaintext string) (string, error) {
if plaintext == "" {
return "", nil
Expand Down
16 changes: 14 additions & 2 deletions crypto_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,8 @@ func testGenSelfSignedCert(t *testing.T, keyAlgo *string) {
ip2 = "10.0.0.2"
dns1 = "bar.com"
dns2 = "bat.com"
uri1 = "https://www.example.com"
uri2 = "spiffe://example.com/workload"
)

var genSelfSignedCertExpr string
Expand All @@ -313,14 +315,16 @@ func testGenSelfSignedCert(t *testing.T, keyAlgo *string) {
}

tpl := fmt.Sprintf(
`{{- $cert := %s "%s" (list "%s" "%s") (list "%s" "%s") 365 }}
`{{- $cert := %s "%s" (list "%s" "%s") (list "%s" "%s") (list "%s" "%s") 365 }}
{{ $cert.Cert }}`,
genSelfSignedCertExpr,
cn,
ip1,
ip2,
dns1,
dns2,
uri1,
uri2,
)

out, err := runRaw(tpl, nil)
Expand All @@ -342,6 +346,8 @@ func testGenSelfSignedCert(t *testing.T, keyAlgo *string) {
assert.Equal(t, ip2, cert.IPAddresses[1].String())
assert.Contains(t, cert.DNSNames, dns1)
assert.Contains(t, cert.DNSNames, dns2)
assert.Equal(t, uri1, cert.URIs[0].String())
assert.Equal(t, uri2, cert.URIs[1].String())
assert.False(t, cert.IsCA)
}

Expand All @@ -366,6 +372,8 @@ func testGenSignedCert(t *testing.T, caKeyAlgo, certKeyAlgo *string) {
ip2 = "10.0.0.2"
dns1 = "bar.com"
dns2 = "bat.com"
uri1 = "https://www.example.com"
uri2 = "spiffe://example.com/workload"
)

var genCAExpr, genSignedCertExpr string
Expand All @@ -382,7 +390,7 @@ func testGenSignedCert(t *testing.T, caKeyAlgo, certKeyAlgo *string) {

tpl := fmt.Sprintf(
`{{- $ca := %s "foo" 365 }}
{{- $cert := %s "%s" (list "%s" "%s") (list "%s" "%s") 365 $ca }}
{{- $cert := %s "%s" (list "%s" "%s") (list "%s" "%s") (list "%s" "%s") 365 $ca }}
{{ $cert.Cert }}
`,
genCAExpr,
Expand All @@ -392,6 +400,8 @@ func testGenSignedCert(t *testing.T, caKeyAlgo, certKeyAlgo *string) {
ip2,
dns1,
dns2,
uri1,
uri2,
)
out, err := runRaw(tpl, nil)
if err != nil {
Expand All @@ -413,6 +423,8 @@ func testGenSignedCert(t *testing.T, caKeyAlgo, certKeyAlgo *string) {
assert.Equal(t, ip2, cert.IPAddresses[1].String())
assert.Contains(t, cert.DNSNames, dns1)
assert.Contains(t, cert.DNSNames, dns2)
assert.Equal(t, uri1, cert.URIs[0].String())
assert.Equal(t, uri2, cert.URIs[1].String())
assert.False(t, cert.IsCA)
}

Expand Down