Files
identity/identity_test.go
zeekay aff3f1f869 rebrand: openziti → hanzozt (Hanzo Zero Trust)
Global rebrand of all OpenZiti references to Hanzo ZT:
- Go module paths: github.com/openziti/* → github.com/hanzozt/*
- Docker images: openziti/* → hanzozt/*
- Java packages: org.openziti.* → org.hanzozt.*
- Brand: OpenZiti → Hanzo ZT
- URLs: openziti.io → hanzozt.dev
2026-02-18 16:13:42 -08:00

733 lines
22 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
Copyright NetFoundry Inc.
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
https://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 identity
import (
"bytes"
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/sha1"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"fmt"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"math/big"
"net"
"os"
"testing"
"time"
)
func Test_LoadIdentityWithPEM(t *testing.T) {
// setup
key, certTemplate := mkServerAndClientCert("Identity With PEM", []string{"test.netfoundry.io"})
keyDer, _ := x509.MarshalECPrivateKey(key.(*ecdsa.PrivateKey))
keyPem := &pem.Block{
Type: "EC PRIVATE KEY",
Bytes: keyDer,
}
certDer, err := x509.CreateCertificate(rand.Reader, certTemplate, certTemplate, key.Public(), key)
assert.NoError(t, err)
cert, err := x509.ParseCertificate(certDer)
assert.NoError(t, err)
certPem := &pem.Block{
Type: "CERTIFICATE",
Bytes: certDer,
}
cfg := Config{
Key: "pem:" + string(pem.EncodeToMemory(keyPem)),
Cert: "pem:" + string(pem.EncodeToMemory(certPem)),
}
id, err := LoadIdentity(cfg)
assert.NoError(t, err)
assert.NotNil(t, id.Cert())
assert.NotNil(t, id.Cert().Leaf)
assert.True(t, cert.Equal(id.Cert().Leaf))
}
func Test_LoadIdentityWithPEMChain(t *testing.T) {
// setup
caKey, caCertTemplate := mkCaCert("Parent CA 1")
caDer, err := x509.CreateCertificate(rand.Reader, caCertTemplate, caCertTemplate, caKey.Public(), caKey)
assert.NoError(t, err)
caCert, err := x509.ParseCertificate(caDer)
assert.NoError(t, err)
key, certTemplate := mkServerAndClientCert("Test Child", []string{"client.netfoundry.io"})
certDer, err := x509.CreateCertificate(rand.Reader, certTemplate, caCertTemplate, key.Public(), caKey)
assert.NoError(t, err)
cert, err := x509.ParseCertificate(certDer)
assert.NoError(t, err)
keyDer, _ := x509.MarshalECPrivateKey(key.(*ecdsa.PrivateKey))
keyPem := &pem.Block{
Type: "EC PRIVATE KEY",
Bytes: keyDer,
}
caPem := &pem.Block{
Type: "CERTIFICATE",
Bytes: caDer,
}
certPem := &pem.Block{
Type: "CERTIFICATE",
Bytes: certDer,
}
cfg := Config{
Key: "pem:" + string(pem.EncodeToMemory(keyPem)),
Cert: "pem:" + string(pem.EncodeToMemory(certPem)) + string(pem.EncodeToMemory(caPem)),
}
id, err := LoadIdentity(cfg)
assert.NoError(t, err)
assert.NotNil(t, id.Cert())
assert.Equal(t, 2, len(id.Cert().Certificate))
assert.NotNil(t, id.Cert().Leaf)
assert.True(t, id.Cert().Leaf.Equal(cert))
// verify CA cert is after leaf
assert.NoError(t, err)
assert.True(t, bytes.Equal(caCert.Raw, id.Cert().Certificate[1]))
}
func Test_CheckServerCertSansForConflicts(t *testing.T) {
t.Run("no conflicts found", func(t *testing.T) {
caKey, caCertTemplate := mkCaCert("Parent CA")
parentDer, err := x509.CreateCertificate(rand.Reader, caCertTemplate, caCertTemplate, caKey.Public(), caKey)
assert.NoError(t, err)
childKey1, childCert1 := mkClientCert("Test Child 1")
childCert1Der, err := x509.CreateCertificate(rand.Reader, childCert1, caCertTemplate, childKey1.Public(), caKey)
assert.NoError(t, err)
childKey2, childCert2 := mkServerCert("Test Child 2", []string{"client2.netfoundry.io"}, []net.IP{net.ParseIP("127.0.0.1")})
childCert2Der, err := x509.CreateCertificate(rand.Reader, childCert2, caCertTemplate, childKey2.Public(), caKey)
assert.NoError(t, err)
childKey3, childCert3 := mkServerCert("Test Child 3", []string{"client3.netfoundry.io"}, []net.IP{net.ParseIP("10.8.0.1")})
childCert3Der, err := x509.CreateCertificate(rand.Reader, childCert3, caCertTemplate, childKey3.Public(), caKey)
assert.NoError(t, err)
childKey4, childCert4 := mkServerCert("Test Child 4", []string{"client4.netfoundry.io"}, []net.IP{net.ParseIP("192.168.0.1")})
childCert4Der, err := x509.CreateCertificate(rand.Reader, childCert4, caCertTemplate, childKey4.Public(), caKey)
assert.NoError(t, err)
childKey1Der, _ := x509.MarshalECPrivateKey(childKey1.(*ecdsa.PrivateKey))
childKey1Pem := &pem.Block{
Type: "EC PRIVATE KEY",
Bytes: childKey1Der,
}
childKey2Der, _ := x509.MarshalECPrivateKey(childKey2.(*ecdsa.PrivateKey))
childKey2Pem := &pem.Block{
Type: "EC PRIVATE KEY",
Bytes: childKey2Der,
}
childKey3Der, _ := x509.MarshalECPrivateKey(childKey3.(*ecdsa.PrivateKey))
childKey3Pem := &pem.Block{
Type: "EC PRIVATE KEY",
Bytes: childKey3Der,
}
childKey4Der, _ := x509.MarshalECPrivateKey(childKey4.(*ecdsa.PrivateKey))
childKey4Pem := &pem.Block{
Type: "EC PRIVATE KEY",
Bytes: childKey4Der,
}
parentPem := &pem.Block{
Type: "CERTIFICATE",
Bytes: parentDer,
}
childCert1Pem := &pem.Block{
Type: "CERTIFICATE",
Bytes: childCert1Der,
}
childCert2Pem := &pem.Block{
Type: "CERTIFICATE",
Bytes: childCert2Der,
}
childCert3Pem := &pem.Block{
Type: "CERTIFICATE",
Bytes: childCert3Der,
}
childCert4Pem := &pem.Block{
Type: "CERTIFICATE",
Bytes: childCert4Der,
}
cfg := Config{
Key: "pem:" + string(pem.EncodeToMemory(childKey1Pem)),
Cert: "pem:" + string(pem.EncodeToMemory(childCert1Pem)) + string(pem.EncodeToMemory(parentPem)),
ServerKey: "pem:" + string(pem.EncodeToMemory(childKey2Pem)),
ServerCert: "pem:" + string(pem.EncodeToMemory(childCert2Pem)) + string(pem.EncodeToMemory(parentPem)),
AltServerCerts: []ServerPair{
{
ServerKey: "pem:" + string(pem.EncodeToMemory(childKey3Pem)),
ServerCert: "pem:" + string(pem.EncodeToMemory(childCert3Pem)) + string(pem.EncodeToMemory(parentPem)),
},
{
ServerKey: "pem:" + string(pem.EncodeToMemory(childKey4Pem)),
ServerCert: "pem:" + string(pem.EncodeToMemory(childCert4Pem)) + string(pem.EncodeToMemory(parentPem)),
},
},
}
id, err := LoadIdentity(cfg)
t.Run("loads without error", func(t *testing.T) {
assert.NoError(t, err)
})
t.Run("check for sans conflicts returns no conflict", func(t *testing.T) {
req := require.New(t)
conflicts := id.CheckServerCertSansForConflicts()
req.Empty(conflicts)
})
})
t.Run("conflicts found", func(t *testing.T) {
caKey, caCertTemplate := mkCaCert("Parent CA")
parentDer, err := x509.CreateCertificate(rand.Reader, caCertTemplate, caCertTemplate, caKey.Public(), caKey)
assert.NoError(t, err)
childKey1, childCert1 := mkClientCert("Test Child 1")
childCert1Der, err := x509.CreateCertificate(rand.Reader, childCert1, caCertTemplate, childKey1.Public(), caKey)
assert.NoError(t, err)
childKey2, childCert2 := mkServerCert("Test Child 2", []string{"client2.netfoundry.io"}, []net.IP{net.ParseIP("127.0.0.1")})
childCert2Der, err := x509.CreateCertificate(rand.Reader, childCert2, caCertTemplate, childKey2.Public(), caKey)
assert.NoError(t, err)
//dupes ip from childCert2
childKey3, childCert3 := mkServerCert("Test Child 3", []string{"client3.netfoundry.io"}, []net.IP{net.ParseIP("127.0.0.1")})
childCert3Der, err := x509.CreateCertificate(rand.Reader, childCert3, caCertTemplate, childKey3.Public(), caKey)
assert.NoError(t, err)
//dupes dns from childCert3
childKey4, childCert4 := mkServerCert("Test Child 4", []string{"client3.netfoundry.io"}, []net.IP{net.ParseIP("192.168.0.1")})
childCert4Der, err := x509.CreateCertificate(rand.Reader, childCert4, caCertTemplate, childKey4.Public(), caKey)
assert.NoError(t, err)
childKey1Der, _ := x509.MarshalECPrivateKey(childKey1.(*ecdsa.PrivateKey))
childKey1Pem := &pem.Block{
Type: "EC PRIVATE KEY",
Bytes: childKey1Der,
}
childKey2Der, _ := x509.MarshalECPrivateKey(childKey2.(*ecdsa.PrivateKey))
childKey2Pem := &pem.Block{
Type: "EC PRIVATE KEY",
Bytes: childKey2Der,
}
childKey3Der, _ := x509.MarshalECPrivateKey(childKey3.(*ecdsa.PrivateKey))
childKey3Pem := &pem.Block{
Type: "EC PRIVATE KEY",
Bytes: childKey3Der,
}
childKey4Der, _ := x509.MarshalECPrivateKey(childKey4.(*ecdsa.PrivateKey))
childKey4Pem := &pem.Block{
Type: "EC PRIVATE KEY",
Bytes: childKey4Der,
}
parentPem := &pem.Block{
Type: "CERTIFICATE",
Bytes: parentDer,
}
childCert1Pem := &pem.Block{
Type: "CERTIFICATE",
Bytes: childCert1Der,
}
childCert2Pem := &pem.Block{
Type: "CERTIFICATE",
Bytes: childCert2Der,
}
childCert3Pem := &pem.Block{
Type: "CERTIFICATE",
Bytes: childCert3Der,
}
childCert4Pem := &pem.Block{
Type: "CERTIFICATE",
Bytes: childCert4Der,
}
cfg := Config{
Key: "pem:" + string(pem.EncodeToMemory(childKey1Pem)),
Cert: "pem:" + string(pem.EncodeToMemory(childCert1Pem)) + string(pem.EncodeToMemory(parentPem)),
ServerKey: "pem:" + string(pem.EncodeToMemory(childKey2Pem)),
ServerCert: "pem:" + string(pem.EncodeToMemory(childCert2Pem)) + string(pem.EncodeToMemory(parentPem)),
AltServerCerts: []ServerPair{
{
ServerKey: "pem:" + string(pem.EncodeToMemory(childKey3Pem)),
ServerCert: "pem:" + string(pem.EncodeToMemory(childCert3Pem)) + string(pem.EncodeToMemory(parentPem)),
},
{
ServerKey: "pem:" + string(pem.EncodeToMemory(childKey4Pem)),
ServerCert: "pem:" + string(pem.EncodeToMemory(childCert4Pem)) + string(pem.EncodeToMemory(parentPem)),
},
},
}
id, err := LoadIdentity(cfg)
t.Run("loads without error", func(t *testing.T) {
assert.NoError(t, err)
})
t.Run("check for sans conflicts returns no conflict", func(t *testing.T) {
req := require.New(t)
conflicts := id.CheckServerCertSansForConflicts()
req.Len(conflicts, 2)
req.Equal("127.0.0.1", conflicts[0].HostOrIp)
req.Equal(conflicts[0].Certificates[0].SerialNumber, childCert2.SerialNumber)
req.Equal(conflicts[0].Certificates[1].SerialNumber, childCert3.SerialNumber)
req.Equal("client3.netfoundry.io", conflicts[1].HostOrIp)
req.Equal(conflicts[1].Certificates[0].SerialNumber, childCert3.SerialNumber)
req.Equal(conflicts[1].Certificates[1].SerialNumber, childCert4.SerialNumber)
})
})
}
func Test_LoadIdentityWithAltServerCerts(t *testing.T) {
// setup
caKey, caCertTemplate := mkCaCert("Parent CA")
parentDer, err := x509.CreateCertificate(rand.Reader, caCertTemplate, caCertTemplate, caKey.Public(), caKey)
assert.NoError(t, err)
childKey1, childCert1 := mkClientCert("Test Child 1")
childCert1Der, err := x509.CreateCertificate(rand.Reader, childCert1, caCertTemplate, childKey1.Public(), caKey)
assert.NoError(t, err)
childKey2, childCert2 := mkServerCert("Test Child 2", []string{"client2.netfoundry.io"}, []net.IP{net.ParseIP("127.0.0.1")})
childCert2Der, err := x509.CreateCertificate(rand.Reader, childCert2, caCertTemplate, childKey2.Public(), caKey)
assert.NoError(t, err)
childKey3, childCert3 := mkServerCert("Test Child 3", []string{"client3.netfoundry.io"}, []net.IP{net.ParseIP("10.8.0.1")})
childCert3Der, err := x509.CreateCertificate(rand.Reader, childCert3, caCertTemplate, childKey3.Public(), caKey)
assert.NoError(t, err)
childKey4, childCert4 := mkServerCert("Test Child 4", []string{"client4.netfoundry.io"}, []net.IP{net.ParseIP("192.168.0.1")})
childCert4Der, err := x509.CreateCertificate(rand.Reader, childCert4, caCertTemplate, childKey4.Public(), caKey)
assert.NoError(t, err)
childKey1Der, _ := x509.MarshalECPrivateKey(childKey1.(*ecdsa.PrivateKey))
childKey1Pem := &pem.Block{
Type: "EC PRIVATE KEY",
Bytes: childKey1Der,
}
childKey2Der, _ := x509.MarshalECPrivateKey(childKey2.(*ecdsa.PrivateKey))
childKey2Pem := &pem.Block{
Type: "EC PRIVATE KEY",
Bytes: childKey2Der,
}
childKey3Der, _ := x509.MarshalECPrivateKey(childKey3.(*ecdsa.PrivateKey))
childKey3Pem := &pem.Block{
Type: "EC PRIVATE KEY",
Bytes: childKey3Der,
}
childKey4Der, _ := x509.MarshalECPrivateKey(childKey4.(*ecdsa.PrivateKey))
childKey4Pem := &pem.Block{
Type: "EC PRIVATE KEY",
Bytes: childKey4Der,
}
parentPem := &pem.Block{
Type: "CERTIFICATE",
Bytes: parentDer,
}
childCert1Pem := &pem.Block{
Type: "CERTIFICATE",
Bytes: childCert1Der,
}
childCert2Pem := &pem.Block{
Type: "CERTIFICATE",
Bytes: childCert2Der,
}
childCert3Pem := &pem.Block{
Type: "CERTIFICATE",
Bytes: childCert3Der,
}
childCert4Pem := &pem.Block{
Type: "CERTIFICATE",
Bytes: childCert4Der,
}
cfg := Config{
Key: "pem:" + string(pem.EncodeToMemory(childKey1Pem)),
Cert: "pem:" + string(pem.EncodeToMemory(childCert1Pem)) + string(pem.EncodeToMemory(parentPem)),
ServerKey: "pem:" + string(pem.EncodeToMemory(childKey2Pem)),
ServerCert: "pem:" + string(pem.EncodeToMemory(childCert2Pem)) + string(pem.EncodeToMemory(parentPem)),
AltServerCerts: []ServerPair{
{
ServerKey: "pem:" + string(pem.EncodeToMemory(childKey3Pem)),
ServerCert: "pem:" + string(pem.EncodeToMemory(childCert3Pem)) + string(pem.EncodeToMemory(parentPem)),
},
{
ServerKey: "pem:" + string(pem.EncodeToMemory(childKey4Pem)),
ServerCert: "pem:" + string(pem.EncodeToMemory(childCert4Pem)) + string(pem.EncodeToMemory(parentPem)),
},
},
}
id, err := LoadIdentity(cfg)
t.Run("loads without error", func(t *testing.T) {
assert.NoError(t, err)
})
t.Run("has the correct client certificate", func(t *testing.T) {
assert.NotNil(t, id.Cert())
assert.Equal(t, 2, len(id.Cert().Certificate))
assert.NotNil(t, id.Cert().Leaf)
assert.Equal(t, childCert1Der, id.Cert().Leaf.Raw)
})
t.Run("has the correct server certificates", func(t *testing.T) {
serverTlsCerts := id.ServerCert()
childCert2Print := fmt.Sprintf("%x", sha1.Sum(childCert2Der))
childCert3Print := fmt.Sprintf("%x", sha1.Sum(childCert3Der))
childCert4Print := fmt.Sprintf("%x", sha1.Sum(childCert4Der))
certsToKeys := map[string]*ecdsa.PrivateKey{
childCert2Print: childKey2.(*ecdsa.PrivateKey),
childCert3Print: childKey3.(*ecdsa.PrivateKey),
childCert4Print: childKey4.(*ecdsa.PrivateKey),
}
foundServerCerts := map[string]bool{
childCert2Print: false,
childCert3Print: false,
childCert4Print: false,
}
for _, cert := range serverTlsCerts {
curPrint := fmt.Sprintf("%x", sha1.Sum(cert.Leaf.Raw))
if certsToKeys[curPrint].Equal(cert.PrivateKey) {
foundServerCerts[curPrint] = true
}
}
assert.True(t, foundServerCerts[childCert2Print], "child cert 2 was not found")
assert.True(t, foundServerCerts[childCert3Print], "child cert 3 was not found")
})
t.Run("returns the correct x509 certificates", func(t *testing.T) {
t.Run("the correct active server chains", func(t *testing.T) {
req := require.New(t)
chains := id.GetX509ActiveServerCertChains()
chainMap := map[string][]string{}
for _, chain := range chains {
leafPrint := fmt.Sprintf("%x", sha1.Sum(chain[0].Raw))
for i, cert := range chain {
if i == 0 {
continue
}
chainMap[leafPrint] = append(chainMap[leafPrint], fmt.Sprintf("%x", sha1.Sum(cert.Raw)))
}
}
cert2Print := fmt.Sprintf("%x", sha1.Sum(childCert2Der))
cert3Print := fmt.Sprintf("%x", sha1.Sum(childCert3Der))
cert4Print := fmt.Sprintf("%x", sha1.Sum(childCert4Der))
parentPrint := fmt.Sprintf("%x", sha1.Sum(parentDer))
expectedMap := map[string][]string{
cert2Print: {parentPrint},
cert3Print: {parentPrint},
cert4Print: {parentPrint},
}
req.Len(chainMap, 3)
req.ElementsMatch(mapKeys(chainMap), mapKeys(expectedMap))
for k, v := range expectedMap {
req.ElementsMatch(v, chainMap[k])
}
})
t.Run("the correct active client chain", func(t *testing.T) {
req := require.New(t)
clientChain := id.GetX509ActiveClientCertChain()
var actualCerts []string
for _, cert := range clientChain {
actualCerts = append(actualCerts, fmt.Sprintf("%x", sha1.Sum(cert.Raw)))
}
var expectedCerts []string
for _, tlsCert := range id.Cert().Certificate {
expectedCerts = append(expectedCerts, fmt.Sprintf("%x", sha1.Sum(tlsCert)))
}
req.Len(actualCerts, 2)
req.Len(expectedCerts, 2)
req.Equal(expectedCerts[0], actualCerts[0])
req.Equal(expectedCerts[1], actualCerts[1])
})
t.Run("the correct identity server cert chain", func(t *testing.T) {
req := require.New(t)
serverChain := id.GetX509IdentityServerCertChain()
var actualCerts []string
for _, cert := range serverChain {
actualCerts = append(actualCerts, fmt.Sprintf("%x", sha1.Sum(cert.Raw)))
}
var expectedCerts []string
parsedCerts, err := LoadCert(id.GetConfig().ServerCert)
req.NoError(err)
for _, cert := range parsedCerts {
expectedCerts = append(expectedCerts, fmt.Sprintf("%x", sha1.Sum(cert.Raw)))
}
req.Len(actualCerts, 2)
req.Len(expectedCerts, 2)
req.Equal(expectedCerts[0], actualCerts[0])
req.Equal(expectedCerts[1], actualCerts[1])
})
t.Run("the correct alt server cert chains", func(t *testing.T) {
req := require.New(t)
chains := id.GetX509IdentityAltCertCertChains()
chainMap := map[string][]string{}
for _, chain := range chains {
leafPrint := fmt.Sprintf("%x", sha1.Sum(chain[0].Raw))
for i, cert := range chain {
if i == 0 {
continue
}
chainMap[leafPrint] = append(chainMap[leafPrint], fmt.Sprintf("%x", sha1.Sum(cert.Raw)))
}
}
cert3Print := fmt.Sprintf("%x", sha1.Sum(childCert3Der))
cert4Print := fmt.Sprintf("%x", sha1.Sum(childCert4Der))
parentPrint := fmt.Sprintf("%x", sha1.Sum(parentDer))
expectedMap := map[string][]string{
cert3Print: {parentPrint},
cert4Print: {parentPrint},
}
req.Len(chainMap, 2)
req.ElementsMatch(mapKeys(chainMap), mapKeys(expectedMap))
for k, v := range expectedMap {
req.ElementsMatch(v, chainMap[k])
}
})
})
}
func Test_LoadIdentityWithFile(t *testing.T) {
// setup
key, cert := mkServerAndClientCert("File Test Cert", []string{"file.test.netfoundry.io"})
keyDer, _ := x509.MarshalECPrivateKey(key.(*ecdsa.PrivateKey))
keyPem := &pem.Block{
Type: "EC PRIVATE KEY",
Bytes: keyDer,
}
keyFile, _ := os.CreateTemp(os.TempDir(), "test-key")
defer func() { _ = os.Remove(keyFile.Name()) }()
certDer, err := x509.CreateCertificate(rand.Reader, cert, cert, key.Public(), key)
assert.NoError(t, err)
certPem := &pem.Block{
Type: "CERTIFICATE",
Bytes: certDer,
}
certFile, _ := os.CreateTemp(os.TempDir(), "test-cert")
defer func() { _ = os.Remove(certFile.Name()) }()
err = pem.Encode(keyFile, keyPem)
assert.NoError(t, err)
err = pem.Encode(certFile, certPem)
assert.NoError(t, err)
cfg := Config{
Key: "file://" + keyFile.Name(),
Cert: "file://" + certFile.Name(),
}
id, err := LoadIdentity(cfg)
assert.NoError(t, err)
assert.Equal(t, certDer, id.Cert().Leaf.Raw)
}
// helpers
var testSerial = int64(0)
func mkCaCert(cn string) (crypto.Signer, *x509.Certificate) {
testSerial++
key, _ := ecdsa.GenerateKey(elliptic.P224(), rand.Reader)
cert := &x509.Certificate{
SerialNumber: big.NewInt(testSerial),
Subject: pkix.Name{
Organization: []string{"Hanzo ZT Identity Tests"},
OrganizationalUnit: []string{"CA Certs"},
CommonName: cn,
},
NotBefore: time.Now(),
NotAfter: time.Now().Add(1 * time.Hour),
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
ExtKeyUsage: []x509.ExtKeyUsage{}, // CAs typically don’t need ExtKeyUsage
IsCA: true,
BasicConstraintsValid: true,
MaxPathLen: 2,
MaxPathLenZero: false,
}
return key, cert
}
func mkServerAndClientCert(cn string, dns []string) (crypto.Signer, *x509.Certificate) {
testSerial++
key, _ := ecdsa.GenerateKey(elliptic.P224(), rand.Reader)
cert := &x509.Certificate{
SerialNumber: big.NewInt(testSerial),
Subject: pkix.Name{
Organization: []string{"Hanzo ZT Identity Tests"},
OrganizationalUnit: []string{"Server And Client Certs"},
CommonName: cn,
},
DNSNames: dns,
NotBefore: time.Now(),
NotAfter: time.Now().Add(1 * time.Hour),
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
BasicConstraintsValid: true,
}
return key, cert
}
func mkServerCert(cn string, dns []string, ips []net.IP) (crypto.Signer, *x509.Certificate) {
testSerial++
key, _ := ecdsa.GenerateKey(elliptic.P224(), rand.Reader)
cert := &x509.Certificate{
SerialNumber: big.NewInt(testSerial),
Subject: pkix.Name{
Organization: []string{"Hanzo ZT Identity Tests"},
OrganizationalUnit: []string{"Server Certs"},
CommonName: cn,
},
DNSNames: dns,
IPAddresses: ips,
NotBefore: time.Now(),
NotAfter: time.Now().Add(1 * time.Hour),
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
BasicConstraintsValid: true,
}
return key, cert
}
func mkClientCert(cn string) (crypto.Signer, *x509.Certificate) {
key, _ := ecdsa.GenerateKey(elliptic.P224(), rand.Reader)
cert := &x509.Certificate{
SerialNumber: big.NewInt(testSerial),
Subject: pkix.Name{
Organization: []string{"Hanzo ZT Identity Tests"},
OrganizationalUnit: []string{"Client Certs"},
CommonName: cn,
},
NotBefore: time.Now(),
NotAfter: time.Now().Add(1 * time.Hour),
KeyUsage: x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
BasicConstraintsValid: true,
}
return key, cert
}
func mapKeys[T comparable, K any](m map[T]K) []T {
result := make([]T, 0, len(m))
for k := range m {
result = append(result, k)
}
return result
}