Skip to content

Resolve circular dependency between Policy and Watch #358

@RingoDev

Description

@RingoDev

Is your feature request related to a problem? Please describe.

Below is the way that a security policy can be created currently and attached to a watch. Unfortunately this design causes problems when one tries to remove a policy without removing the watch.
Because of the "name", there is an implicit dependency of the watch on the policy, which means that TF tries to destroy the policy first and runs into the issue that the "policy cannot be removed because it is attached to a watch".

resource "xray_security_policy" "example" {
  name        = "my-security-policy"
  description = "My security policy"
  type        = "security"
  
  # ... your rules configuration ...
}

resource "xray_watch" "example" {
  name        = "my-watch"
  description = "My watch"
  active      = true

  watch_resource {
    type = "repository"
    name = "my-repo"
  }

  assigned_policy {
    name = xray_security_policy.example.name
    type = "security"
  }
}

Describe the solution you'd like
Similar stable providers like AWS provide a separate resource for attachments, that gets rid of the problem.

resource "xray_security_policy" "example" { }

resource "xray_watch" "example" { }

resource "xray_watch_policy_attachment" "example" {
  watch_name  = xray_watch.example.name
  policy_name = xray_security_policy.example.name
  policy_type = "security"
}

This would leave us with the dependency order of

  • Create Policy: policy → watch → attachment ✓
  • Delete Policy: attachment → policy → watch ✓

Describe alternatives you've considered
The only real fully automatic solution to detach a policy from a watch before deletion would probably need to contain custom API calls. All other solutions I could think of require rolling out the update in multiple steps.

resource "terraform_data" "policy_cleanup" {
  triggers_replace = {
    policy_name = xray_security_policy.example.name
  }

  provisioner "local-exec" {
    when    = destroy
    command = <<-EOT
      curl -X POST \
        -u admin:password \
        "${var.xray_url}/api/v2/watches/${var.watch_name}" \
        -H "Content-Type: application/json" \
        -d '{"general_data": {"name": "${var.watch_name}"}, "assigned_policies": []}'
    EOT
  }
}

resource "xray_security_policy" "example" {
  name = "my-security-policy"
  type = "security"
  # ... configuration ...
  
  depends_on = [terraform_data.policy_cleanup]
}

Metadata

Metadata

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions