Migrating from security_group_rules to security_group
-> This migration guide applies to Exoscale Terraform Provider version 0.31.3 to 0.53.2.
This page helps you migrate from an exoscale_security_group_rules
resource (which is deprecated) to a set of exoscale_security_group_rule
.
~> Note: Before migrating exoscale_security_group_rules
resources you need to ensure you use the latest version of Terraform and have a clean configuration.
Before proceeding, please:
- Upgrade the Exoscale provider to at least v0.31.3: allow us to run
terraform import
onexoscale_security_group
andexoscale_security_group_rule
resources. - Ensure your configuration can be successfully applied:
terraform plan
must NOT output errors, changes, or moves of resources - Have the Exoscale cli to retrieve IDs of security groups and security group rules
- Perform a backup of your state! We are going to manipulate it, and errors can always happen. Remote states can be retrieved with
terraform state pull
and restored withterraform state push
. If you keep your state as a single local file, a regular file copy can do the job.
Example configuration
In this guide, we will assume the following configuration as an example:
resource "exoscale_security_group" "webapp" {
name = "webapp"
# ...
}
resource "exoscale_security_group" "bastion" {
name = "bastion"
# ...
}
resource "exoscale_security_group_rules" "webapp" {
security_group_id = exoscale_security_group.webapp.id
ingress {
ports = ["22"]
protocol = "TCP"
user_security_group_list = [exoscale_security_group.bastion.name]
}
ingress {
ports = ["80"]
protocol = "TCP"
cidr_list = ["0.0.0.0/0"]
}
ingress {
ports = ["443"]
protocol = "TCP"
cidr_list = ["0.0.0.0/0"]
}
}
As you can see, we have a security group with an associated security_group_rules
resource that:
- allows access from every IPv4 address to ports 80 and 443, and
- allows access to port 22 from hosts that belongs to another security group named
bastion
.
From the Exoscale cli, we can retrieve information for every security group:
exo compute sg list
# [output]
# ┼──────────────────────────────────────┼─────────┼
# │ ID │ NAME │
# ┼──────────────────────────────────────┼─────────┼
# │ b83fe506-51e6-4933-8e70-205df6b640fa │ webapp │
# │ e1654b58-64f6-4efc-b8d9-7bbda86a83fa │ bastion │
# │ a0191fd7-1275-4614-9fed-be6f19a770a0 │ default │
# ┼──────────────────────────────────────┼─────────┼
The Terraform state contains them as well:
terraform state list
# [output]
# exoscale_security_group.bastion
# exoscale_security_group.webapp
# exoscale_security_group_rules.webapp
We want to migrate the single exoscale_security_group_rules.webapp
to 3 different exoscale_security_group_rule
resources, as we have 3 different ingress rules.
~> Note: If in your exoscale_security_group_rules
definition ingress
and/or egress
blocks define multiple ports or port ranges (as ports
attribute is an array), you need to define one exoscale_security_group_rule
for each port or port range as multiple values per rule are no longer allowed.
Migration plan
To achieve this migration, we have to remove from the state:
exoscale_security_group.webapp
- ALL rules that belongs to
exoscale_security_group.webapp
. In our case:exoscale_security_group_rules.webapp
After these resources are removed from the state, we will have to import exoscale_security_group.webapp
back as well as related security group rules as exoscale_security_group_rule
resources.
Applying the migration plan
Removing the security group from the state
This step is pretty straightforward: we will have to issue a terraform state rm
command for each resources we have to
remove from the state. In our example, we have to remove exoscale_security_group.webapp
, and exoscale_security_group_rules.webapp
:
terraform state rm exoscale_security_group_rules.webapp
# [output]
# Removed exoscale_security_group_rules.webapp
# Successfully removed 1 resource instance(s).
terraform state rm exoscale_security_group.webapp
# [output]
# Removed exoscale_security_group.webapp
# Successfully removed 1 resource instance(s).
Now, these resources are removed from the state.
Update infrastructure definition
Replace the exoscale_security_group_rules
block by new exoscale_security_group_rule
resources:
resource "exoscale_security_group_rule" "webapp_ssh" {
security_group_id = exoscale_security_group.webapp.id
type = "INGRESS"
start_port = 22
end_port = 22
protocol = "TCP"
user_security_group_id = exoscale_security_group.bastion.id
}
resource "exoscale_security_group_rule" "webapp_public" {
for_each = toset(["80", "443"])
security_group_id = exoscale_security_group.webapp.id
type = "INGRESS"
start_port = each.value
end_port = each.value
protocol = "TCP"
cidr = "0.0.0.0/0"
}
Note that we can of course imagine 3 single resource blocks: webapp_http
and webapp_https
replacing webapp_public
in addition to webapp_ssh
.
In our example we tried instead to follow the semantic behind each rule, and group them:
webapp_ssh
allows access to SSH through a bastion security groupwebapp_public
allows access to HTTP(S) services, on both port 80 and 443, leveraging thefor_each
notation of Terraform.
Importing the security group and related rules into the state
Using the Exoscale cli, we can find the ID of the webapp security group:
exo compute sg list
# [output]
# ┼──────────────────────────────────────┼─────────┼
# │ ID │ NAME │
# ┼──────────────────────────────────────┼─────────┼
# │ b83fe506-51e6-4933-8e70-205df6b640fa │ webapp │
# │ e1654b58-64f6-4efc-b8d9-7bbda86a83fa │ bastion │
# │ a0191fd7-1275-4614-9fed-be6f19a770a0 │ default │
# ┼──────────────────────────────────────┼─────────┼
In our case, it’s b83fe506-51e6-4933-8e70-205df6b640fa
. Let’s import this resource:
terraform import exoscale_security_group.webapp b83fe506-51e6-4933-8e70-205df6b640fa
# [output]
# exoscale_security_group.webapp: Importing from ID "b83fe506-51e6-4933-8e70-205df6b640fa"...
# exoscale_security_group.webapp: Import prepared!
# Prepared exoscale_security_group for import
# exoscale_security_group.webapp: Refreshing state... [id=b83fe506-51e6-4933-8e70-205df6b640fa]
#
# Import successful!
#
# The resources that were imported are shown above. These resources are now in
# your Terraform state and will henceforth be managed by Terraform.
As you can see, and as expected, the import process imported exoscale_security_group.webapp
.
We also need to import related exoscale_security_group_rule
resources. To find their IDs, we must use CLI again:
exo c security-group show b83fe506-51e6-4933-8e70-205df6b640fa
┼──────────────────┼─────────────────────────────────────────────────────────────────────┼
│ SECURITY GROUP │ │
┼──────────────────┼─────────────────────────────────────────────────────────────────────┼
│ ID │ b83fe506-51e6-4933-8e70-205df6b640fa │
│ Name │ webapp │
│ Description │ │
│ Ingress Rules │ │
│ │ 5dafa58d-ba4d-4990-b66d-2996782ee3f3 TCP 0.0.0.0/0 22 │
│ │ e7bbda2b-3c93-4693-a54c-465ac28bda59 TCP 0.0.0.0/0 443 │
│ │ 0a187bd0-b5dc-4a58-bab2-44bc7064b83b TCP 0.0.0.0/0 80 │
│ │ │
│ Egress Rules │ - │
│ External Sources │ - │
┼──────────────────┼─────────────────────────────────────────────────────────────────────┼
Security group rule IDs can by found in Ingress Rules
: 5dafa58d-ba4d-4990-b66d-2996782ee3f3
, e7bbda2b-3c93-4693-a54c-465ac28bda59
and 0a187bd0-b5dc-4a58-bab2-44bc7064b83b
.
Now we can import them one by one:
terraform import exoscale_security_group_rule.webapp_ssh b83fe506-51e6-4933-8e70-205df6b640fa/5dafa58d-ba4d-4990-b66d-2996782ee3f3
# [output]
# exoscale_security_group_rule.webapp_ssh: Importing from ID "b83fe506-51e6-4933-8e70-205df6b640fa/5dafa58d-ba4d-4990-b66d-2996782ee3f3"...
# exoscale_security_group_rule.webapp_ssh: Import prepared!
# Prepared exoscale_security_group_rule for import
# exoscale_security_group_rule.webapp_ssh: Refreshing state... [id=5dafa58d-ba4d-4990-b66d-2996782ee3f3]
#
# Import successful!
#
# The resources that were imported are shown above. These resources are now in
# your Terraform state and will henceforth be managed by Terraform.
terraform import 'exoscale_security_group_rule.webapp_public["443"]' b83fe506-51e6-4933-8e70-205df6b640fa/e7bbda2b-3c93-4693-a54c-465ac28bda59
# [output]
# exoscale_security_group_rule.webapp_public["443"]: Importing from ID "b83fe506-51e6-4933-8e70-205df6b640fa/e7bbda2b-3c93-4693-a54c-465ac28bda59"...
# exoscale_security_group_rule.webapp_public["443"]: Import prepared!
# Prepared exoscale_security_group_rule for import
# exoscale_security_group_rule.webapp_public["443"]: Refreshing state... [id=e7bbda2b-3c93-4693-a54c-465ac28bda59]
#
# Import successful!
#
# The resources that were imported are shown above. These resources are now in
# your Terraform state and will henceforth be managed by Terraform.
terraform import 'exoscale_security_group_rule.webapp_public["80"]' b83fe506-51e6-4933-8e70-205df6b640fa/0a187bd0-b5dc-4a58-bab2-44bc7064b83b
# [output]
# exoscale_security_group_rule.webapp_public["80"]: Importing from ID "b83fe506-51e6-4933-8e70-205df6b640fa/0a187bd0-b5dc-4a58-bab2-44bc7064b83b"...
# exoscale_security_group.webapp_public["80"]: Import prepared!
# Prepared exoscale_security_group_rule for import
# exoscale_security_group_rule.webapp_public["80"]: Refreshing state... [id=0a187bd0-b5dc-4a58-bab2-44bc7064b83b]
#
# Import successful!
#
# The resources that were imported are shown above. These resources are now in
# your Terraform state and will henceforth be managed by Terraform.
In order to check this result and display details on newly imported rules, we have to run terraform plan
:
terraform apply
# [output]
# exoscale_security_group.webapp: Refreshing state... [id=b83fe506-51e6-4933-8e70-205df6b640fa]
# exoscale_security_group.bastion: Refreshing state... [id=e1654b58-64f6-4efc-b8d9-7bbda86a83fa]
# exoscale_security_group_rule.webapp_ssh: Refreshing state... [id=5dafa58d-ba4d-4990-b66d-2996782ee3f3]
# exoscale_security_group_rule.webapp_public["80"]: Refreshing state... [id=0a187bd0-b5dc-4a58-bab2-44bc7064b83b]
# exoscale_security_group_rule.webapp_public["443"]: Refreshing state... [id=e7bbda2b-3c93-4693-a54c-465ac28bda59]
#
# No changes. Your infrastructure matches the configuration.
#
# Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
Here we can see that our configuration is matching the state: no resources will be changed.
Now we have finished replacing exoscale_security_group_rules
with a set of exoscale_security_group_rule
.
Our Terraform state matches the related configuration, so migration is completely done.