From 608208ff71b854ed5385ba66c333731c941a0fed Mon Sep 17 00:00:00 2001 From: RahulC-dev Date: Tue, 24 Feb 2026 15:42:58 +0530 Subject: [PATCH] 7787: Add support for parsing allow/deny dependency lists from config file --- internal/upload/batch.go | 33 +++++- internal/upload/batch_test.go | 110 ++++++++++++++++++ .../debricked-config-policies-only.yaml | 54 +++++++++ .../testdata/debricked-config-policies.yaml | 35 ++++++ 4 files changed, 230 insertions(+), 2 deletions(-) create mode 100644 internal/upload/testdata/debricked-config-policies-only.yaml create mode 100644 internal/upload/testdata/debricked-config-policies.yaml diff --git a/internal/upload/batch.go b/internal/upload/batch.go index 0bf23864..4213cd83 100644 --- a/internal/upload/batch.go +++ b/internal/upload/batch.go @@ -322,8 +322,9 @@ type purlConfig struct { } type DebrickedConfig struct { - Overrides []purlConfig `json:"override,omitempty" yaml:"overrides"` - Ignore *IgnoreConfig `json:"ignore,omitempty" yaml:"ignore,omitempty"` + Overrides []purlConfig `json:"override,omitempty" yaml:"overrides"` + Ignore *IgnoreConfig `json:"ignore,omitempty" yaml:"ignore,omitempty"` + Policies *PoliciesConfig `json:"policies,omitempty" yaml:"policies,omitempty"` } // IgnoreConfig matches the structure of the 'ignore' section in YAML @@ -336,6 +337,17 @@ type IgnorePackage struct { Version string `json:"version,omitempty" yaml:"version,omitempty"` } +// PoliciesConfig matches the structure of the 'policies' section in YAML +type PoliciesConfig struct { + Allow *PolicyPackages `json:"allow,omitempty" yaml:"allow,omitempty"` + Deny *PolicyPackages `json:"deny,omitempty" yaml:"deny,omitempty"` +} + +// PolicyPackages contains a list of package identifiers. +type PolicyPackages struct { + Packages []string `json:"packages" yaml:"packages"` +} + type uploadFinish struct { CiUploadId string `json:"ciUploadId"` RepositoryName string `json:"repositoryName"` @@ -387,6 +399,21 @@ func extractIgnore(raw map[string]interface{}) *IgnoreConfig { return nil } +// extractPolicies unmarshals the policies section from raw config +func extractPolicies(raw map[string]interface{}) *PoliciesConfig { + if rawPolicies, ok := raw["policies"]; ok { + policiesYaml, err := yaml.Marshal(rawPolicies) + if err == nil { + var policiesObj PoliciesConfig + if yaml.Unmarshal(policiesYaml, &policiesObj) == nil { + return &policiesObj + } + } + } + + return nil +} + // convertOverrides converts YAML overrides to purlConfig slice func convertOverrides(yamlOverrides []pURLConfigYAML) []purlConfig { var overrides []purlConfig @@ -463,10 +490,12 @@ func GetDebrickedConfig(path string) *DebrickedConfig { } ignore := extractIgnore(raw) + policies := extractPolicies(raw) overrides := convertOverrides(yamlConfig.Overrides) return &DebrickedConfig{ Overrides: overrides, Ignore: ignore, + Policies: policies, } } diff --git a/internal/upload/batch_test.go b/internal/upload/batch_test.go index 16ce2c10..dc4b6abb 100644 --- a/internal/upload/batch_test.go +++ b/internal/upload/batch_test.go @@ -310,3 +310,113 @@ func TestGetDebrickedConfigSingularOverride(t *testing.T) { assert.Nil(t, err) assert.JSONEq(t, string(configJSON), string(expectedJSON)) } + +func TestGetDebrickedConfigPolicies(t *testing.T) { + config := GetDebrickedConfig(filepath.Join("testdata", "debricked-config-policies.yaml")) + configJSON, err := json.Marshal(config) + assert.Nil(t, err) + expectedJSON, err := json.Marshal(DebrickedConfig{ + Overrides: []purlConfig{ + { + PackageURL: "pkg:npm/lodash", + Version: boolOrString{Version: "1.0.0", HasVersion: true}, + FileRegexes: []string{"chart.js-2.6.0.tgz"}, + }, + }, + Ignore: &IgnoreConfig{ + Packages: []IgnorePackage{ + {PURL: "pkg:maven/javax.transaction/jta"}, + {PURL: "pkg:maven/org.quartz-scheduler/quartz"}, + {PURL: "pkg:maven/com.google.guava/guava", Version: "1.1.1"}, + {PURL: "pkg:maven/com.googlecode.json-simple/json-simplea", Version: "1.1.1"}, + {PURL: "pkg:maven/com.fasterxml.jackson.core/jackson-databind"}, + }, + }, + Policies: &PoliciesConfig{ + Allow: &PolicyPackages{ + Packages: []string{ + "pkg:npm/lodash@4.17.21", + "pkg:maven/org.springframework/spring-core@5.3.20", + "react", + "express", + "axios@1.3.0", + "lodash@>=4.17.21,<5.0.0", + "log4j@2.15.0-2.17.1", + }, + }, + Deny: &PolicyPackages{ + Packages: []string{ + "pkg:npm/request", + "colors@<=1.4.0", + "node-ipc@<=9.2.1", + "pkg:pypi/setuptools@<65.0.0", + "pkg:pypi/gpl-restricted-package", + "proprietary-lib", + }, + }, + }, + }) + assert.Nil(t, err) + assert.JSONEq(t, string(configJSON), string(expectedJSON)) +} + +func TestGetDebrickedConfigPoliciesOnly(t *testing.T) { + config := GetDebrickedConfig(filepath.Join("testdata", "debricked-config-policies-only.yaml")) + configJSON, err := json.Marshal(config) + assert.Nil(t, err) + expectedJSON, err := json.Marshal(DebrickedConfig{ + Policies: &PoliciesConfig{ + Allow: &PolicyPackages{ + Packages: []string{ + // PURL format + "pkg:npm/lodash@4.17.21", + "pkg:maven/org.springframework/spring-core@5.3.20", + "pkg:pypi/requests@2.28.0", + "pkg:nuget/Newtonsoft.Json@13.0.1", + "pkg:npm/@angular/core@15.0.0", + // Name only + "react", + "webpack", + "express", + "typescript", + // Name@version + "axios@1.3.0", + "lodash@4.17.21", + "vue@3.2.45", + // Version ranges + "django@>=3.2.0,<5.0.0", + "spring-boot@>=2.7.0,<3.0.0", + "lodash@>=4.17.21,<5.0.0", + "log4j@2.15.0-2.17.1", + // Comparison operators + "pytest@>=7.0.0", + "guava@>=31.0.0", + }, + }, + Deny: &PolicyPackages{ + Packages: []string{ + // PURL format + "pkg:npm/request", + "pkg:npm/event-stream@3.3.6", + "pkg:maven/log4j/log4j@1.2.17", + "pkg:pypi/pycrypto", + "pkg:npm/flatmap-stream", + // Name only + "colors", + "node-ipc", + // Version ranges and constraints + "setuptools@<65.0.0", + "minimist@<1.2.6", + "pillow@<8.3.2", + "log4j@1.0-2.14.1", + "commons-collections@<=3.2.1", + // Comparison operators + "System.Text.Encodings.Web@<4.7.2", + "moment@<=2.29.1", + }, + }, + }, + }) + assert.Nil(t, err) + assert.JSONEq(t, string(configJSON), string(expectedJSON)) +} diff --git a/internal/upload/testdata/debricked-config-policies-only.yaml b/internal/upload/testdata/debricked-config-policies-only.yaml new file mode 100644 index 00000000..e7208036 --- /dev/null +++ b/internal/upload/testdata/debricked-config-policies-only.yaml @@ -0,0 +1,54 @@ +policies: + allow: + packages: + # PURL format (exact package match) + - "pkg:npm/lodash@4.17.21" + - "pkg:maven/org.springframework/spring-core@5.3.20" + - "pkg:pypi/requests@2.28.0" + - "pkg:nuget/Newtonsoft.Json@13.0.1" + - "pkg:npm/@angular/core@15.0.0" + + # Name only (matches all versions, all package managers) + - "react" + - "webpack" + - "express" + - "typescript" + + # Name@version (specific version) + - "axios@1.3.0" + - "lodash@4.17.21" + - "vue@3.2.45" + + # Version ranges (semver style) + - "django@>=3.2.0,<5.0.0" + - "spring-boot@>=2.7.0,<3.0.0" + - "lodash@>=4.17.21,<5.0.0" + - "log4j@2.15.0-2.17.1" + + # Comparison operators + - "pytest@>=7.0.0" + - "guava@>=31.0.0" + + deny: + packages: + # PURL format (exact package match) + - "pkg:npm/request" + - "pkg:npm/event-stream@3.3.6" + - "pkg:maven/log4j/log4j@1.2.17" + - "pkg:pypi/pycrypto" + - "pkg:npm/flatmap-stream" + + # Name only (any version) + - "colors" + - "node-ipc" + + # Version ranges and constraints + - "setuptools@<65.0.0" + - "minimist@<1.2.6" + - "pillow@<8.3.2" + - "log4j@1.0-2.14.1" + - "commons-collections@<=3.2.1" + + # Comparison operators + - "System.Text.Encodings.Web@<4.7.2" + - "moment@<=2.29.1" diff --git a/internal/upload/testdata/debricked-config-policies.yaml b/internal/upload/testdata/debricked-config-policies.yaml new file mode 100644 index 00000000..a8b6ab1d --- /dev/null +++ b/internal/upload/testdata/debricked-config-policies.yaml @@ -0,0 +1,35 @@ +overrides: + - pURL: "pkg:npm/lodash" + version: "1.0.0" + fileRegexes: + - "chart.js-2.6.0.tgz" + +ignore: + packages: + - pURL: "pkg:maven/javax.transaction/jta" + - pURL: "pkg:maven/org.quartz-scheduler/quartz" + - pURL: "pkg:maven/com.google.guava/guava" + version: "1.1.1" + - pURL: "pkg:maven/com.googlecode.json-simple/json-simplea" + version: "1.1.1" + - pURL: "pkg:maven/com.fasterxml.jackson.core/jackson-databind" + +policies: + allow: + packages: + - "pkg:npm/lodash@4.17.21" + - "pkg:maven/org.springframework/spring-core@5.3.20" + - "react" + - "express" + - "axios@1.3.0" + - "lodash@>=4.17.21,<5.0.0" + - "log4j@2.15.0-2.17.1" + + deny: + packages: + - "pkg:npm/request" + - "colors@<=1.4.0" + - "node-ipc@<=9.2.1" + - "pkg:pypi/setuptools@<65.0.0" + - "pkg:pypi/gpl-restricted-package" + - "proprietary-lib"