Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 3.1.12 (Jul 23,2026). Tested on JFrog Platform 11.5.11 (Artifactory 7.146.29, Xray 3.143.31, Catalog 1.43.1) with Terraform 1.15.8 and OpenTofu 1.12.5

BUG FIXES:

* resource/xray_custom_curation_condition: Remove the hard-coded `condition_template_id` allow-list that rejected valid platform-supported templates (e.g. `isMalicious`, `NoLicense`, aged-package variants) before the request reached the API. The set of available templates depends on the JFrog Platform version and enabled features, so `condition_template_id` is no longer restricted client-side and parameter validation is deferred to the Xray API for templates the provider does not recognize. Issue: [#432](https://github.com/jfrog/terraform-provider-xray/issues/432)

## 3.1.11(Jun 9, 2026).

BUG FIXES:
Expand Down
31 changes: 17 additions & 14 deletions pkg/xray/resource/resource_xray_custom_curation_condition.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,18 @@ func (v paramValuesJSONValidator) ValidateString(ctx context.Context, req valida
}
}

// Check for empty parameters (required for all templates)
// For templates the provider doesn't know about (e.g. platform/version-specific
// templates such as isMalicious, NoLicense, or aged-package variants), defer
// parameter validation to the Xray API, which is the source of truth for both
// the allowed template IDs and their parameters. The JSON syntax has already
// been validated above.
if conditionTemplateID != "" {
if _, known := conditionTemplateParams[conditionTemplateID]; !known {
return
}
}

// Check for empty parameters (required for all known templates)
if len(paramValues) == 0 {
resp.Diagnostics.AddAttributeError(
req.Path,
Expand Down Expand Up @@ -1105,21 +1116,13 @@ func (r *CustomCurationConditionResource) Schema(ctx context.Context, req resour
},
},
"condition_template_id": schema.StringAttribute{
Required: true,
Description: "One of the IDs of the supported condition templates returned by the list condition templates API.",
Required: true,
Description: "One of the IDs of the supported condition templates returned by the list condition templates API. " +
"The set of available templates depends on the JFrog Platform version and enabled features " +
"(e.g. `isMalicious`, `NoLicense`, aged-package variants), so the value is not restricted to a " +
"fixed list client-side; unsupported templates are rejected by the Xray API.",
Validators: []validator.String{
stringvalidator.LengthAtLeast(1),
stringvalidator.OneOf(
"OpenSSF",
"BannedLabels",
"AllowedLabels",
"SpecificVersions",
"AllowedLicenses",
"BannedLicenses",
"CVECVSSRange",
"isImmature",
"CVEName",
),
},
},
"param_values": schema.StringAttribute{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,34 @@ func TestAccCustomCurationCondition_CVEName_Smoke(t *testing.T) {
})
}

// TestAccCustomCurationCondition_PlatformSpecificTemplate_NotRejectedClientSide is a
// regression test for https://github.com/jfrog/terraform-provider-xray/issues/432
//
// The provider previously restricted condition_template_id to a hard-coded OneOf list,
// rejecting valid platform/version-specific templates (e.g. isMalicious, NoLicense,
// aged-package variants) at plan time before the request ever reached the Xray API.
// The set of supported templates is dynamic (returned by the condition_templates API),
// so the provider must not gate it client-side.
//
// This uses PlanOnly so it exercises the config-level validators without requiring the
// backend to actually support the template. Before the fix the plan fails with
// "Invalid Attribute Value Match"; after the fix the config plans successfully.
func TestAccCustomCurationCondition_PlatformSpecificTemplate_NotRejectedClientSide(t *testing.T) {
_, _, name := testutil.MkNames("test-platform-template", "xray_custom_curation_condition")

resource.Test(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ProtoV6ProviderFactories: acctest.ProtoV6ProviderFactories,
Steps: []resource.TestStep{
{
Config: testAccCustomCurationConditionPlatformTemplate(name),
PlanOnly: true,
ExpectNonEmptyPlan: true,
},
},
})
}

// CVEName Tests
func TestAccCustomCurationCondition_CVEName_Basic(t *testing.T) {
_, fqrn, name := testutil.MkNames("test-cve-condition", "xray_custom_curation_condition")
Expand Down Expand Up @@ -442,6 +470,21 @@ resource "xray_custom_curation_condition" "{{ .name }}" {
})
}

// testAccCustomCurationConditionPlatformTemplate uses a template ID that is not in the
// provider's previously hard-coded list, to verify it is no longer rejected client-side.
func testAccCustomCurationConditionPlatformTemplate(name string) string {
return util.ExecuteTemplate("TestAccCustomCurationConditionPlatformTemplate", `
resource "xray_custom_curation_condition" "{{ .name }}" {
name = "{{ .name }}"
condition_template_id = "isMalicious"

param_values = jsonencode([])
}
`, map[string]interface{}{
"name": name,
})
}

func testAccCustomCurationConditionCVENameUpdated(name string) string {
return util.ExecuteTemplate("TestAccCustomCurationConditionCVENameUpdated", `
resource "xray_custom_curation_condition" "{{ .name }}" {
Expand Down
Loading