Skip to main content

dtcloud_security_group_rule (Resource)

Manages one rule inside a security group.

The API has a create endpoint and a delete endpoint and nothing else, so every argument forces a new rule. That is what the platform does anyway: delete the old rule, create the new one. The resource ID is <security-group-id>:<rule-id>, because a rule is read by listing its group's rules.

Example Usage​

# Allow SSH from one address range.
resource "dtcloud_security_group_rule" "ssh_from_office" {
security_group_id = dtcloud_security_group.web.id
direction = "ingress"
protocol = "tcp"
port_range_min = 22
port_range_max = 22
remote_ip_prefix = "10.10.0.0/16"
}

# Allow traffic from every machine in another group. Referring to a group rather
# than to an address keeps the rule correct as machines come and go.
resource "dtcloud_security_group_rule" "app_from_web" {
security_group_id = dtcloud_security_group.app.id
direction = "ingress"
protocol = "tcp"
port_range_min = 8080
port_range_max = 8080
remote_group_id = dtcloud_security_group.web.id
}
note

Leave out both remote_ip_prefix and remote_group_id and the rule applies to the whole address family: 0.0.0.0/0 for IPv4, ::/0 for IPv6.

Schema​

Required​

  • direction (String) Traffic direction: ingress (inbound) or egress (outbound). Changing this forces a new resource to be created.
  • security_group_id (String) ID of the security group this rule belongs to. Changing this forces a new resource to be created.

Optional​

  • ethertype (String) Address family: IPv4 or IPv6. Defaults to whatever the platform picks, which is IPv4. Changing this forces a new resource to be created.
  • port_range_max (Number) Last port in the range. For icmp this is the ICMP code, not a port. Omit for all ports. Changing this forces a new resource to be created.
  • port_range_min (Number) First port in the range. For icmp this is the ICMP type, not a port. Omit for all ports. See the note on 0 below. Changing this forces a new resource to be created.
  • protocol (String) Protocol the rule matches, e.g. tcp, udp, icmp, or a protocol number. Omit it to match every protocol. Not restricted to a fixed list, because the platform accepts more than the common names. Changing this forces a new resource to be created.
  • remote_group_id (String) ID of another security group whose members the rule applies to. An id, not a name — the platform does not resolve names here. Mutually exclusive with remote_ip_prefix. Changing this forces a new resource to be created.
  • remote_ip_prefix (String) CIDR the rule applies to, e.g. 10.0.0.0/24. Mutually exclusive with remote_group_id. Changing this forces a new resource to be created.
  • timeouts (Block, Optional) (see below for nested schema)

Read-Only​

  • description (String) Description of the rule. Read-only: the create route does not accept one, so this is only ever non-empty for a rule created outside Terraform.
  • id (String) The ID of this resource.
  • normalized_cidr (String) remote_ip_prefix with its host bits cleared, as the platform computes it — 10.0.0.5/24 is reported here as 10.0.0.0/24.

Nested Schema for timeouts​

Optional:

  • create (String)
  • delete (String)

Behaviour worth knowing​

  • Refused at plan time. A port range without a protocol, port_range_min greater than port_range_max for tcp and udp, and a remote_ip_prefix whose address family disagrees with ethertype. A duplicate rule is not among them: whether one already exists is only known at apply, where the platform's refusal is passed through.
  • ICMP uses the port fields for type and code. For protocol = "icmp", port_range_min is the ICMP type and port_range_max the code. They are not a range, so the ordering check is not applied.
  • 0 and "not set" are the same value. A zero port is dropped from the request, and the platform reports an unset port as empty, which reads back as 0. In practice this only rules out ICMP type 0 (echo reply).
  • protocol ignores case. It is lowercased before it is sent and stored, so TCP and tcp never show as a change.
  • Deleting the group takes its rules. A rule whose group is gone drops out of state instead of failing, because the platform answers a deleted group's rule listing with an empty list.

Timeouts​

create and delete each default to 5 minutes; there is no update, since every change replaces the rule. These calls are synchronous, so the timeouts bound a hung request. Override them with a timeouts block:

resource "dtcloud_security_group_rule" "ssh_from_office" {
# ...

timeouts {
create = "10m"
}
}

Import​

# A rule is found by listing its group, so the import id carries both ids:
# <security-group-id>:<rule-id>
terraform import dtcloud_security_group_rule.ssh_from_office 7f9c1e40-1c3d-4b6a-9a2f-5f1c9d0e3b11:2b8d5a71-90ce-4f2a-8d13-6c0b4e7a1f22

The rule ids are in the group's inbound_rule and outbound_rule attributes, on the resource and on the dtcloud_security_group data source. Everything is read back.