From ac8cdaeda9dda490c71afd021fc8886a79379532 Mon Sep 17 00:00:00 2001 From: Max Date: Fri, 27 Mar 2026 15:46:01 +0800 Subject: [PATCH] refactor(workflows): remove license root certificate injection from build process - Eliminated the steps for injecting commercial license root certificates from GitHub Secrets in both Linux and macOS workflows, streamlining the build process. - Updated the `inspect` command to load commercial license information directly, enhancing the application's licensing capabilities without relying on external secrets during the build. --- .github/workflows/release-linux.yml | 13 ----- .github/workflows/release-macos.yml | 14 ----- cmd/inspect.go | 1 + commercial/commercial_test.go | 60 ++++++++++++++++++++ commercial/roots/root-ca-1.pem | 23 ++++---- commercial/roots/root-ca-2.pem | 17 ++++-- commercial/testdata/test-intermediate-ca.pem | 14 +++++ commercial/testdata/test-license.pem | 34 +++++++++++ 8 files changed, 133 insertions(+), 43 deletions(-) create mode 100644 commercial/testdata/test-intermediate-ca.pem create mode 100644 commercial/testdata/test-license.pem diff --git a/.github/workflows/release-linux.yml b/.github/workflows/release-linux.yml index 09e2b85b..db057837 100644 --- a/.github/workflows/release-linux.yml +++ b/.github/workflows/release-linux.yml @@ -35,9 +35,6 @@ jobs: aws configure set default.s3.endpoint_url https://$R2_ACCOUNT_ID.r2.cloudflarestorage.com - name: Build - env: - ROOT_CA_1: ${{ secrets.YAO_ROOT_CA_1_PEM }} - ROOT_CA_2: ${{ secrets.YAO_ROOT_CA_2_PEM }} run: | export PATH=$PATH:/github/home/go/bin @@ -51,16 +48,6 @@ jobs: git clone https://github.com/yaoapp/yao-init.git /app/yao-init git clone https://github.com/yaoapp/yao.git /app/yao - # Inject commercial license root certificates from GitHub Secrets - if [ -n "$ROOT_CA_1" ]; then - echo "$ROOT_CA_1" | base64 -d > /app/yao/commercial/roots/root-ca-1.pem - echo "Injected root-ca-1.pem" - fi - if [ -n "$ROOT_CA_2" ]; then - echo "$ROOT_CA_2" | base64 -d > /app/yao/commercial/roots/root-ca-2.pem - echo "Injected root-ca-2.pem" - fi - # Extract libv8 files=$(find /app/v8go -name "libv8*.zip") for file in $files; do diff --git a/.github/workflows/release-macos.yml b/.github/workflows/release-macos.yml index d64835ef..a6846134 100644 --- a/.github/workflows/release-macos.yml +++ b/.github/workflows/release-macos.yml @@ -105,20 +105,6 @@ jobs: rm -f share/const.go.bak grep 'const VERSION' share/const.go - - name: Inject License Root Certificates - env: - ROOT_CA_1: ${{ secrets.YAO_ROOT_CA_1_PEM }} - ROOT_CA_2: ${{ secrets.YAO_ROOT_CA_2_PEM }} - run: | - if [ -n "$ROOT_CA_1" ]; then - echo "$ROOT_CA_1" | base64 -d > commercial/roots/root-ca-1.pem - echo "Injected root-ca-1.pem" - fi - if [ -n "$ROOT_CA_2" ]; then - echo "$ROOT_CA_2" | base64 -d > commercial/roots/root-ca-2.pem - echo "Injected root-ca-2.pem" - fi - - name: Setup Go uses: actions/setup-go@v5 with: diff --git a/cmd/inspect.go b/cmd/inspect.go index 1cf7ef11..fbf96059 100644 --- a/cmd/inspect.go +++ b/cmd/inspect.go @@ -16,6 +16,7 @@ var inspectCmd = &cobra.Command{ Long: L("Show app configure"), Run: func(cmd *cobra.Command, args []string) { Boot() + commercial.Load(config.Conf.Root, "yao") engine.InspectExtTools() res := maps.Map{ "version": share.VERSION, diff --git a/commercial/commercial_test.go b/commercial/commercial_test.go index 7339f4a5..45809303 100644 --- a/commercial/commercial_test.go +++ b/commercial/commercial_test.go @@ -2,6 +2,7 @@ package commercial import ( "crypto/x509" + _ "embed" "math/big" "os" "path/filepath" @@ -10,6 +11,12 @@ import ( "time" ) +//go:embed testdata/test-intermediate-ca.pem +var testIntermediateCAPEM []byte + +//go:embed testdata/test-license.pem +var testLicensePEM []byte + // withTestRootPool temporarily replaces the root pool and revocation list // for testing, restoring originals on cleanup. func withTestRootPool(t *testing.T, ca *testCA, revoked []*big.Int) { @@ -419,6 +426,59 @@ func TestDefaultLicenseAndHelpers(t *testing.T) { } } +// TestRealChainIntermediate verifies a certificate signed by a real test intermediate CA, +// which in turn is signed by the real Root CA 1 embedded in the binary. +// Uses testdata/test-intermediate-ca.pem and testdata/test-license.pem generated by +// /Volumes/DATA/Work/Yaobots/keys/gen-test-certs.go. +func TestRealChainIntermediate(t *testing.T) { + // Use the real embedded root pool (not overridden) + dir := t.TempDir() + if err := os.WriteFile(filepath.Join(dir, "license.pem"), testLicensePEM, 0644); err != nil { + t.Fatal(err) + } + + License = DefaultLicense() + Load(dir, "yao") + + if !License.Valid { + t.Fatalf("expected Valid=true with real chain, got error: %s", License.Error) + } + if License.Edition != "enterprise" { + t.Fatalf("expected Edition=enterprise, got %s", License.Edition) + } + if !License.HasProduct("yao") { + t.Fatalf("expected HasProduct(yao)=true, got products: %v", License.Product) + } + if !License.Permissions.AllowBrandingRemoval { + t.Fatal("expected AllowBrandingRemoval=true") + } + if !License.Permissions.AllowWhiteLabel { + t.Fatal("expected AllowWhiteLabel=true") + } + if !License.IsLevel("enterprise") { + t.Fatalf("expected IsLevel(enterprise)=true, edition=%s", License.Edition) + } +} + +// TestRealIntermediateCACert parses the embedded test intermediate CA cert +// and verifies it is signed by the real Root CA 1. +func TestRealIntermediateCACert(t *testing.T) { + intCert, err := ParsePEMChain(testIntermediateCAPEM) + if err != nil || len(intCert) == 0 { + t.Fatalf("failed to parse test intermediate CA: %v", err) + } + + opts := x509.VerifyOptions{ + Roots: RootPool(), + CurrentTime: time.Now(), + } + // Intermediate CA certs are not end-entity; relax KeyUsages check + opts.KeyUsages = []x509.ExtKeyUsage{x509.ExtKeyUsageAny} + if _, err := intCert[0].Verify(opts); err != nil { + t.Fatalf("test intermediate CA not verified by real root pool: %v", err) + } +} + func TestCertsSubdirectoryFallback(t *testing.T) { root, err := generateRootCA("Test Root CA", 10*365*24*time.Hour) if err != nil { diff --git a/commercial/roots/root-ca-1.pem b/commercial/roots/root-ca-1.pem index d8d9cd9c..3d631d68 100644 --- a/commercial/roots/root-ca-1.pem +++ b/commercial/roots/root-ca-1.pem @@ -1,14 +1,13 @@ -----BEGIN CERTIFICATE----- -MIICFzCCAZygAwIBAgIQYJYI6zEyHfyDlfFW2p4NHDAKBggqhkjOPQQDAzBLMQsw -CQYDVQQGEwJDTjEhMB8GA1UEChMYSW5maW5pdGUgV2lzZG9tIFNvZnR3YXJlMRkw -FwYDVQQDExBZYW8gVGVzdCBSb290IENBMB4XDTI2MDMyNzAzMzYxMVoXDTM2MDMy -NDA0MzYxMVowSzELMAkGA1UEBhMCQ04xITAfBgNVBAoTGEluZmluaXRlIFdpc2Rv -bSBTb2Z0d2FyZTEZMBcGA1UEAxMQWWFvIFRlc3QgUm9vdCBDQTB2MBAGByqGSM49 -AgEGBSuBBAAiA2IABNe4Y3nl17lCgK3dZaGFYPdeutdm/hdprjwynJPfGBnw84oE -UBIgm7Nd5hpM57xZak9oH4ol58sOTxjWL492JWX+jU9pRUYn042HA4imSmmrxzP3 -83m8Kn9VcYSEKPJzmKNFMEMwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYB -Af8CAQEwHQYDVR0OBBYEFGh4E/o55y4xR3qa7ZUSIVoxpHdlMAoGCCqGSM49BAMD -A2kAMGYCMQDLhwvg8SDmMiwHCejwtLBozFLcdkys/MoFVnueUE1RAQo1G0CitB/y -UJaYwCnV3j0CMQDe09TLfSA/69XDsv4ueNq9UtY9+ysEzkD2zxupOL1MYSPGNN0a -/ct7CLnLDOnRsN8= +MIICATCCAYegAwIBAgIBATAKBggqhkjOPQQDAzBIMQswCQYDVQQGEwJDTjEhMB8G +A1UEChMYSW5maW5pdGUgV2lzZG9tIFNvZnR3YXJlMRYwFAYDVQQDEw1ZYW8gUm9v +dCBDQSAxMB4XDTI2MDMyNzA2MzYxMloXDTM2MDMyNDA3MzYxMlowSDELMAkGA1UE +BhMCQ04xITAfBgNVBAoTGEluZmluaXRlIFdpc2RvbSBTb2Z0d2FyZTEWMBQGA1UE +AxMNWWFvIFJvb3QgQ0EgMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABDg0J9BxEjOn +Os5D7i3fzFxFOlLR13nanGIjde3bqaohZoD7fCGtfVd5+2vq7y/UOQRAvbu5/RzK +e1S9LFlWjFppdpgbeegd0dMCDEe/9tJknAO35MpWCJxmU7f3Jo4QE6NFMEMwDgYD +VR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQIwHQYDVR0OBBYEFB6XvPEQ +D+g1yTpwyPj3Quwu9wuXMAoGCCqGSM49BAMDA2gAMGUCMFc2K+Xggn5GRo181pAU +aU43Sud8kyXlOuMMpQ/+mfqVNKJhPN75VditQoGiau8VjQIxAO4lJGpuG8f/j4mE +6WaF1x4x45GKc6zaHtgpVUTaX2FazAqkZgSYy57Ipnx0UWrD+A== -----END CERTIFICATE----- diff --git a/commercial/roots/root-ca-2.pem b/commercial/roots/root-ca-2.pem index 9e45480f..cbb88b0d 100644 --- a/commercial/roots/root-ca-2.pem +++ b/commercial/roots/root-ca-2.pem @@ -1,4 +1,13 @@ ------BEGIN PLACEHOLDER----- -This is a development placeholder. The real backup root certificate will be -injected by the release workflow via GitHub Secrets before compilation. ------END PLACEHOLDER----- +-----BEGIN CERTIFICATE----- +MIICATCCAYegAwIBAgIBAjAKBggqhkjOPQQDAzBIMQswCQYDVQQGEwJDTjEhMB8G +A1UEChMYSW5maW5pdGUgV2lzZG9tIFNvZnR3YXJlMRYwFAYDVQQDEw1ZYW8gUm9v +dCBDQSAyMB4XDTI2MDMyNzA2MzYxMloXDTM2MDMyNDA3MzYxMlowSDELMAkGA1UE +BhMCQ04xITAfBgNVBAoTGEluZmluaXRlIFdpc2RvbSBTb2Z0d2FyZTEWMBQGA1UE +AxMNWWFvIFJvb3QgQ0EgMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABB01XlJON6el +vpif5oCD4Mmdvj5muXeq02ZGHSWSrqrxkzUbCbI5LpwURiGObOVnGMw2MT76hW0P +Eq28XDTiXxnVqrjkE95ppl5npgnqMv3PTODizkak2HSXqwuIESLip6NFMEMwDgYD +VR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQIwHQYDVR0OBBYEFNHmPR9D +aXyJZQng5BcwhaB9H9CsMAoGCCqGSM49BAMDA2gAMGUCMQDkQlbGE1yZq7cLele8 +4S+RiYhj3sTsZejU5215f0doOfDka18iv5BeclELP2aQOeQCMFqfeeSKS9SFrHly +SRfZV9o/qxQM3i9EgV1l/D7T9qzPZWR2YcTUSS8TTcwxyIiLAA== +-----END CERTIFICATE----- diff --git a/commercial/testdata/test-intermediate-ca.pem b/commercial/testdata/test-intermediate-ca.pem new file mode 100644 index 00000000..a2a09477 --- /dev/null +++ b/commercial/testdata/test-intermediate-ca.pem @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICLzCCAbSgAwIBAgICIykwCgYIKoZIzj0EAwMwSDELMAkGA1UEBhMCQ04xITAf +BgNVBAoTGEluZmluaXRlIFdpc2RvbSBTb2Z0d2FyZTEWMBQGA1UEAxMNWWFvIFJv +b3QgQ0EgMTAeFw0yNjAzMjcwNjQyNTlaFw0yODAzMjYwNzQyNTlaMFMxCzAJBgNV +BAYTAkNOMSEwHwYDVQQKExhJbmZpbml0ZSBXaXNkb20gU29mdHdhcmUxITAfBgNV +BAMTGFlhbyBUZXN0IEludGVybWVkaWF0ZSBDQTB2MBAGByqGSM49AgEGBSuBBAAi +A2IABHG2U+9ScPK/NBfGW3jgg8fNVH/NfGcPOkypKHonsIad1fG4H+kUtEyyQTvP +4of6FO8FmnvyezMdtaEPlUxRLmYPW9dqsnCZswZasgQLOd5b+qxe4bFY86yla2Iq +HxWIyKNmMGQwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYD +VR0OBBYEFHoGH8BliDziOpSBraPs5+ehyWBMMB8GA1UdIwQYMBaAFB6XvPEQD+g1 +yTpwyPj3Quwu9wuXMAoGCCqGSM49BAMDA2kAMGYCMQCkN/W+unUuHyP/2phruVv4 +itASDUZfm3ZDGS450ixZO9OMQZ9t/dNv1HyfN0M9wCMCMQDoYKwveqllF7XvSPQp +fBfRbxsR+t8LpJqzNXMGgzUpKuZ/KLBAjnbZgwCCGCR1zN0= +-----END CERTIFICATE----- diff --git a/commercial/testdata/test-license.pem b/commercial/testdata/test-license.pem new file mode 100644 index 00000000..6c525429 --- /dev/null +++ b/commercial/testdata/test-license.pem @@ -0,0 +1,34 @@ +-----BEGIN CERTIFICATE----- +MIIDSzCCAtGgAwIBAgIDAV+RMAoGCCqGSM49BAMDMFMxCzAJBgNVBAYTAkNOMSEw +HwYDVQQKExhJbmZpbml0ZSBXaXNkb20gU29mdHdhcmUxITAfBgNVBAMTGFlhbyBU +ZXN0IEludGVybWVkaWF0ZSBDQTAeFw0yNjAzMjcwNjQyNTlaFw0yNzAzMjcwNzQy +NTlaMD4xCzAJBgNVBAYTAkNOMRkwFwYDVQQKExBZYW8gQXBwIFRlc3QgT3JnMRQw +EgYDVQQDEwtZYW8gRGV2IEFwcDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABLBN +Ikb7MXULLpHymC2qV2YjB2pbUjuB7hP6tQa/5aN82o5W7lxMUF2jP4kuptMeaiXj +QyKrtlhDWZzAJ/HshhmjggGnMIIBozAOBgNVHQ8BAf8EBAMCB4AwDwYDVR0lBAgw +BgYEVR0lADAfBgNVHSMEGDAWgBR6Bh/AZYg84jqUga2j7OfnoclgTDAaBgNVHREE +EzARgQ9kZXZAeWFvYXBwcy5jb20wFQYKKwYBBAH1ewEBAQQHeWFvLHRhaTAYBgor +BgEEAfV7AQECBAplbnRlcnByaXNlMA8GCisGAQQB9XsBAgEEATAwDwYKKwYBBAH1 +ewECAgQBMDAPBgorBgEEAfV7AQIDBAEwMA8GCisGAQQB9XsBAgQEATAwDwYKKwYB +BAH1ewECBQQBMDAPBgorBgEEAfV7AQIGBAEwMBIGCisGAQQB9XsBAwEEBHRydWUw +EgYKKwYBBAH1ewEDAgQEdHJ1ZTASBgorBgEEAfV7AQMDBAR0cnVlMBIGCisGAQQB +9XsBAwQEBHRydWUwEgYKKwYBBAH1ewEDBQQEdHJ1ZTASBgorBgEEAfV7AQMGBAR0 +cnVlMBcGCisGAQQB9XsBAwcECWRlZGljYXRlZDAbBgorBgEEAfV7AQQCBA1URVNU +LTIwMjYtMDAxMAoGCCqGSM49BAMDA2gAMGUCMDKJ9oL04HJa0Djh5PbB/bEDEpZA +nS/UWyfaXCbgqQeI+rIhjIXFsEC9CXeFXfa5iwIxAKmTybVyE0QkIQqEifB50LLy +8FXcL1owzKWB5JHn2rTVGr2cSf2SrBQJMefFWiLEUQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICLzCCAbSgAwIBAgICIykwCgYIKoZIzj0EAwMwSDELMAkGA1UEBhMCQ04xITAf +BgNVBAoTGEluZmluaXRlIFdpc2RvbSBTb2Z0d2FyZTEWMBQGA1UEAxMNWWFvIFJv +b3QgQ0EgMTAeFw0yNjAzMjcwNjQyNTlaFw0yODAzMjYwNzQyNTlaMFMxCzAJBgNV +BAYTAkNOMSEwHwYDVQQKExhJbmZpbml0ZSBXaXNkb20gU29mdHdhcmUxITAfBgNV +BAMTGFlhbyBUZXN0IEludGVybWVkaWF0ZSBDQTB2MBAGByqGSM49AgEGBSuBBAAi +A2IABHG2U+9ScPK/NBfGW3jgg8fNVH/NfGcPOkypKHonsIad1fG4H+kUtEyyQTvP +4of6FO8FmnvyezMdtaEPlUxRLmYPW9dqsnCZswZasgQLOd5b+qxe4bFY86yla2Iq +HxWIyKNmMGQwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYD +VR0OBBYEFHoGH8BliDziOpSBraPs5+ehyWBMMB8GA1UdIwQYMBaAFB6XvPEQD+g1 +yTpwyPj3Quwu9wuXMAoGCCqGSM49BAMDA2kAMGYCMQCkN/W+unUuHyP/2phruVv4 +itASDUZfm3ZDGS450ixZO9OMQZ9t/dNv1HyfN0M9wCMCMQDoYKwveqllF7XvSPQp +fBfRbxsR+t8LpJqzNXMGgzUpKuZ/KLBAjnbZgwCCGCR1zN0= +-----END CERTIFICATE-----