Skip to content

frostmoln_security_group (Resource) ​

Manages a security group in the Frostmoln Cloud Platform.

This resource manages the GROUP ONLY, never its rules. Rules are separate frostmoln_security_group_rule resources — the same shape the AWS provider uses. Nothing in this resource describes the rules the group carries: there is no rules attribute and Read does not fetch any, so a terraform plan on this resource NEVER reports rule drift, whatever the group's rules have become.

A rule added out of band is invisible to Terraform. A rule created through the portal, the fm CLI or the API — by a colleague, a script, or an incident fix — appears in no plan, is never flagged, and is never removed by terraform apply or terraform destroy. The reverse case IS caught: a frostmoln_security_group_rule this configuration owns that is deleted out of band is detected on refresh and planned for re-creation. Reconciling added rules means listing the group outside Terraform — fm, the portal and the API all return its full rule set — and then importing each rule that should be managed with terraform import frostmoln_security_group_rule.<name> <security_group_id>/<rule_id>.

Every new security group starts with two allow-all egress rules. Frostmoln adds no default rules of its own to a group created here, but the underlying network service unconditionally creates one "any protocol to everywhere" egress rule per address family — IPv4 and IPv6 — on every security group, each carrying an EMPTY remote prefix. They are live and permissive from the moment the group exists, they are returned by the API (so fm, the portal and the API all show them), and adding egress rules of your own does not narrow them — security group rules are additive, so traffic matching any rule is allowed. Setting delete_default_egress = true removes both as part of creating the group. Without it they are unmanaged: they appear in no plan and survive a terraform destroy of every rule this configuration declares, and a group that must not egress freely has to have them removed deliberately — either delete them outside Terraform, or import each as a frostmoln_security_group_rule ONLY IN ORDER TO DESTROY IT, and remove the block from configuration again once the destroy has run. Leaving the block in place makes the next apply try to RE-CREATE the rule, and the platform refuses a rule with no remote. frostmoln_security_group_rule also has no ether_type attribute, so the IPv4 and IPv6 defaults are indistinguishable in configuration — only one of the two could ever be expressed.

A security group Frostmoln provisioned for a managed service cannot be managed here. Groups created for a managed database, cache, webserver, messaging instance, Kubernetes cluster or Application Gateway are visible in your account and returned by the API, so they can be imported — but every write against one is refused with 409 / resource_in_use, permanently. Reads still work, so an imported group that matches its configuration plans empty and applies clean; what fails, every time, is terraform destroy and any apply that plans a change to it. There is no attribute that predicts this and no force flag, so the only exit is terraform state rm. Do not import one.

Authoritative scope — who owns what on this resource, declared in internal/scopedecl and machine-checked against the schema.

Enacted and reconciled — every configurable attribute not listed below: the platform applies it, and a refresh reads the truth back.

Create-immutable — vpc_id: the network API has no in-place update for it, so a change destroys and re-creates the group.

Not enacted state — delete_default_egress: a create-time directive: it applies when the group is created, and changing it on an existing group is a documented no-op (the plan warns to that effect).

Observed, not enacted — tags_all: keys set outside Terraform — in the portal, by the fm CLI, or stamped by the platform — appear only here and are kept on every apply, never removed.

Platform-invented default — allow-all egress pair (IPv4 + IPv6, empty remote prefix, injected by the network service on every new group): delete-on-create. The pair is not load-bearing; delete_default_egress = true removes it at create (opt-in today, the default flips to true at provider v2 with a deprecation notice ahead of it).

Platform-invented default — the tenant's default security group (is_default): keep-with-docs. Readable as the computed is_default; no default_* resource exists to adopt it today.

Example Usage ​

terraform
resource "frostmoln_security_group" "web" {
  name        = "web-sg"
  description = "Security group for web servers"
  vpc_id      = frostmoln_vpc.example.id

  # Delete the two allow-all egress rules the platform injects into every new
  # group (one per address family, empty remote prefix) as part of creating
  # it. Rules are additive and those defaults allow everything outbound, so
  # until they are gone the egress declared below narrows nothing. Opting in
  # here is also what a configuration wants ahead of provider v2, where this
  # becomes the default.
  delete_default_egress = true

  tags = {
    tier = "web"
  }
}

# Declare the group's egress explicitly. With the injected defaults deleted
# above, this is the egress the group actually carries — not an addition to
# an allow-all baseline.
resource "frostmoln_security_group_rule" "web_egress_https" {
  security_group_id = frostmoln_security_group.web.id
  direction         = "egress"
  protocol          = "tcp"
  port_range_min    = 443
  port_range_max    = 443
  remote_cidr       = "0.0.0.0/0"
  description       = "Allow HTTPS egress"
}

Schema ​

Required ​

  • name (String) The name of the security group, 1 to 234 characters.

Optional ​

  • delete_default_egress (Boolean) Delete the two allow-all egress rules the network service injects into every new group (one per address family, each with an EMPTY remote prefix) as part of creating it. Those defaults allow all outbound traffic, and declaring egress rules of your own does not narrow them — rules are additive. When this is true, Create deletes both right after the group exists, matched on direction and empty remote prefix, never on address family — a rule has no ether_type, so the IPv4 and IPv6 defaults are indistinguishable and both must go. A deletion failure is reported as a WARNING, never as a failed create: the group is live either way.

    This is create-time behaviour only. The value is carried in state so plans stay clean, changing it on an existing group does nothing, and Read never lists or manages rules. Defaults to false today; at provider v2 the default flips to true, announced by a deprecation notice in the v1 line ahead of the flip.

  • description (String) A description of the security group, at most 1024 characters.

  • tags (Map of String) Tags for the security group. Merged with the provider's default_tags on every write (a key set here wins). Holds only the keys this configuration sets; the full set is in tags_all.

  • timeouts (Block, Optional) (see below for nested schema)

  • vpc_id (String) The ID of the VPC this security group belongs to.

Read-Only ​

  • created_at (String) The creation timestamp.
  • id (String) The unique identifier of the security group.
  • is_default (Boolean) Whether this is the default security group.
  • tags_all (Map of String) Every tag the platform holds on this resource: the provider's default_tags, this resource's own tags (which win on a shared key), and any key set outside Terraform — in the portal, by the fm CLI, or stamped by the platform. Keys set outside Terraform appear only here and are kept on every apply, never removed.

Nested Schema for timeouts ​

Optional:

  • create (String) How long the provider waits for the create operation to converge before giving up (e.g. "45m", "2h").
  • delete (String) How long the provider waits for the delete to complete before giving up (e.g. "30m").
  • update (String) How long the provider waits for an update (resize, in-place change) to converge before giving up (e.g. "30m").