github.com/webdestroya/awsmocker@v0.2.6/certstore.go (about) 1 package awsmocker 2 3 import ( 4 "crypto/rand" 5 "crypto/rsa" 6 "crypto/tls" 7 "crypto/x509" 8 "crypto/x509/pkix" 9 "math" 10 "math/big" 11 "net" 12 "sync" 13 "time" 14 ) 15 16 var ( 17 globalCertStore *CertStorage 18 19 leafCertStart = time.Unix(time.Now().Unix()-2592000, 0) // 2592000 = 30 day 20 leafCertEnd = time.Unix(time.Now().Unix()+31536000, 0) 21 ) 22 23 type CertStorage struct { 24 certs sync.Map 25 26 mu sync.Mutex 27 28 nextSerial int64 29 privateKey *rsa.PrivateKey 30 } 31 32 func (tcs *CertStorage) Fetch(hostname string) *tls.Certificate { 33 34 icert, ok := tcs.certs.Load(hostname) 35 if ok { 36 cert := icert.(tls.Certificate) 37 return &cert 38 } 39 40 return tcs.generateCert(hostname) 41 } 42 43 func (tcs *CertStorage) generateCert(hostname string) *tls.Certificate { 44 45 tcs.mu.Lock() 46 defer tcs.mu.Unlock() 47 48 tcs.nextSerial += 1 49 50 caCert := CACert() 51 52 template := x509.Certificate{ 53 SerialNumber: big.NewInt(tcs.nextSerial), 54 Issuer: caCert.Subject, 55 Subject: pkix.Name{ 56 Country: []string{"US"}, 57 Organization: []string{"webdestroya"}, 58 OrganizationalUnit: []string{"awsmocker fake leaf"}, 59 }, 60 NotBefore: leafCertStart, 61 NotAfter: leafCertEnd, 62 63 KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, 64 ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, 65 BasicConstraintsValid: true, 66 } 67 68 if ip := net.ParseIP(hostname); ip != nil { 69 template.IPAddresses = append(template.IPAddresses, ip) 70 } else { 71 template.DNSNames = append(template.DNSNames, hostname) 72 template.Subject.CommonName = hostname 73 } 74 75 var derBytes []byte 76 var err error 77 if derBytes, err = x509.CreateCertificate(rand.Reader, &template, caCert, tcs.privateKey.Public(), caKeyPair.PrivateKey); err != nil { 78 panic("could not generate cert") 79 } 80 newCert := tls.Certificate{ 81 Certificate: [][]byte{derBytes, caKeyPair.Certificate[0]}, 82 PrivateKey: tcs.privateKey, 83 } 84 85 val, _ := tcs.certs.LoadOrStore(hostname, newCert) 86 87 val2 := (val).(tls.Certificate) 88 return &val2 89 } 90 91 func init() { 92 privKey, _ := rsa.GenerateKey(rand.Reader, 2048) 93 startSerial, _ := rand.Int(rand.Reader, big.NewInt(int64(math.Pow(2, 40)))) 94 95 globalCertStore = &CertStorage{ 96 certs: sync.Map{}, 97 privateKey: privKey, 98 nextSerial: startSerial.Int64(), 99 } 100 }