From 4289429adbd619ba718e231de0d43ce5f9b4e018 Mon Sep 17 00:00:00 2001 From: dortam888 Date: Sun, 19 May 2024 03:53:25 +0300 Subject: [PATCH 1/7] changing valid package types to supported types in Xray. Adding hugging face and oci and remove unsupported types --- .../resource/resource_xray_custom_issue.go | 25 ++++++------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/pkg/xray/resource/resource_xray_custom_issue.go b/pkg/xray/resource/resource_xray_custom_issue.go index 195db066..97c3f6e2 100644 --- a/pkg/xray/resource/resource_xray_custom_issue.go +++ b/pkg/xray/resource/resource_xray_custom_issue.go @@ -17,37 +17,28 @@ import ( var validPackageTypes = []string{ "alpine", - "bower", + //"bower", "cargo", - "chef", - "cocoapods", "composer", "conan", "conda", "cran", "debian", "docker", - "gems", "generic", - "gitlfs", "go", - "gradle", - "helm", - "ivy", + //"gradle", + "huggingface", + //"ivy", "maven", "npm", "nuget", - "opkg", - "p2", - "puppet", + "oci", "pypi", "rpm", - "sbt", - "swift", - "terraform", - "terraformbackend", - "vagrant", - "vcs", + "rubygems", + //"sbt", + //"terraformbe", } type VulnerableRange struct { From 7d128a45942035b1d1280f937b3559f11f2c769a Mon Sep 17 00:00:00 2001 From: dortam888 Date: Sun, 19 May 2024 07:09:16 +0300 Subject: [PATCH 2/7] adding package support for security policy. Added package_name, package_type and package_versions with pack and unpack and also added rules for diff --- pkg/xray/resource/policies.go | 15 ++++++++ .../resource/resource_xray_security_policy.go | 36 +++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/pkg/xray/resource/policies.go b/pkg/xray/resource/policies.go index cd421d73..13bfa9d0 100644 --- a/pkg/xray/resource/policies.go +++ b/pkg/xray/resource/policies.go @@ -203,6 +203,9 @@ type PolicyRuleCriteria struct { MaliciousPackage bool `json:"malicious_package,omitempty"` VulnerabilityIds []string `json:"vulnerability_ids,omitempty"` Exposures *PolicyExposures `json:"exposures,omitempty"` + PackageName string `json:"package_name,omitempty"` + PackageType string `json:"package_type,omitempty"` + PackageVersions []string `json:"package_versions,omitempty"` // We use pointer for CVSSRange to address nil-verification for non-primitive types. // Unlike primitive types, when the non-primitive type in the struct is set // to nil, the empty key will be created in the JSON body anyway. @@ -316,6 +319,15 @@ func unpackSecurityCriteria(tfCriteria map[string]interface{}) *PolicyRuleCriter if _, ok := tfCriteria["exposures"]; ok { criteria.Exposures = unpackExposures(tfCriteria["exposures"].([]interface{})) } + if v, ok := tfCriteria["package_name"]; ok { + criteria.PackageName = v.(string) + } + if v, ok := tfCriteria["package_type"]; ok { + criteria.PackageType = v.(string) + } + if v, ok := tfCriteria["package_versions"]; ok { + criteria.PackageVersions = sdk.CastToStringArr(v.(*schema.Set).List()) + } // This is also picky about not allowing empty values to be set cvss := unpackCVSSRange(tfCriteria["cvss_range"].([]interface{})) if cvss == nil { @@ -620,6 +632,9 @@ func packSecurityCriteria(criteria *PolicyRuleCriteria) []interface{} { m["fix_version_dependant"] = criteria.FixVersionDependant m["malicious_package"] = criteria.MaliciousPackage m["exposures"] = packExposures(criteria.Exposures) + m["package_name"] = criteria.PackageName + m["package_type"] = criteria.PackageType + m["package_versions"] = criteria.PackageVersions return []interface{}{m} } diff --git a/pkg/xray/resource/resource_xray_security_policy.go b/pkg/xray/resource/resource_xray_security_policy.go index 2d79b4d9..4a83c4c3 100644 --- a/pkg/xray/resource/resource_xray_security_policy.go +++ b/pkg/xray/resource/resource_xray_security_policy.go @@ -106,6 +106,28 @@ func ResourceXraySecurityPolicyV2() *schema.Resource { }, }, }, + "package_name": { + Type: schema.TypeString, + Optional: true, + Description: "The package name to create a rule for", + }, + "package_type": { + Type: schema.TypeString, + Optional: true, + Description: "The package type to create a rule for", + ValidateDiagFunc: validator.StringInSlice(true, validPackageTypes...), + }, + "package_versions": { + Type: schema.TypeSet, + Optional: true, + Description: "package versions to apply the rule on can be (,) for any version or a open range (1,4) or closed [1,4] or one version [1]", + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateDiagFunc: validation.ToDiagFunc( + validation.StringMatch(regexp.MustCompile(`((^(\(|\[)((\d+\.)?(\d+\.)?(\*|\d+)|(\s*))\,((\d+\.)?(\d+\.)?(\*|\d+)|(\s*))(\)|\])$|^\[(\d+\.)?(\d+\.)?(\*|\d+)\]$))`), "invalid Range, must be one of the follows: Any Version: (,) or Speciific Version: [1.2], [3] or Range: (1,), [,1.2.3], (4.5.0,6.5.2]"), + ), + }, + }, } return &schema.Resource{ @@ -144,6 +166,10 @@ var criteriaMaliciousPkgDiff = func(ctx context.Context, diff *schema.ResourceDi vulnerabilityIDs := criterion["vulnerability_ids"].(*schema.Set).List() maliciousPackage := criterion["malicious_package"].(bool) exposures := criterion["exposures"].([]interface{}) + package_name := criterion["package_name"].(string) + package_type := criterion["package_type"].(string) + package_versions := criterion["package_versions"].(*schema.Set).List() + isPackageSet := len(package_name) > 0 || len(package_type) > 0 || len(package_versions) > 0 //if one of them is not defined the API will return an error guiding which one is missing if len(exposures) > 0 && maliciousPackage || (len(exposures) > 0 && len(cvssRange) > 0) || (len(exposures) > 0 && len(minSeverity) > 0) || (len(exposures) > 0 && len(vulnerabilityIDs) > 0) { @@ -165,5 +191,15 @@ var criteriaMaliciousPkgDiff = func(ctx context.Context, diff *schema.ResourceDi return fmt.Errorf("vulnerability_ids can't be set together with with malicious_package, min_severity, cvss_range and exposures") } + if (isPackageSet && len(vulnerabilityIDs) > 0) || (isPackageSet && maliciousPackage) || + (isPackageSet && len(cvssRange) > 0) || (isPackageSet && len(minSeverity) > 0) || + (isPackageSet && len(exposures) > 0) { + return fmt.Errorf("package_name, package_type and package versions can't be set together with with vulnerability_ids, malicious_package, min_severity, cvss_range and exposures") + } + + if isPackageSet && fixVersionDependant { + return fmt.Errorf("package type policy must be set to false if malicious_package is true") + } + return nil } From 1a5debba16537836e6a715792d5c7ec0737263a2 Mon Sep 17 00:00:00 2001 From: dortam888 Date: Sun, 19 May 2024 07:10:55 +0300 Subject: [PATCH 3/7] adding tests for package type policy. Check invalid versions range and general creation --- .../resource_xray_security_policy_test.go | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/pkg/xray/resource/resource_xray_security_policy_test.go b/pkg/xray/resource/resource_xray_security_policy_test.go index 17cdaae6..248d34bb 100644 --- a/pkg/xray/resource/resource_xray_security_policy_test.go +++ b/pkg/xray/resource/resource_xray_security_policy_test.go @@ -20,6 +20,7 @@ const criteriaTypeSeverity = "severity" const criteriaTypeMaliciousPkg = "malicious_package" const criteriaTypeVulnerabilityIds = "vulnerability_ids" const criteriaTypeExposures = "exposures" +const criteriaTypePackageName = "package_name" var testDataSecurity = map[string]string{ "resource_name": "", @@ -760,6 +761,69 @@ func TestAccSecurityPolicy_exposures(t *testing.T) { }) } +func TestAccSecurityPolicy_Packages(t *testing.T) { + _, fqrn, resourceName := testutil.MkNames("policy-", "xray_security_policy") + testData := sdk.MergeMaps(testDataSecurity) + + testData["resource_name"] = resourceName + testData["policy_name"] = fmt.Sprintf("terraform-security-policy-10-%d", testutil.RandomInt()) + testData["rule_name"] = fmt.Sprintf("test-security-rule-10-%d", testutil.RandomInt()) + testData["block_unscanned"] = "false" + testData["block_active"] = "false" + testData["package_name"] = "nuget:RazorEngine" + testData["package_type"] = "NuGet" + testData["package_version_1"] = "(1.2.3,3.10.2)" + testData["package_version_2"] = "[3.11,)" + testData["package_version_3"] = "[4.0.0]" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + CheckDestroy: acctest.VerifyDeleted(fqrn, acctest.CheckPolicy), + ProtoV6ProviderFactories: acctest.ProtoV6MuxProviderFactories, + Steps: []resource.TestStep{ + { + Config: util.ExecuteTemplate(fqrn, securityPolicyPackages, testData), + Check: verifySecurityPolicy(fqrn, testData, criteriaTypePackageName), + }, + { + ResourceName: fqrn, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccSecurityPolicy_PackagesIncorrectVersionRangeFails(t *testing.T) { + _, fqrn, resourceName := testutil.MkNames("policy-", "xray_security_policy") + testData := sdk.MergeMaps(testDataSecurity) + + for _, invalidVersionRange := range []string{"3.10.0", "[3,,4]", "(1,latest)", "[1.0.0.0]"} { + testData["resource_name"] = resourceName + testData["policy_name"] = fmt.Sprintf("terraform-security-policy-10-%d", testutil.RandomInt()) + testData["rule_name"] = fmt.Sprintf("test-security-rule-10-%d", testutil.RandomInt()) + testData["block_unscanned"] = "false" + testData["block_active"] = "false" + testData["package_name"] = "nuget://RazorEngine" + testData["package_type"] = "nuget" + testData["package_version_1"] = invalidVersionRange + testData["package_version_2"] = "(3.2.1,)" + testData["package_version_3"] = "[3.2.1,]" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + CheckDestroy: acctest.VerifyDeleted(fqrn, acctest.CheckPolicy), + ProtoV6ProviderFactories: acctest.ProtoV6MuxProviderFactories, + Steps: []resource.TestStep{ + { + Config: util.ExecuteTemplate(fqrn, securityPolicyPackages, testData), + ExpectError: regexp.MustCompile("invalid value for package_versions"), + }, + }, + }) + } +} + func testAccXraySecurityPolicy_badSecurityType(name, description, ruleName string, rangeTo int) string { return fmt.Sprintf(` resource "xray_security_policy" "test" { @@ -859,6 +923,14 @@ func verifySecurityPolicy(fqrn string, testData map[string]string, criteriaType resource.TestCheckResourceAttr(fqrn, "rule.0.criteria.0.exposures.0.iac", testData["exposures_iac"]), ) } + if criteriaType == criteriaTypePackageName { + return resource.ComposeTestCheckFunc( + commonCheckList, + resource.TestCheckResourceAttr(fqrn, "rule.0.criteria.0.package_name", testData["package_name"]), + resource.TestCheckResourceAttr(fqrn, "rule.0.criteria.0.package_type", testData["package_type"]), + resource.TestCheckTypeSetElemAttr(fqrn, "rule.0.criteria.0.package_versions.*", testData["package_version_1"]), + ) + } return nil } @@ -1168,3 +1240,30 @@ const securityPolicyMaliciousPkgFixVersionDep = `resource "xray_security_policy" } } }` + +const securityPolicyPackages = `resource "xray_security_policy" "{{ .resource_name }}" { + name = "{{ .policy_name }}" + description = "{{ .policy_description }}" + type = "security" + rule { + name = "{{ .rule_name }}" + priority = 1 + criteria { + package_name = "{{ .package_name }}" + package_type = "{{ .package_type }}" + package_versions = ["{{ .package_version_1 }}", "{{ .package_version_2 }}", "{{ .package_version_3 }}"] + } + actions { + block_release_bundle_distribution = {{ .block_release_bundle_distribution }} + fail_build = {{ .fail_build }} + notify_watch_recipients = {{ .notify_watch_recipients }} + notify_deployer = {{ .notify_deployer }} + create_ticket_enabled = {{ .create_ticket_enabled }} + build_failure_grace_period_in_days = {{ .grace_period_days }} + block_download { + unscanned = {{ .block_unscanned }} + active = {{ .block_active }} + } + } + } +}` From 9e398e249ae175ee700485e491399f35cfe214dd Mon Sep 17 00:00:00 2001 From: dortam888 Date: Thu, 23 May 2024 04:37:38 +0300 Subject: [PATCH 4/7] seperate lists for packages and custom issues. fix diff message --- pkg/xray/resource/policies.go | 21 +++++++++++++++++++ .../resource/resource_xray_custom_issue.go | 10 ++++----- .../resource/resource_xray_security_policy.go | 4 ++-- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/pkg/xray/resource/policies.go b/pkg/xray/resource/policies.go index 13bfa9d0..16435680 100644 --- a/pkg/xray/resource/policies.go +++ b/pkg/xray/resource/policies.go @@ -11,6 +11,27 @@ import ( "github.com/jfrog/terraform-provider-shared/validator" ) +var validPackageTypesSupportedXraySecPolicies = []string{ + "alpine", + "cargo", + "composer", + "conan", + "conda", + "cran", + "debian", + "docker", + "generic", + "go", + "huggingface", + "maven", + "npm", + "nuget", + "oci", + "pypi", + "rpm", + "rubygems", +} + var commonActionsSchema = map[string]*schema.Schema{ "webhooks": { Type: schema.TypeSet, diff --git a/pkg/xray/resource/resource_xray_custom_issue.go b/pkg/xray/resource/resource_xray_custom_issue.go index 97c3f6e2..db0a770a 100644 --- a/pkg/xray/resource/resource_xray_custom_issue.go +++ b/pkg/xray/resource/resource_xray_custom_issue.go @@ -17,7 +17,7 @@ import ( var validPackageTypes = []string{ "alpine", - //"bower", + "bower", "cargo", "composer", "conan", @@ -27,9 +27,9 @@ var validPackageTypes = []string{ "docker", "generic", "go", - //"gradle", + "gradle", "huggingface", - //"ivy", + "ivy", "maven", "npm", "nuget", @@ -37,8 +37,8 @@ var validPackageTypes = []string{ "pypi", "rpm", "rubygems", - //"sbt", - //"terraformbe", + "sbt", + "terraformbe", } type VulnerableRange struct { diff --git a/pkg/xray/resource/resource_xray_security_policy.go b/pkg/xray/resource/resource_xray_security_policy.go index 4a83c4c3..e0bcb52c 100644 --- a/pkg/xray/resource/resource_xray_security_policy.go +++ b/pkg/xray/resource/resource_xray_security_policy.go @@ -115,7 +115,7 @@ func ResourceXraySecurityPolicyV2() *schema.Resource { Type: schema.TypeString, Optional: true, Description: "The package type to create a rule for", - ValidateDiagFunc: validator.StringInSlice(true, validPackageTypes...), + ValidateDiagFunc: validator.StringInSlice(true, validPackageTypesSupportedXraySecPolicies...), }, "package_versions": { Type: schema.TypeSet, @@ -198,7 +198,7 @@ var criteriaMaliciousPkgDiff = func(ctx context.Context, diff *schema.ResourceDi } if isPackageSet && fixVersionDependant { - return fmt.Errorf("package type policy must be set to false if malicious_package is true") + return fmt.Errorf("fix_version_dependant must be set to false if package type policy is used") } return nil From e11ab80424927762706d8cea7166f02ceb75cdd6 Mon Sep 17 00:00:00 2001 From: dortam888 Date: Thu, 23 May 2024 04:41:17 +0300 Subject: [PATCH 5/7] add tests for diff functionality --- .../resource_xray_security_policy_test.go | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/pkg/xray/resource/resource_xray_security_policy_test.go b/pkg/xray/resource/resource_xray_security_policy_test.go index 248d34bb..ac0cab78 100644 --- a/pkg/xray/resource/resource_xray_security_policy_test.go +++ b/pkg/xray/resource/resource_xray_security_policy_test.go @@ -665,6 +665,7 @@ func TestAccSecurityPolicy_conflictingAttributesFail(t *testing.T) { "malicious_package = true", "min_severity = \"High\"", "exposures {\nmin_severity = \"High\" \nsecrets = true \n applications = true \n services = true \n iac = true\n}", + "package_name = \"nuget://RazorEngine\"", } for _, testAttribute := range testAttributes { @@ -824,6 +825,33 @@ func TestAccSecurityPolicy_PackagesIncorrectVersionRangeFails(t *testing.T) { } } +func TestAccSecurityPolicy_createPackagesFail(t *testing.T) { + _, fqrn, resourceName := testutil.MkNames("policy-", "xray_security_policy") + testData := sdk.MergeMaps(testDataSecurity) + + testData["resource_name"] = resourceName + testData["policy_name"] = fmt.Sprintf("terraform-security-policy-6-%d", testutil.RandomInt()) + testData["rule_name"] = fmt.Sprintf("test-security-rule-6-%d", testutil.RandomInt()) + testData["package_name"] = "nuget:RazorEngine" + testData["package_type"] = "NuGet" + testData["package_version_1"] = "(1.2.3,3.10.2)" + testData["package_version_2"] = "[3.11,)" + testData["package_version_3"] = "[4.0.0]" + testData["fix_version_dependant"] = "true" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + CheckDestroy: acctest.VerifyDeleted(fqrn, acctest.CheckPolicy), + ProtoV6ProviderFactories: acctest.ProtoV6MuxProviderFactories, + Steps: []resource.TestStep{ + { + Config: util.ExecuteTemplate(fqrn, securityPolicyPackagesFixVersionDep, testData), + ExpectError: regexp.MustCompile("fix_version_dependant must be set to false if package type policy is used"), + }, + }, + }) +} + func testAccXraySecurityPolicy_badSecurityType(name, description, ruleName string, rangeTo int) string { return fmt.Sprintf(` resource "xray_security_policy" "test" { @@ -1241,6 +1269,34 @@ const securityPolicyMaliciousPkgFixVersionDep = `resource "xray_security_policy" } }` +const securityPolicyPackagesFixVersionDep = `resource "xray_security_policy" "{{ .resource_name }}" { + name = "{{ .policy_name }}" + description = "{{ .policy_description }}" + type = "security" + rule { + name = "{{ .rule_name }}" + priority = 1 + criteria { + package_name = "{{ .package_name }}" + package_type = "{{ .package_type }}" + package_versions = ["{{ .package_version_1 }}", "{{ .package_version_2 }}", "{{ .package_version_3 }}"] + fix_version_dependant = {{ .fix_version_dependant }} + } + actions { + block_release_bundle_distribution = {{ .block_release_bundle_distribution }} + fail_build = {{ .fail_build }} + notify_watch_recipients = {{ .notify_watch_recipients }} + notify_deployer = {{ .notify_deployer }} + create_ticket_enabled = {{ .create_ticket_enabled }} + build_failure_grace_period_in_days = {{ .grace_period_days }} + block_download { + unscanned = {{ .block_unscanned }} + active = {{ .block_active }} + } + } + } +}` + const securityPolicyPackages = `resource "xray_security_policy" "{{ .resource_name }}" { name = "{{ .policy_name }}" description = "{{ .policy_description }}" From 0419f09861c0839159ebd83d48e84807efd9edfe Mon Sep 17 00:00:00 2001 From: dortam888 Date: Thu, 23 May 2024 04:42:27 +0300 Subject: [PATCH 6/7] update documentation --- docs/resources/custom_issue.md | 2 +- docs/resources/security_policy.md | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/resources/custom_issue.md b/docs/resources/custom_issue.md index b2b42bab..99bad675 100644 --- a/docs/resources/custom_issue.md +++ b/docs/resources/custom_issue.md @@ -53,7 +53,7 @@ resource "xray_custom_issue" "my-issue-1" { - `cve` (Block Set, Min: 1) CVE of the custom issue (see [below for nested schema](#nestedblock--cve)) - `description` (String) Description of custom issue - `name` (String) Name of the custom issue. It must not begin with 'xray' (case insensitive) -- `package_type` (String) Package Type of custom issue. Valid values are: alpine, bower, cargo, chef, cocoapods, composer, conan, conda, cran, debian, docker, gems, generic, gitlfs, go, gradle, helm, ivy, maven, npm, nuget, opkg, p2, puppet, pypi, rpm, sbt, swift, terraform, terraformbackend, vagrant, vcs +- `package_type` (String) Package Type of custom issue. Valid values are: alpine, bower, cargo, composer, conan, conda, cran, debian, docker, generic, go, gradle, huggingface, ivy, maven, npm, nuget, oci, pypi, rpm, rubygems, sbt, terraformbe - `provider_name` (String) Provider of custom issue. It must not be 'jfrog' (case insensitive) - `severity` (String) Severity of custom issue. Valid values: Critical, High, Medium, Low, Information - `source` (Block Set, Min: 1) List of sources (see [below for nested schema](#nestedblock--source)) diff --git a/docs/resources/security_policy.md b/docs/resources/security_policy.md index cde950ef..779ab89e 100644 --- a/docs/resources/security_policy.md +++ b/docs/resources/security_policy.md @@ -188,6 +188,9 @@ Optional: - `fix_version_dependant` (Boolean) Default value is `false`. Issues that do not have a fixed version are not generated until a fixed version is available. Must be `false` with `malicious_package` enabled. - `malicious_package` (Boolean) Default value is `false`. Generating a violation on a malicious package. - `min_severity` (String) The minimum security vulnerability severity that will be impacted by the policy. Valid values: `All Severities`, `Critical`, `High`, `Medium`, `Low` +- `package_name` (String) The package name to create a rule for +- `package_type` (String) The package type to create a rule for +- `package_versions` (Set of String) package versions to apply the rule on can be (,) for any version or a open range (1,4) or closed [1,4] or one version [1] - `vulnerability_ids` (Set of String) Creates policy rules for specific vulnerability IDs that you input. You can add multiple vulnerabilities IDs up to 100. CVEs and Xray IDs are supported. Example - CVE-2015-20107, XRAY-2344 From 268bba5452ce2256c291b0b2a2ac2ff00831faf1 Mon Sep 17 00:00:00 2001 From: dortam888 Date: Wed, 29 May 2024 02:32:05 +0300 Subject: [PATCH 7/7] fix typos --- pkg/xray/resource/resource_xray_security_policy.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/xray/resource/resource_xray_security_policy.go b/pkg/xray/resource/resource_xray_security_policy.go index e0bcb52c..3a20dbf8 100644 --- a/pkg/xray/resource/resource_xray_security_policy.go +++ b/pkg/xray/resource/resource_xray_security_policy.go @@ -120,11 +120,11 @@ func ResourceXraySecurityPolicyV2() *schema.Resource { "package_versions": { Type: schema.TypeSet, Optional: true, - Description: "package versions to apply the rule on can be (,) for any version or a open range (1,4) or closed [1,4] or one version [1]", + Description: "package versions to apply the rule on can be (,) for any version or an open range (1,4) or closed [1,4] or one version [1]", Elem: &schema.Schema{ Type: schema.TypeString, ValidateDiagFunc: validation.ToDiagFunc( - validation.StringMatch(regexp.MustCompile(`((^(\(|\[)((\d+\.)?(\d+\.)?(\*|\d+)|(\s*))\,((\d+\.)?(\d+\.)?(\*|\d+)|(\s*))(\)|\])$|^\[(\d+\.)?(\d+\.)?(\*|\d+)\]$))`), "invalid Range, must be one of the follows: Any Version: (,) or Speciific Version: [1.2], [3] or Range: (1,), [,1.2.3], (4.5.0,6.5.2]"), + validation.StringMatch(regexp.MustCompile(`((^(\(|\[)((\d+\.)?(\d+\.)?(\*|\d+)|(\s*))\,((\d+\.)?(\d+\.)?(\*|\d+)|(\s*))(\)|\])$|^\[(\d+\.)?(\d+\.)?(\*|\d+)\]$))`), "invalid Range, must be one of the follows: Any Version: (,) or Specific Version: [1.2], [3] or Range: (1,), [,1.2.3], (4.5.0,6.5.2]"), ), }, },