diff --git a/sdk/manifest.go b/sdk/manifest.go index 1e91bfa82..5331badb3 100644 --- a/sdk/manifest.go +++ b/sdk/manifest.go @@ -62,7 +62,7 @@ type Manifest struct { EncryptionInformation `json:"encryptionInformation"` Payload `json:"payload"` Assertions []Assertion `json:"assertions,omitempty"` - TDFVersion string `json:"tdf_spec_version,omitempty"` + TDFVersion string `json:"schemaVersion,omitempty"` } type attributeObject struct { diff --git a/sdk/tdf.go b/sdk/tdf.go index db919927e..ffb62bb27 100644 --- a/sdk/tdf.go +++ b/sdk/tdf.go @@ -335,10 +335,17 @@ func (s SDK) prepareManifest(ctx context.Context, t *TDFObject, tdfConfig TDFCon version, err := semver.NewVersion(sdkVersion) if err != nil { - return fmt.Errorf("ReadVersion failed:%w", err) + return fmt.Errorf("failed to parse semantic version %q: %w", sdkVersion, err) } - manifest.TDFVersion = version.String() + // Only attempt to set metadata if it's provided + if metadata := strings.TrimSpace(tdfConfig.buildMetadata); metadata != "" { + versionWithMetadata, err := version.SetMetadata(metadata) + if err != nil { + return fmt.Errorf("failed to set build metadata %q: %w", metadata, err) + } + manifest.TDFVersion = versionWithMetadata.String() + } if len(tdfConfig.splitPlan) == 0 && len(tdfConfig.kasInfoList) == 0 { return fmt.Errorf("%w: no key access template specified or inferred", errInvalidKasInfo) diff --git a/sdk/tdf_config.go b/sdk/tdf_config.go index 25f761a85..902ee3774 100644 --- a/sdk/tdf_config.go +++ b/sdk/tdf_config.go @@ -56,6 +56,7 @@ type TDFConfig struct { tdfPrivateKey string metaData string mimeType string + buildMetadata string integrityAlgorithm IntegrityAlgorithm segmentIntegrityAlgorithm IntegrityAlgorithm assertions []AssertionConfig @@ -172,6 +173,14 @@ func WithMetaData(metaData string) TDFOption { } } +// WithBuildMetadata returns an Option that add build metadata to TDF. +func WithBuildMetadata(buildMetadata string) TDFOption { + return func(c *TDFConfig) error { + c.buildMetadata = buildMetadata + return nil + } +} + func WithMimeType(mimeType string) TDFOption { return func(c *TDFConfig) error { c.mimeType = mimeType diff --git a/sdk/tdf_test.go b/sdk/tdf_test.go index fa408c9fd..cadd340a7 100644 --- a/sdk/tdf_test.go +++ b/sdk/tdf_test.go @@ -18,6 +18,7 @@ import ( "testing" "time" + "github.com/Masterminds/semver/v3" "github.com/lestrrat-go/jwx/v2/jwt" "github.com/opentdf/platform/lib/ocrypto" kaspb "github.com/opentdf/platform/protocol/go/kas" @@ -259,6 +260,7 @@ func TestTDF(t *testing.T) { func (s *TDFSuite) Test_SimpleTDF() { metaData := []byte(`{"displayName" : "openTDF go sdk"}`) + buildMetadata := "test.01" attributes := []string{ "https://example.com/attr/Classification/value/S", "https://example.com/attr/Classification/value/X", @@ -290,13 +292,14 @@ func (s *TDFSuite) Test_SimpleTDF() { WithKasInformation(kasURLs...), WithMetaData(string(metaData)), WithDataAttributes(attributes...), + WithBuildMetadata(buildMetadata), ) s.Require().NoError(err) s.InDelta(float64(expectedTdfSize), float64(tdfObj.size), 32.0) } - // test meta data + // test meta data and build meta data { readSeeker, err := os.Open(tdfFilename) s.Require().NoError(err) @@ -323,6 +326,11 @@ func (s *TDFSuite) Test_SimpleTDF() { payloadKey, err := r.UnsafePayloadKeyRetrieval() s.Require().NoError(err) s.Len(payloadKey, kKeySize) + + version, err := semver.NewVersion(r.manifest.TDFVersion) + s.Require().NoError(err) + + s.EqualValues(buildMetadata, version.Metadata()) } // test reader