2021-10-21 16:24:11 -05:00
//go:build !windows
2019-12-11 10:13:19 -05:00
// +build !windows
2019-11-19 17:00:20 +00:00
package main
import (
"bytes"
"crypto/rand"
2023-04-03 13:59:38 -04:00
"errors"
2019-11-19 17:00:20 +00:00
"os"
"testing"
"time"
2019-12-11 23:15:57 -05:00
"github.com/slackhq/nebula/cert"
2019-11-19 17:00:20 +00:00
"github.com/stretchr/testify/assert"
2025-03-10 17:38:14 -05:00
"github.com/stretchr/testify/require"
2019-11-19 17:00:20 +00:00
"golang.org/x/crypto/ed25519"
)
func Test_signSummary ( t * testing . T ) {
assert . Equal ( t , "sign <flags>: create and sign a certificate" , signSummary ( ) )
}
func Test_signHelp ( t * testing . T ) {
ob := & bytes . Buffer { }
signHelp ( ob )
assert . Equal (
t ,
"Usage of " + os . Args [ 0 ] + " sign <flags>: create and sign a certificate\n" +
" -ca-crt string\n" +
" \tOptional: path to the signing CA cert (default \"ca.crt\")\n" +
" -ca-key string\n" +
" \tOptional: path to the signing CA key (default \"ca.key\")\n" +
" -duration duration\n" +
2020-01-06 19:51:29 +01:00
" \tOptional: how long the cert should be valid for. The default is 1 second before the signing cert expires. Valid time units are seconds: \"s\", minutes: \"m\", hours: \"h\"\n" +
2019-11-19 17:00:20 +00:00
" -groups string\n" +
" \tOptional: comma separated list of groups\n" +
" -in-pub string\n" +
" \tOptional (if out-key not set): path to read a previously generated public key\n" +
" -ip string\n" +
2025-03-06 11:28:26 -06:00
" \tDeprecated, see -networks\n" +
2019-11-19 17:00:20 +00:00
" -name string\n" +
" \tRequired: name of the cert, usually a hostname\n" +
2025-03-06 11:28:26 -06:00
" -networks string\n" +
" \tRequired: comma separated list of ip address and network in CIDR notation to assign to this cert\n" +
2019-11-19 17:00:20 +00:00
" -out-crt string\n" +
" \tOptional: path to write the certificate to\n" +
" -out-key string\n" +
" \tOptional (if in-pub not set): path to write the private key to\n" +
2021-02-11 18:53:25 -06:00
" -out-qr string\n" +
" \tOptional: output a qr code image (png) of the certificate\n" +
2024-09-09 17:51:58 -04:00
optionalPkcs11String ( " -pkcs11 string\n \tOptional: PKCS#11 URI to an existing private key\n" ) +
2019-11-19 17:00:20 +00:00
" -subnets string\n" +
2025-03-06 11:28:26 -06:00
" \tDeprecated, see -unsafe-networks\n" +
" -unsafe-networks string\n" +
" \tOptional: comma separated list of ip address and network in CIDR notation. Unsafe networks this cert can route for\n" +
" -version uint\n" +
" \tOptional: version of the certificate format to use, the default is to create both v1 and v2 certificates.\n" ,
2019-11-19 17:00:20 +00:00
ob . String ( ) ,
)
}
func Test_signCert ( t * testing . T ) {
ob := & bytes . Buffer { }
eb := & bytes . Buffer { }
2023-04-03 13:59:38 -04:00
nopw := & StubPasswordReader {
password : [ ] byte ( "" ) ,
err : nil ,
}
errpw := & StubPasswordReader {
password : [ ] byte ( "" ) ,
err : errors . New ( "stub error" ) ,
}
passphrase := [ ] byte ( "DO NOT USE THIS KEY" )
testpw := & StubPasswordReader {
password : passphrase ,
err : nil ,
}
2019-11-19 17:00:20 +00:00
// required args
2023-04-03 13:59:38 -04:00
assertHelpError ( t , signCert (
2025-03-06 11:28:26 -06:00
[ ] string { "-version" , "1" , "-ca-crt" , "./nope" , "-ca-key" , "./nope" , "-ip" , "1.1.1.1/24" , "-out-key" , "nope" , "-out-crt" , "nope" } , ob , eb , nopw ,
2023-04-03 13:59:38 -04:00
) , "-name is required" )
2019-11-19 17:00:20 +00:00
assert . Empty ( t , ob . String ( ) )
assert . Empty ( t , eb . String ( ) )
2023-04-03 13:59:38 -04:00
assertHelpError ( t , signCert (
2025-03-06 11:28:26 -06:00
[ ] string { "-version" , "1" , "-ca-crt" , "./nope" , "-ca-key" , "./nope" , "-name" , "test" , "-out-key" , "nope" , "-out-crt" , "nope" } , ob , eb , nopw ,
) , "-networks is required" )
2019-11-19 17:00:20 +00:00
assert . Empty ( t , ob . String ( ) )
assert . Empty ( t , eb . String ( ) )
// cannot set -in-pub and -out-key
2023-04-03 13:59:38 -04:00
assertHelpError ( t , signCert (
2025-03-06 11:28:26 -06:00
[ ] string { "-version" , "1" , "-ca-crt" , "./nope" , "-ca-key" , "./nope" , "-name" , "test" , "-in-pub" , "nope" , "-ip" , "1.1.1.1/24" , "-out-crt" , "nope" , "-out-key" , "nope" } , ob , eb , nopw ,
2023-04-03 13:59:38 -04:00
) , "cannot set both -in-pub and -out-key" )
2019-11-19 17:00:20 +00:00
assert . Empty ( t , ob . String ( ) )
assert . Empty ( t , eb . String ( ) )
// failed to read key
ob . Reset ( )
eb . Reset ( )
2025-03-06 11:28:26 -06:00
args := [ ] string { "-version" , "1" , "-ca-crt" , "./nope" , "-ca-key" , "./nope" , "-name" , "test" , "-ip" , "1.1.1.1/24" , "-out-crt" , "nope" , "-out-key" , "nope" , "-duration" , "100m" }
2025-03-10 17:38:14 -05:00
require . EqualError ( t , signCert ( args , ob , eb , nopw ) , "error while reading ca-key: open ./nope: " + NoSuchFileError )
2019-11-19 17:00:20 +00:00
// failed to unmarshal key
ob . Reset ( )
eb . Reset ( )
2023-10-31 22:35:13 +08:00
caKeyF , err := os . CreateTemp ( "" , "sign-cert.key" )
2025-03-10 17:38:14 -05:00
require . NoError ( t , err )
2019-11-19 17:00:20 +00:00
defer os . Remove ( caKeyF . Name ( ) )
2025-03-06 11:28:26 -06:00
args = [ ] string { "-version" , "1" , "-ca-crt" , "./nope" , "-ca-key" , caKeyF . Name ( ) , "-name" , "test" , "-ip" , "1.1.1.1/24" , "-out-crt" , "nope" , "-out-key" , "nope" , "-duration" , "100m" }
2025-03-10 17:38:14 -05:00
require . EqualError ( t , signCert ( args , ob , eb , nopw ) , "error while parsing ca-key: input did not contain a valid PEM encoded block" )
2019-11-19 17:00:20 +00:00
assert . Empty ( t , ob . String ( ) )
assert . Empty ( t , eb . String ( ) )
// Write a proper ca key for later
ob . Reset ( )
eb . Reset ( )
caPub , caPriv , _ := ed25519 . GenerateKey ( rand . Reader )
2024-10-10 18:00:22 -05:00
caKeyF . Write ( cert . MarshalSigningPrivateKeyToPEM ( cert . Curve_CURVE25519 , caPriv ) )
2019-11-19 17:00:20 +00:00
// failed to read cert
2025-03-06 11:28:26 -06:00
args = [ ] string { "-version" , "1" , "-ca-crt" , "./nope" , "-ca-key" , caKeyF . Name ( ) , "-name" , "test" , "-ip" , "1.1.1.1/24" , "-out-crt" , "nope" , "-out-key" , "nope" , "-duration" , "100m" }
2025-03-10 17:38:14 -05:00
require . EqualError ( t , signCert ( args , ob , eb , nopw ) , "error while reading ca-crt: open ./nope: " + NoSuchFileError )
2019-11-19 17:00:20 +00:00
assert . Empty ( t , ob . String ( ) )
assert . Empty ( t , eb . String ( ) )
// failed to unmarshal cert
ob . Reset ( )
eb . Reset ( )
2023-10-31 22:35:13 +08:00
caCrtF , err := os . CreateTemp ( "" , "sign-cert.crt" )
2025-03-10 17:38:14 -05:00
require . NoError ( t , err )
2019-11-19 17:00:20 +00:00
defer os . Remove ( caCrtF . Name ( ) )
2025-03-06 11:28:26 -06:00
args = [ ] string { "-version" , "1" , "-ca-crt" , caCrtF . Name ( ) , "-ca-key" , caKeyF . Name ( ) , "-name" , "test" , "-ip" , "1.1.1.1/24" , "-out-crt" , "nope" , "-out-key" , "nope" , "-duration" , "100m" }
2025-03-10 17:38:14 -05:00
require . EqualError ( t , signCert ( args , ob , eb , nopw ) , "error while parsing ca-crt: input did not contain a valid PEM encoded block" )
2019-11-19 17:00:20 +00:00
assert . Empty ( t , ob . String ( ) )
assert . Empty ( t , eb . String ( ) )
// write a proper ca cert for later
2024-10-10 18:00:22 -05:00
ca , _ := NewTestCaCert ( "ca" , caPub , caPriv , time . Now ( ) , time . Now ( ) . Add ( time . Minute * 200 ) , nil , nil , nil )
b , _ := ca . MarshalPEM ( )
2019-11-19 17:00:20 +00:00
caCrtF . Write ( b )
// failed to read pub
2025-03-06 11:28:26 -06:00
args = [ ] string { "-version" , "1" , "-ca-crt" , caCrtF . Name ( ) , "-ca-key" , caKeyF . Name ( ) , "-name" , "test" , "-ip" , "1.1.1.1/24" , "-out-crt" , "nope" , "-in-pub" , "./nope" , "-duration" , "100m" }
2025-03-10 17:38:14 -05:00
require . EqualError ( t , signCert ( args , ob , eb , nopw ) , "error while reading in-pub: open ./nope: " + NoSuchFileError )
2019-11-19 17:00:20 +00:00
assert . Empty ( t , ob . String ( ) )
assert . Empty ( t , eb . String ( ) )
// failed to unmarshal pub
ob . Reset ( )
eb . Reset ( )
2023-10-31 22:35:13 +08:00
inPubF , err := os . CreateTemp ( "" , "in.pub" )
2025-03-10 17:38:14 -05:00
require . NoError ( t , err )
2019-11-19 17:00:20 +00:00
defer os . Remove ( inPubF . Name ( ) )
2025-03-06 11:28:26 -06:00
args = [ ] string { "-version" , "1" , "-ca-crt" , caCrtF . Name ( ) , "-ca-key" , caKeyF . Name ( ) , "-name" , "test" , "-ip" , "1.1.1.1/24" , "-out-crt" , "nope" , "-in-pub" , inPubF . Name ( ) , "-duration" , "100m" }
2025-03-10 17:38:14 -05:00
require . EqualError ( t , signCert ( args , ob , eb , nopw ) , "error while parsing in-pub: input did not contain a valid PEM encoded block" )
2019-11-19 17:00:20 +00:00
assert . Empty ( t , ob . String ( ) )
assert . Empty ( t , eb . String ( ) )
// write a proper pub for later
ob . Reset ( )
eb . Reset ( )
inPub , _ := x25519Keypair ( )
2024-10-10 18:00:22 -05:00
inPubF . Write ( cert . MarshalPublicKeyToPEM ( cert . Curve_CURVE25519 , inPub ) )
2019-11-19 17:00:20 +00:00
// bad ip cidr
ob . Reset ( )
eb . Reset ( )
2025-03-06 11:28:26 -06:00
args = [ ] string { "-version" , "1" , "-ca-crt" , caCrtF . Name ( ) , "-ca-key" , caKeyF . Name ( ) , "-name" , "test" , "-ip" , "a1.1.1.1/24" , "-out-crt" , "nope" , "-out-key" , "nope" , "-duration" , "100m" }
assertHelpError ( t , signCert ( args , ob , eb , nopw ) , "invalid -networks definition: a1.1.1.1/24" )
assert . Empty ( t , ob . String ( ) )
assert . Empty ( t , eb . String ( ) )
ob . Reset ( )
eb . Reset ( )
args = [ ] string { "-version" , "1" , "-ca-crt" , caCrtF . Name ( ) , "-ca-key" , caKeyF . Name ( ) , "-name" , "test" , "-ip" , "100::100/100" , "-out-crt" , "nope" , "-out-key" , "nope" , "-duration" , "100m" }
assertHelpError ( t , signCert ( args , ob , eb , nopw ) , "invalid -networks definition: v1 certificates can only have a single ipv4 address" )
2019-11-19 17:00:20 +00:00
assert . Empty ( t , ob . String ( ) )
assert . Empty ( t , eb . String ( ) )
2021-12-07 21:40:30 -06:00
ob . Reset ( )
eb . Reset ( )
2025-03-06 11:28:26 -06:00
args = [ ] string { "-version" , "1" , "-ca-crt" , caCrtF . Name ( ) , "-ca-key" , caKeyF . Name ( ) , "-name" , "test" , "-ip" , "1.1.1.1/24,1.1.1.2/24" , "-out-crt" , "nope" , "-out-key" , "nope" , "-duration" , "100m" }
assertHelpError ( t , signCert ( args , ob , eb , nopw ) , "invalid -networks definition: v1 certificates can only have a single ipv4 address" )
2021-12-07 21:40:30 -06:00
assert . Empty ( t , ob . String ( ) )
assert . Empty ( t , eb . String ( ) )
2019-11-19 17:00:20 +00:00
// bad subnet cidr
ob . Reset ( )
eb . Reset ( )
2025-03-06 11:28:26 -06:00
args = [ ] string { "-version" , "1" , "-ca-crt" , caCrtF . Name ( ) , "-ca-key" , caKeyF . Name ( ) , "-name" , "test" , "-ip" , "1.1.1.1/24" , "-out-crt" , "nope" , "-out-key" , "nope" , "-duration" , "100m" , "-subnets" , "a" }
assertHelpError ( t , signCert ( args , ob , eb , nopw ) , "invalid -unsafe-networks definition: a" )
2019-11-19 17:00:20 +00:00
assert . Empty ( t , ob . String ( ) )
assert . Empty ( t , eb . String ( ) )
2021-12-07 21:40:30 -06:00
ob . Reset ( )
eb . Reset ( )
2025-03-06 11:28:26 -06:00
args = [ ] string { "-version" , "1" , "-ca-crt" , caCrtF . Name ( ) , "-ca-key" , caKeyF . Name ( ) , "-name" , "test" , "-ip" , "1.1.1.1/24" , "-out-crt" , "nope" , "-out-key" , "nope" , "-duration" , "100m" , "-subnets" , "100::100/100" }
assertHelpError ( t , signCert ( args , ob , eb , nopw ) , "invalid -unsafe-networks definition: v1 certificates can only be ipv4" )
2021-12-07 21:40:30 -06:00
assert . Empty ( t , ob . String ( ) )
assert . Empty ( t , eb . String ( ) )
2021-10-01 12:43:33 -04:00
// mismatched ca key
_ , caPriv2 , _ := ed25519 . GenerateKey ( rand . Reader )
2023-10-31 22:35:13 +08:00
caKeyF2 , err := os . CreateTemp ( "" , "sign-cert-2.key" )
2025-03-10 17:38:14 -05:00
require . NoError ( t , err )
2021-10-01 12:43:33 -04:00
defer os . Remove ( caKeyF2 . Name ( ) )
2024-10-10 18:00:22 -05:00
caKeyF2 . Write ( cert . MarshalSigningPrivateKeyToPEM ( cert . Curve_CURVE25519 , caPriv2 ) )
2021-10-01 12:43:33 -04:00
ob . Reset ( )
eb . Reset ( )
2025-03-06 11:28:26 -06:00
args = [ ] string { "-version" , "1" , "-ca-crt" , caCrtF . Name ( ) , "-ca-key" , caKeyF2 . Name ( ) , "-name" , "test" , "-ip" , "1.1.1.1/24" , "-out-crt" , "nope" , "-out-key" , "nope" , "-duration" , "100m" , "-subnets" , "a" }
2025-03-10 17:38:14 -05:00
require . EqualError ( t , signCert ( args , ob , eb , nopw ) , "refusing to sign, root certificate does not match private key" )
2021-10-01 12:43:33 -04:00
assert . Empty ( t , ob . String ( ) )
assert . Empty ( t , eb . String ( ) )
2019-11-19 17:00:20 +00:00
// failed key write
ob . Reset ( )
eb . Reset ( )
2025-03-06 11:28:26 -06:00
args = [ ] string { "-version" , "1" , "-ca-crt" , caCrtF . Name ( ) , "-ca-key" , caKeyF . Name ( ) , "-name" , "test" , "-ip" , "1.1.1.1/24" , "-out-crt" , "/do/not/write/pleasecrt" , "-out-key" , "/do/not/write/pleasekey" , "-duration" , "100m" , "-subnets" , "10.1.1.1/32" }
2025-03-10 17:38:14 -05:00
require . EqualError ( t , signCert ( args , ob , eb , nopw ) , "error while writing out-key: open /do/not/write/pleasekey: " + NoSuchDirError )
2019-11-19 17:00:20 +00:00
assert . Empty ( t , ob . String ( ) )
assert . Empty ( t , eb . String ( ) )
// create temp key file
2023-10-31 22:35:13 +08:00
keyF , err := os . CreateTemp ( "" , "test.key" )
2025-03-10 17:38:14 -05:00
require . NoError ( t , err )
2019-11-19 17:00:20 +00:00
os . Remove ( keyF . Name ( ) )
// failed cert write
ob . Reset ( )
eb . Reset ( )
2025-03-06 11:28:26 -06:00
args = [ ] string { "-version" , "1" , "-ca-crt" , caCrtF . Name ( ) , "-ca-key" , caKeyF . Name ( ) , "-name" , "test" , "-ip" , "1.1.1.1/24" , "-out-crt" , "/do/not/write/pleasecrt" , "-out-key" , keyF . Name ( ) , "-duration" , "100m" , "-subnets" , "10.1.1.1/32" }
2025-03-10 17:38:14 -05:00
require . EqualError ( t , signCert ( args , ob , eb , nopw ) , "error while writing out-crt: open /do/not/write/pleasecrt: " + NoSuchDirError )
2019-11-19 17:00:20 +00:00
assert . Empty ( t , ob . String ( ) )
assert . Empty ( t , eb . String ( ) )
os . Remove ( keyF . Name ( ) )
// create temp cert file
2023-10-31 22:35:13 +08:00
crtF , err := os . CreateTemp ( "" , "test.crt" )
2025-03-10 17:38:14 -05:00
require . NoError ( t , err )
2019-11-19 17:00:20 +00:00
os . Remove ( crtF . Name ( ) )
// test proper cert with removed empty groups and subnets
ob . Reset ( )
eb . Reset ( )
2025-03-06 11:28:26 -06:00
args = [ ] string { "-version" , "1" , "-ca-crt" , caCrtF . Name ( ) , "-ca-key" , caKeyF . Name ( ) , "-name" , "test" , "-ip" , "1.1.1.1/24" , "-out-crt" , crtF . Name ( ) , "-out-key" , keyF . Name ( ) , "-duration" , "100m" , "-subnets" , "10.1.1.1/32, , 10.2.2.2/32 , , ,, 10.5.5.5/32" , "-groups" , "1,, 2 , ,,,3,4,5" }
2025-03-10 17:38:14 -05:00
require . NoError ( t , signCert ( args , ob , eb , nopw ) )
2019-11-19 17:00:20 +00:00
assert . Empty ( t , ob . String ( ) )
assert . Empty ( t , eb . String ( ) )
// read cert and key files
2023-10-31 22:35:13 +08:00
rb , _ := os . ReadFile ( keyF . Name ( ) )
2024-10-10 18:00:22 -05:00
lKey , b , curve , err := cert . UnmarshalPrivateKeyFromPEM ( rb )
assert . Equal ( t , cert . Curve_CURVE25519 , curve )
2025-03-10 09:18:34 -05:00
assert . Empty ( t , b )
2025-03-10 17:38:14 -05:00
require . NoError ( t , err )
2019-11-19 17:00:20 +00:00
assert . Len ( t , lKey , 32 )
2023-10-31 22:35:13 +08:00
rb , _ = os . ReadFile ( crtF . Name ( ) )
2024-10-10 18:00:22 -05:00
lCrt , b , err := cert . UnmarshalCertificateFromPEM ( rb )
2025-03-10 09:18:34 -05:00
assert . Empty ( t , b )
2025-03-10 17:38:14 -05:00
require . NoError ( t , err )
2019-11-19 17:00:20 +00:00
2024-10-10 18:00:22 -05:00
assert . Equal ( t , "test" , lCrt . Name ( ) )
assert . Equal ( t , "1.1.1.1/24" , lCrt . Networks ( ) [ 0 ] . String ( ) )
assert . Len ( t , lCrt . Networks ( ) , 1 )
assert . False ( t , lCrt . IsCA ( ) )
assert . Equal ( t , [ ] string { "1" , "2" , "3" , "4" , "5" } , lCrt . Groups ( ) )
assert . Len ( t , lCrt . UnsafeNetworks ( ) , 3 )
assert . Len ( t , lCrt . PublicKey ( ) , 32 )
assert . Equal ( t , time . Duration ( time . Minute * 100 ) , lCrt . NotAfter ( ) . Sub ( lCrt . NotBefore ( ) ) )
2019-11-19 17:00:20 +00:00
sns := [ ] string { }
2024-10-10 18:00:22 -05:00
for _ , sn := range lCrt . UnsafeNetworks ( ) {
2019-11-19 17:00:20 +00:00
sns = append ( sns , sn . String ( ) )
}
assert . Equal ( t , [ ] string { "10.1.1.1/32" , "10.2.2.2/32" , "10.5.5.5/32" } , sns )
2024-10-10 18:00:22 -05:00
issuer , _ := ca . Fingerprint ( )
assert . Equal ( t , issuer , lCrt . Issuer ( ) )
2019-11-19 17:00:20 +00:00
assert . True ( t , lCrt . CheckSignature ( caPub ) )
// test proper cert with in-pub
os . Remove ( keyF . Name ( ) )
os . Remove ( crtF . Name ( ) )
ob . Reset ( )
eb . Reset ( )
2025-03-06 11:28:26 -06:00
args = [ ] string { "-version" , "1" , "-ca-crt" , caCrtF . Name ( ) , "-ca-key" , caKeyF . Name ( ) , "-name" , "test" , "-ip" , "1.1.1.1/24" , "-out-crt" , crtF . Name ( ) , "-in-pub" , inPubF . Name ( ) , "-duration" , "100m" , "-groups" , "1" }
2025-03-10 17:38:14 -05:00
require . NoError ( t , signCert ( args , ob , eb , nopw ) )
2019-11-19 17:00:20 +00:00
assert . Empty ( t , ob . String ( ) )
assert . Empty ( t , eb . String ( ) )
// read cert file and check pub key matches in-pub
2023-10-31 22:35:13 +08:00
rb , _ = os . ReadFile ( crtF . Name ( ) )
2024-10-10 18:00:22 -05:00
lCrt , b , err = cert . UnmarshalCertificateFromPEM ( rb )
2025-03-10 09:18:34 -05:00
assert . Empty ( t , b )
2025-03-10 17:38:14 -05:00
require . NoError ( t , err )
2024-10-10 18:00:22 -05:00
assert . Equal ( t , lCrt . PublicKey ( ) , inPub )
2019-11-19 17:00:20 +00:00
// test refuse to sign cert with duration beyond root
ob . Reset ( )
eb . Reset ( )
2024-10-10 18:00:22 -05:00
os . Remove ( keyF . Name ( ) )
os . Remove ( crtF . Name ( ) )
2025-03-06 11:28:26 -06:00
args = [ ] string { "-version" , "1" , "-ca-crt" , caCrtF . Name ( ) , "-ca-key" , caKeyF . Name ( ) , "-name" , "test" , "-ip" , "1.1.1.1/24" , "-out-crt" , crtF . Name ( ) , "-out-key" , keyF . Name ( ) , "-duration" , "1000m" , "-subnets" , "10.1.1.1/32, , 10.2.2.2/32 , , ,, 10.5.5.5/32" , "-groups" , "1,, 2 , ,,,3,4,5" }
2025-03-10 17:38:14 -05:00
require . EqualError ( t , signCert ( args , ob , eb , nopw ) , "error while signing: certificate expires after signing certificate" )
2019-11-19 17:00:20 +00:00
assert . Empty ( t , ob . String ( ) )
assert . Empty ( t , eb . String ( ) )
// create valid cert/key for overwrite tests
os . Remove ( keyF . Name ( ) )
os . Remove ( crtF . Name ( ) )
2025-03-06 11:28:26 -06:00
args = [ ] string { "-version" , "1" , "-ca-crt" , caCrtF . Name ( ) , "-ca-key" , caKeyF . Name ( ) , "-name" , "test" , "-ip" , "1.1.1.1/24" , "-out-crt" , crtF . Name ( ) , "-out-key" , keyF . Name ( ) , "-duration" , "100m" , "-subnets" , "10.1.1.1/32, , 10.2.2.2/32 , , ,, 10.5.5.5/32" , "-groups" , "1,, 2 , ,,,3,4,5" }
2025-03-10 17:38:14 -05:00
require . NoError ( t , signCert ( args , ob , eb , nopw ) )
2019-11-19 17:00:20 +00:00
// test that we won't overwrite existing key file
2019-12-11 10:13:19 -05:00
os . Remove ( crtF . Name ( ) )
2019-11-19 17:00:20 +00:00
ob . Reset ( )
eb . Reset ( )
2025-03-06 11:28:26 -06:00
args = [ ] string { "-version" , "1" , "-ca-crt" , caCrtF . Name ( ) , "-ca-key" , caKeyF . Name ( ) , "-name" , "test" , "-ip" , "1.1.1.1/24" , "-out-crt" , crtF . Name ( ) , "-out-key" , keyF . Name ( ) , "-duration" , "100m" , "-subnets" , "10.1.1.1/32, , 10.2.2.2/32 , , ,, 10.5.5.5/32" , "-groups" , "1,, 2 , ,,,3,4,5" }
2025-03-10 17:38:14 -05:00
require . EqualError ( t , signCert ( args , ob , eb , nopw ) , "refusing to overwrite existing key: " + keyF . Name ( ) )
2019-11-19 17:00:20 +00:00
assert . Empty ( t , ob . String ( ) )
assert . Empty ( t , eb . String ( ) )
2019-12-11 10:13:19 -05:00
// create valid cert/key for overwrite tests
os . Remove ( keyF . Name ( ) )
os . Remove ( crtF . Name ( ) )
2025-03-06 11:28:26 -06:00
args = [ ] string { "-version" , "1" , "-ca-crt" , caCrtF . Name ( ) , "-ca-key" , caKeyF . Name ( ) , "-name" , "test" , "-ip" , "1.1.1.1/24" , "-out-crt" , crtF . Name ( ) , "-out-key" , keyF . Name ( ) , "-duration" , "100m" , "-subnets" , "10.1.1.1/32, , 10.2.2.2/32 , , ,, 10.5.5.5/32" , "-groups" , "1,, 2 , ,,,3,4,5" }
2025-03-10 17:38:14 -05:00
require . NoError ( t , signCert ( args , ob , eb , nopw ) )
2019-12-11 10:13:19 -05:00
2019-11-19 17:00:20 +00:00
// test that we won't overwrite existing certificate file
os . Remove ( keyF . Name ( ) )
ob . Reset ( )
eb . Reset ( )
2025-03-06 11:28:26 -06:00
args = [ ] string { "-version" , "1" , "-ca-crt" , caCrtF . Name ( ) , "-ca-key" , caKeyF . Name ( ) , "-name" , "test" , "-ip" , "1.1.1.1/24" , "-out-crt" , crtF . Name ( ) , "-out-key" , keyF . Name ( ) , "-duration" , "100m" , "-subnets" , "10.1.1.1/32, , 10.2.2.2/32 , , ,, 10.5.5.5/32" , "-groups" , "1,, 2 , ,,,3,4,5" }
2025-03-10 17:38:14 -05:00
require . EqualError ( t , signCert ( args , ob , eb , nopw ) , "refusing to overwrite existing cert: " + crtF . Name ( ) )
2019-11-19 17:00:20 +00:00
assert . Empty ( t , ob . String ( ) )
assert . Empty ( t , eb . String ( ) )
2023-04-03 13:59:38 -04:00
// create valid cert/key using encrypted CA key
os . Remove ( caKeyF . Name ( ) )
os . Remove ( caCrtF . Name ( ) )
os . Remove ( keyF . Name ( ) )
os . Remove ( crtF . Name ( ) )
ob . Reset ( )
eb . Reset ( )
2023-10-31 22:35:13 +08:00
caKeyF , err = os . CreateTemp ( "" , "sign-cert.key" )
2025-03-10 17:38:14 -05:00
require . NoError ( t , err )
2023-04-03 13:59:38 -04:00
defer os . Remove ( caKeyF . Name ( ) )
2023-10-31 22:35:13 +08:00
caCrtF , err = os . CreateTemp ( "" , "sign-cert.crt" )
2025-03-10 17:38:14 -05:00
require . NoError ( t , err )
2023-04-03 13:59:38 -04:00
defer os . Remove ( caCrtF . Name ( ) )
// generate the encrypted key
caPub , caPriv , _ = ed25519 . GenerateKey ( rand . Reader )
kdfParams := cert . NewArgon2Parameters ( 64 * 1024 , 4 , 3 )
2023-05-04 17:50:23 -04:00
b , _ = cert . EncryptAndMarshalSigningPrivateKey ( cert . Curve_CURVE25519 , caPriv , passphrase , kdfParams )
2023-04-03 13:59:38 -04:00
caKeyF . Write ( b )
2024-10-10 18:00:22 -05:00
ca , _ = NewTestCaCert ( "ca" , caPub , caPriv , time . Now ( ) , time . Now ( ) . Add ( time . Minute * 200 ) , nil , nil , nil )
b , _ = ca . MarshalPEM ( )
2023-04-03 13:59:38 -04:00
caCrtF . Write ( b )
// test with the proper password
2025-03-06 11:28:26 -06:00
args = [ ] string { "-version" , "1" , "-ca-crt" , caCrtF . Name ( ) , "-ca-key" , caKeyF . Name ( ) , "-name" , "test" , "-ip" , "1.1.1.1/24" , "-out-crt" , crtF . Name ( ) , "-out-key" , keyF . Name ( ) , "-duration" , "100m" , "-subnets" , "10.1.1.1/32, , 10.2.2.2/32 , , ,, 10.5.5.5/32" , "-groups" , "1,, 2 , ,,,3,4,5" }
2025-03-10 17:38:14 -05:00
require . NoError ( t , signCert ( args , ob , eb , testpw ) )
2023-04-03 13:59:38 -04:00
assert . Equal ( t , "Enter passphrase: " , ob . String ( ) )
assert . Empty ( t , eb . String ( ) )
// test with the wrong password
ob . Reset ( )
eb . Reset ( )
testpw . password = [ ] byte ( "invalid password" )
2025-03-06 11:28:26 -06:00
args = [ ] string { "-version" , "1" , "-ca-crt" , caCrtF . Name ( ) , "-ca-key" , caKeyF . Name ( ) , "-name" , "test" , "-ip" , "1.1.1.1/24" , "-out-crt" , crtF . Name ( ) , "-out-key" , keyF . Name ( ) , "-duration" , "100m" , "-subnets" , "10.1.1.1/32, , 10.2.2.2/32 , , ,, 10.5.5.5/32" , "-groups" , "1,, 2 , ,,,3,4,5" }
2025-03-10 17:38:14 -05:00
require . Error ( t , signCert ( args , ob , eb , testpw ) )
2023-04-03 13:59:38 -04:00
assert . Equal ( t , "Enter passphrase: " , ob . String ( ) )
assert . Empty ( t , eb . String ( ) )
// test with the user not entering a password
ob . Reset ( )
eb . Reset ( )
2025-03-06 11:28:26 -06:00
args = [ ] string { "-version" , "1" , "-ca-crt" , caCrtF . Name ( ) , "-ca-key" , caKeyF . Name ( ) , "-name" , "test" , "-ip" , "1.1.1.1/24" , "-out-crt" , crtF . Name ( ) , "-out-key" , keyF . Name ( ) , "-duration" , "100m" , "-subnets" , "10.1.1.1/32, , 10.2.2.2/32 , , ,, 10.5.5.5/32" , "-groups" , "1,, 2 , ,,,3,4,5" }
2025-03-10 17:38:14 -05:00
require . Error ( t , signCert ( args , ob , eb , nopw ) )
2023-04-03 13:59:38 -04:00
// normally the user hitting enter on the prompt would add newlines between these
assert . Equal ( t , "Enter passphrase: Enter passphrase: Enter passphrase: Enter passphrase: Enter passphrase: " , ob . String ( ) )
assert . Empty ( t , eb . String ( ) )
// test an error condition
ob . Reset ( )
eb . Reset ( )
2025-03-06 11:28:26 -06:00
args = [ ] string { "-version" , "1" , "-ca-crt" , caCrtF . Name ( ) , "-ca-key" , caKeyF . Name ( ) , "-name" , "test" , "-ip" , "1.1.1.1/24" , "-out-crt" , crtF . Name ( ) , "-out-key" , keyF . Name ( ) , "-duration" , "100m" , "-subnets" , "10.1.1.1/32, , 10.2.2.2/32 , , ,, 10.5.5.5/32" , "-groups" , "1,, 2 , ,,,3,4,5" }
2025-03-10 17:38:14 -05:00
require . Error ( t , signCert ( args , ob , eb , errpw ) )
2023-04-03 13:59:38 -04:00
assert . Equal ( t , "Enter passphrase: " , ob . String ( ) )
assert . Empty ( t , eb . String ( ) )
2019-11-19 17:00:20 +00:00
}