Files
golib/certificates/certificates_config_test.go
Nicolas JUHEL 22b364593e Package certificates:
- rework package to allow convert config to model and retrive config from model
- add sub package to manage cipher, curves, auth client, tls version, certificates, root ca...
- add some small test (can be expande to having more coverage)
- optimize some code

Package httpcli:
- update code following change in certificates

Package httpserver:
- update code following change in certificates

Package Config/Components:
- update code following change in certificates

Package FTPClient:
- update code following change in certificates

Package Nats:
- update code following change in certificates
2024-12-04 17:30:22 +01:00

215 lines
6.6 KiB
Go

/*
* MIT License
*
* Copyright (c) 2020 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package certificates_test
import (
"bytes"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/x509"
"crypto/x509/pkix"
"encoding/json"
"encoding/pem"
"math/big"
"net"
"os"
"time"
libtls "github.com/nabbar/golib/certificates"
tlscrt "github.com/nabbar/golib/certificates/certs"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
func genCertififcate() ([]byte, []byte) {
priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
Expect(err).ToNot(HaveOccurred())
Expect(priv).ToNot(BeNil())
keyUsage := x509.KeyUsageDigitalSignature
notBefore := time.Now()
notAfter := notBefore.Add(time.Hour * 24 * 365)
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
Expect(err).ToNot(HaveOccurred())
template := x509.Certificate{
SerialNumber: serialNumber,
Subject: pkix.Name{
Organization: []string{"Acme Co"},
},
NotBefore: notBefore,
NotAfter: notAfter,
KeyUsage: keyUsage,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
BasicConstraintsValid: true,
}
template.DNSNames = append(template.DNSNames, "example.com")
template.DNSNames = append(template.DNSNames, "localhost")
if ip := net.ParseIP("127.0.0.1"); ip != nil {
template.IPAddresses = append(template.IPAddresses, ip)
}
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
Expect(err).ToNot(HaveOccurred())
bufPub := bytes.NewBuffer(make([]byte, 0))
err = pem.Encode(bufPub, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
Expect(err).ToNot(HaveOccurred())
bufKey := bytes.NewBuffer(make([]byte, 0))
privBytes, err := x509.MarshalPKCS8PrivateKey(priv)
Expect(err).ToNot(HaveOccurred())
err = pem.Encode(bufKey, &pem.Block{Type: "PRIVATE KEY", Bytes: privBytes})
Expect(err).ToNot(HaveOccurred())
return bufPub.Bytes(), bufKey.Bytes()
}
func writeGenCert(pub, key string) {
p, k := genCertififcate()
f, e := os.Create(pub)
Expect(e).ToNot(HaveOccurred())
_, e = f.Write(p)
Expect(e).ToNot(HaveOccurred())
Expect(f.Close()).ToNot(HaveOccurred())
f, e = os.Create(key)
Expect(e).ToNot(HaveOccurred())
_, e = f.Write(k)
Expect(e).ToNot(HaveOccurred())
Expect(f.Close()).ToNot(HaveOccurred())
}
func getConfigFile() []byte {
writeGenCert(pubFile, keyFile)
str := &tlscrt.ConfigPair{
Key: keyFile,
Pub: pubFile,
}
p, e := json.Marshal(str)
Expect(e).ToNot(HaveOccurred())
var oldConfig string = `{
"authClient": "none",
"certs": [` + string(p) + `],
"cipherList": ["RSA_AES_128_GCM_SHA256", "RSA_AES_256_GCM_SHA384", "ECDHE_RSA_AES_128_GCM_SHA256", "ECDHE_ECDSA_AES_128_GCM_SHA256", "ECDHE_RSA_AES_256_GCM_SHA384", "ECDHE_ECDSA_AES_256_GCM_SHA384", "ECDHE_RSA_CHACHA20_POLY1305_SHA256", "ECDHE_ECDSA_CHACHA20_POLY1305_SHA256", "AES_128_GCM_SHA256", "AES_256_GCM_SHA384", "CHACHA20_POLY1305_SHA256"],
"clientCA": [],
"curveList": ["X25519", "P256", "P384", "P521"],
"dynamicSizingDisable": false,
"inheritDefault": false,
"rootCA": [],
"sessionTicketDisable": false,
"versionMax": "1.3",
"versionMin": "1.2"
}`
return []byte(oldConfig)
}
func getConfigChain() []byte {
pub, key := genCertififcate()
str := "\n" + string(pub) + string(key)
buf, err := json.Marshal(str)
Expect(err).ToNot(HaveOccurred())
var oldConfig string = `{
"authClient": "none",
"certs": [` + string(buf) + `],
"cipherList": ["RSA_AES_128_GCM_SHA256", "RSA_AES_256_GCM_SHA384", "ECDHE_RSA_AES_128_GCM_SHA256", "ECDHE_ECDSA_AES_128_GCM_SHA256", "ECDHE_RSA_AES_256_GCM_SHA384", "ECDHE_ECDSA_AES_256_GCM_SHA384", "ECDHE_RSA_CHACHA20_POLY1305_SHA256", "ECDHE_ECDSA_CHACHA20_POLY1305_SHA256", "AES_128_GCM_SHA256", "AES_256_GCM_SHA384", "CHACHA20_POLY1305_SHA256"],
"clientCA": [],
"curveList": ["X25519", "P256", "P384", "P521"],
"dynamicSizingDisable": false,
"inheritDefault": false,
"rootCA": [],
"sessionTicketDisable": false,
"versionMax": "1.3",
"versionMin": "1.2"
}`
return []byte(oldConfig)
}
var _ = Describe("certificates test", func() {
Context("Using a config json", func() {
It("must success to new Config when certificates are paste as file mode", func() {
cfg := libtls.Config{}
p := getConfigFile()
Expect(len(p)).To(BeNumerically(">", 0))
e := json.Unmarshal(p, &cfg)
Expect(e).ToNot(HaveOccurred())
cnf := cfg.New()
Expect(cnf).ToNot(BeNil())
Expect(len(cnf.GetCertificatePair())).To(Equal(1))
cfgtls := cnf.TLS("localhost")
Expect(cfgtls).ToNot(BeNil())
Expect(len(cfgtls.Certificates)).To(Equal(1))
Expect(len(cfgtls.CipherSuites)).To(BeNumerically(">", 0))
Expect(len(cfgtls.CurvePreferences)).To(BeNumerically(">", 0))
p, e = json.Marshal(cnf.Config())
Expect(e).ToNot(HaveOccurred())
Expect(len(p)).To(BeNumerically(">", 0))
})
It("must success to new Config when certificates are paste as chain mode", func() {
cfg := libtls.Config{}
p := getConfigChain()
Expect(len(p)).To(BeNumerically(">", 0))
e := json.Unmarshal(p, &cfg)
Expect(e).ToNot(HaveOccurred())
cnf := cfg.New()
Expect(cnf).ToNot(BeNil())
Expect(len(cnf.GetCertificatePair())).To(Equal(1))
cfgtls := cnf.TLS("localhost")
Expect(cfgtls).ToNot(BeNil())
Expect(len(cfgtls.Certificates)).To(Equal(1))
Expect(len(cfgtls.CipherSuites)).To(BeNumerically(">", 0))
Expect(len(cfgtls.CurvePreferences)).To(BeNumerically(">", 0))
p, e = json.Marshal(cnf)
Expect(e).ToNot(HaveOccurred())
Expect(len(p)).To(BeNumerically(">", 0))
})
})
})