yao/commercial/testhelper_test.go
Max 789cc85996 feat(certificates): inject commercial license root certificates into build process
- Added steps in both Linux and macOS workflows to inject commercial license root certificates from GitHub Secrets during the build process.
- Updated the `inspect` and `load` packages to include license information, enhancing the application's licensing capabilities.
- Included license metadata in the OpenAPI response for better visibility of licensing status.
2026-03-27 12:51:30 +08:00

177 lines
4.8 KiB
Go

package commercial
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"math/big"
"time"
)
// testCA holds a generated CA certificate and its private key.
type testCA struct {
Cert *x509.Certificate
Key *ecdsa.PrivateKey
CertPEM []byte
}
// testLicenseCert holds a generated leaf (license) certificate.
type testLicenseCert struct {
Cert *x509.Certificate
CertPEM []byte
}
// generateRootCA creates a self-signed ECDSA P-384 root CA for testing.
func generateRootCA(cn string, validity time.Duration) (*testCA, error) {
key, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
if err != nil {
return nil, err
}
serial, _ := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128))
tmpl := &x509.Certificate{
SerialNumber: serial,
Subject: pkix.Name{
CommonName: cn,
Organization: []string{"Infinite Wisdom Software"},
Country: []string{"CN"},
},
NotBefore: time.Now().Add(-1 * time.Hour),
NotAfter: time.Now().Add(validity),
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
BasicConstraintsValid: true,
IsCA: true,
MaxPathLen: 1,
}
certDER, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &key.PublicKey, key)
if err != nil {
return nil, err
}
cert, err := x509.ParseCertificate(certDER)
if err != nil {
return nil, err
}
certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER})
return &testCA{Cert: cert, Key: key, CertPEM: certPEM}, nil
}
// generateIntermediateCA creates an intermediate CA signed by the given parent.
func generateIntermediateCA(cn string, validity time.Duration, parent *testCA) (*testCA, error) {
key, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
if err != nil {
return nil, err
}
serial, _ := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128))
tmpl := &x509.Certificate{
SerialNumber: serial,
Subject: pkix.Name{
CommonName: cn,
Organization: []string{"Test Partner Inc."},
Country: []string{"US"},
},
NotBefore: time.Now().Add(-1 * time.Hour),
NotAfter: time.Now().Add(validity),
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
BasicConstraintsValid: true,
IsCA: true,
MaxPathLen: 0,
MaxPathLenZero: true,
}
certDER, err := x509.CreateCertificate(rand.Reader, tmpl, parent.Cert, &key.PublicKey, parent.Key)
if err != nil {
return nil, err
}
cert, err := x509.ParseCertificate(certDER)
if err != nil {
return nil, err
}
certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER})
return &testCA{Cert: cert, Key: key, CertPEM: certPEM}, nil
}
// licenseOpts configures a test license certificate.
type licenseOpts struct {
CN string
Org string
Country string
Email string
NotBefore time.Time
NotAfter time.Time
Serial *big.Int
Extensions []ExtensionValue
}
func defaultLicenseOpts() licenseOpts {
return licenseOpts{
CN: "Test Corp",
Org: "Test Inc.",
Country: "CN",
Email: "test@example.com",
NotBefore: time.Now().Add(-1 * time.Hour),
NotAfter: time.Now().Add(365 * 24 * time.Hour),
Serial: big.NewInt(10042),
Extensions: []ExtensionValue{
{OID: OIDProduct, Value: "yao"},
{OID: OIDEdition, Value: "pro"},
{OID: OIDMaxUsers, Value: "500"},
{OID: OIDMaxTaiNodes, Value: "10"},
{OID: OIDMaxAgents, Value: "50"},
{OID: OIDMaxSandboxes, Value: "20"},
{OID: OIDMaxAPIRPM, Value: "10000"},
{OID: OIDMaxStorageGB, Value: "100"},
{OID: OIDSupportLevel, Value: "priority"},
},
}
}
// generateLicenseCert creates a leaf license certificate signed by the given CA.
func generateLicenseCert(signer *testCA, opts licenseOpts) (*testLicenseCert, error) {
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
return nil, err
}
tmpl := &x509.Certificate{
SerialNumber: opts.Serial,
Subject: pkix.Name{
CommonName: opts.CN,
Organization: []string{opts.Org},
Country: []string{opts.Country},
},
EmailAddresses: []string{opts.Email},
NotBefore: opts.NotBefore,
NotAfter: opts.NotAfter,
KeyUsage: x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageAny},
}
for _, ext := range opts.Extensions {
tmpl.ExtraExtensions = append(tmpl.ExtraExtensions, pkix.Extension{
Id: ext.OID,
Value: []byte(ext.Value),
})
}
certDER, err := x509.CreateCertificate(rand.Reader, tmpl, signer.Cert, &key.PublicKey, signer.Key)
if err != nil {
return nil, err
}
cert, err := x509.ParseCertificate(certDER)
if err != nil {
return nil, err
}
certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER})
return &testLicenseCert{Cert: cert, CertPEM: certPEM}, nil
}