From 114bb60b13dec500e1f07ddb3c2f85e699a2f4d6 Mon Sep 17 00:00:00 2001 From: Mateusz Urbanek Date: Fri, 1 May 2026 06:29:03 +0200 Subject: [PATCH] fix(spdx): use configured external URL in document namespace Hardcoded `factory.talos.dev` in SPDX document namespace broke deployments where image-factory runs under a different hostname. External URL now threads from service config through SPDXOptions and Builder down to namespace generation. Fixes #440 Signed-off-by: Mateusz Urbanek --- cmd/image-factory/cmd/service.go | 1 + enterprise/spdx/builder/builder.go | 10 +++++++--- enterprise/spdx/builder/spdx.go | 6 +++++- internal/integration/frontend_test.go | 2 +- internal/integration/spdx_test.go | 3 ++- pkg/enterprise/enterprise.go | 1 + pkg/enterprise/enterprise_on.go | 1 + 7 files changed, 18 insertions(+), 6 deletions(-) diff --git a/cmd/image-factory/cmd/service.go b/cmd/image-factory/cmd/service.go index a0960dd..8509aef 100644 --- a/cmd/image-factory/cmd/service.go +++ b/cmd/image-factory/cmd/service.go @@ -192,6 +192,7 @@ func buildEnterprisePlugins( } spdxFrontend, err := enterprise.NewSpdxFrontend(logger, enterprise.SPDXOptions{ + ExternalURL: opts.HTTP.ExternalURL, SchematicFactory: configFactory, ArtifactsManager: artifactsManager, AssetBuilder: assetBuilder, diff --git a/enterprise/spdx/builder/builder.go b/enterprise/spdx/builder/builder.go index fd0bd21..c305d9f 100644 --- a/enterprise/spdx/builder/builder.go +++ b/enterprise/spdx/builder/builder.go @@ -42,21 +42,23 @@ type AuthProvider interface { // Builder orchestrates SPDX extraction and caching. type Builder struct { storage storage.Storage + sf singleflight.Group + authProvider AuthProvider artifactsManager *artifacts.Manager assetBuilder *asset.Builder schematicFactory *schematic.Factory logger *zap.Logger - sf singleflight.Group - authProvider AuthProvider + externalURL string } // Options defines the dependencies for the SPDX builder. type Options struct { Storage storage.Storage + AuthProvider AuthProvider ArtifactsManager *artifacts.Manager SchematicFactory *schematic.Factory AssetBuilder *asset.Builder - AuthProvider AuthProvider + ExternalURL string } // NewBuilder creates a new SPDX bundle builder. @@ -65,6 +67,7 @@ func NewBuilder( opts Options, ) *Builder { return &Builder{ + externalURL: opts.ExternalURL, storage: opts.Storage, artifactsManager: opts.ArtifactsManager, schematicFactory: opts.SchematicFactory, @@ -136,6 +139,7 @@ func (b *Builder) buildBundle(sc *schematicpkg.Schematic, schematicID, versionTa SchematicID: schematicID, TalosVersion: versionTag, Arch: string(arch), + ExternalURL: b.externalURL, Files: []File{}, } diff --git a/enterprise/spdx/builder/spdx.go b/enterprise/spdx/builder/spdx.go index 587e55f..5e2342f 100644 --- a/enterprise/spdx/builder/spdx.go +++ b/enterprise/spdx/builder/spdx.go @@ -41,6 +41,9 @@ type Bundle struct { // Arch is the target architecture (e.g., "amd64"). Arch string + // ExternalURL is the host used in the document namespace (e.g., "factory.sidero.dev"). + ExternalURL string + // Files contains the extracted SPDX files. Files []File } @@ -60,7 +63,8 @@ func BundleToJSON(bundle *Bundle) (io.Reader, int64, error) { SPDXIdentifier: common.ElementID("DOCUMENT"), DocumentName: fmt.Sprintf("talos-%s-%s-%s", bundle.SchematicID, bundle.TalosVersion, bundle.Arch), DocumentNamespace: fmt.Sprintf( - "https://factory.talos.dev/spdx/%s/%s/%s", + "https://%s/spdx/%s/%s/%s", + bundle.ExternalURL, bundle.SchematicID, bundle.TalosVersion, bundle.Arch, diff --git a/internal/integration/frontend_test.go b/internal/integration/frontend_test.go index 7a18702..1a71edf 100644 --- a/internal/integration/frontend_test.go +++ b/internal/integration/frontend_test.go @@ -11,10 +11,10 @@ import ( "net/http" "testing" - "github.com/siderolabs/image-factory/pkg/client" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/siderolabs/image-factory/pkg/client" "github.com/siderolabs/image-factory/pkg/enterprise" schematicpkg "github.com/siderolabs/image-factory/pkg/schematic" ) diff --git a/internal/integration/spdx_test.go b/internal/integration/spdx_test.go index 52b7fa3..9479016 100644 --- a/internal/integration/spdx_test.go +++ b/internal/integration/spdx_test.go @@ -79,7 +79,8 @@ func testSPDXFrontend(ctx context.Context, t *testing.T, baseURL string) { assert.Equal(t, spdx.Version, doc.SPDXVersion) assert.Equal(t, spdx.DataLicense, doc.DataLicense) assert.Contains(t, doc.DocumentName, "talos-"+emptySchematicID) - assert.Contains(t, doc.DocumentNamespace, "https://factory.talos.dev/spdx/"+emptySchematicID) + assert.Contains(t, doc.DocumentNamespace, "https://") + assert.Contains(t, doc.DocumentNamespace, "/spdx/"+emptySchematicID) require.NotNil(t, doc.CreationInfo) assert.NotEmpty(t, doc.CreationInfo.Creators) }) diff --git a/pkg/enterprise/enterprise.go b/pkg/enterprise/enterprise.go index 96a220c..926aa35 100644 --- a/pkg/enterprise/enterprise.go +++ b/pkg/enterprise/enterprise.go @@ -29,6 +29,7 @@ type FrontendPlugin interface { // SPDXOptions holds configuration options for the SPDX frontend. type SPDXOptions struct { + ExternalURL string CacheImageSigner signer.Signer SchematicFactory *schematic.Factory ArtifactsManager *artifacts.Manager diff --git a/pkg/enterprise/enterprise_on.go b/pkg/enterprise/enterprise_on.go index 373edf8..1452fac 100644 --- a/pkg/enterprise/enterprise_on.go +++ b/pkg/enterprise/enterprise_on.go @@ -48,6 +48,7 @@ func NewSpdxFrontend(logger *zap.Logger, opts SPDXOptions) (FrontendPlugin, erro } builder := builder.NewBuilder(logger, builder.Options{ + ExternalURL: opts.ExternalURL, Storage: storage, ArtifactsManager: opts.ArtifactsManager, SchematicFactory: opts.SchematicFactory,