@@ -19,20 +19,23 @@ package main
1919
2020import (
2121 "crypto"
22+ "crypto/rand"
2223 "crypto/tls"
2324 "crypto/x509"
25+ "encoding/pem"
2426 "flag"
2527 "fmt"
2628 "net"
2729 "os"
2830 "path/filepath"
2931 "strings"
32+ "time"
3033
3134 "github.com/elastic/elastic-agent-libs/testing/certutil"
3235)
3336
3437func main () {
35- var caPath , caKeyPath , dest , name , ipList string
38+ var caPath , caKeyPath , dest , name , ipList , filePrefix , pass string
3639 flag .StringVar (& caPath , "ca" , "" ,
3740 "File path for CA in PEM format" )
3841 flag .StringVar (& caKeyPath , "ca-key" , "" ,
@@ -43,6 +46,10 @@ func main() {
4346 "used as \" distinguished name\" and \" Subject Alternate Name values\" for the child certificate" )
4447 flag .StringVar (& ipList , "ips" , "127.0.0.1" ,
4548 "a comma separated list of IP addresses for the child certificate" )
49+ flag .StringVar (& filePrefix , "prefix" , "current timestamp" ,
50+ "a prefix to be added to the file name. If not provided a timestamp will be used" )
51+ flag .StringVar (& pass , "pass" , "" ,
52+ "a passphrase to encrypt the certificate key" )
4653 flag .Parse ()
4754
4855 if caPath == "" && caKeyPath != "" || caPath != "" && caKeyPath == "" {
@@ -52,6 +59,16 @@ func main() {
5259 caPath , caKeyPath )
5360
5461 }
62+ if filePrefix == "" {
63+ filePrefix = fmt .Sprintf ("%d" , time .Now ().Unix ())
64+ }
65+ filePrefix += "-"
66+
67+ wd , err := os .Getwd ()
68+ if err != nil {
69+ fmt .Printf ("error getting current working directory: %v\n " , err )
70+ }
71+ fmt .Println ("files will be witten to:" , wd )
5572
5673 ips := strings .Split (ipList , "," )
5774 var netIPs []net.IP
@@ -61,25 +78,57 @@ func main() {
6178
6279 var rootCert * x509.Certificate
6380 var rootKey crypto.PrivateKey
64- var err error
6581 if caPath == "" && caKeyPath == "" {
6682 var pair certutil.Pair
6783 rootKey , rootCert , pair , err = certutil .NewRootCA ()
6884 if err != nil {
6985 panic (fmt .Errorf ("could not create root CA certificate: %w" , err ))
7086 }
7187
72- savePair (dest , "ca" , pair )
88+ savePair (dest , filePrefix + "ca" , pair )
7389 } else {
7490 rootKey , rootCert = loadCA (caPath , caKeyPath )
7591 }
7692
77- _ , childPair , err := certutil .GenerateChildCert (name , netIPs , rootKey , rootCert )
93+ childCert , childPair , err := certutil .GenerateChildCert (name , netIPs , rootKey , rootCert )
7894 if err != nil {
7995 panic (fmt .Errorf ("error generating child certificate: %w" , err ))
8096 }
8197
82- savePair (dest , name , childPair )
98+ savePair (dest , filePrefix + name , childPair )
99+
100+ if pass == "" {
101+ return
102+ }
103+
104+ fmt .Printf ("passphrase present, encrypting \" %s\" certificate key\n " ,
105+ name )
106+ err = os .WriteFile (filePrefix + name + "-passphrase" , []byte (pass ), 0o600 )
107+ if err != nil {
108+ panic (fmt .Errorf ("error writing passphrase file: %w" , err ))
109+ }
110+
111+ key , err := x509 .MarshalPKCS8PrivateKey (childCert .PrivateKey )
112+ if err != nil {
113+ panic (fmt .Errorf ("error getting ecdh.PrivateKey from the child's private key: %w" , err ))
114+ }
115+
116+ encPem , err := x509 .EncryptPEMBlock ( //nolint:staticcheck // we need to drop support for this, but while we don't, it needs to be tested.
117+ rand .Reader ,
118+ "EC PRIVATE KEY" ,
119+ key ,
120+ []byte (pass ),
121+ x509 .PEMCipherAES128 )
122+ if err != nil {
123+ panic (fmt .Errorf ("failed encrypting agent child certificate key block: %v" , err ))
124+ }
125+
126+ certKeyEnc := pem .EncodeToMemory (encPem )
127+
128+ err = os .WriteFile (filepath .Join (dest , filePrefix + name + "_enc-key.pem" ), certKeyEnc , 0o600 )
129+ if err != nil {
130+ panic (fmt .Errorf ("could not save %s certificate encrypted key: %w" , filePrefix + name + "_enc-key.pem" , err ))
131+ }
83132}
84133
85134func loadCA (caPath string , keyPath string ) (crypto.PrivateKey , * x509.Certificate ) {
0 commit comments