hashicorp / terraform-provider-aws

The AWS Provider enables Terraform to manage AWS resources.
https://registry.terraform.io/providers/hashicorp/aws
Mozilla Public License 2.0
9.73k stars 9.09k forks source link

[Bug]: aws_ec2_client_vpn_authorization_rule import does not work #26883

Open sidekick-eimantas opened 1 year ago

sidekick-eimantas commented 1 year ago

Terraform Core Version

1.2.7

AWS Provider Version

4.27.0

Affected Resource(s)

Expected Behavior

Import of aws_ec2_client_vpn_authorization_rule works

Actual Behavior

Terraform cannot find the resource when importing aws_ec2_client_vpn_authorization_rule

(3.10) eimantas@Eimantass-MBP vpc % terraform import 'module.vpn_ireland.aws_ec2_client_vpn_authorization_rule.this["all-0.0.0.0/0"]' 'cvpn-endpoint-0cbcabe87524400f8,0.0.0.0/0'
module.vpn_ireland.aws_ec2_client_vpn_authorization_rule.this["all-0.0.0.0/0"]: Importing from ID "cvpn-endpoint-0cbcabe87524400f8,0.0.0.0/0"...
module.vpn_ireland.aws_ec2_client_vpn_authorization_rule.this["all-0.0.0.0/0"]: Import prepared!
  Prepared aws_ec2_client_vpn_authorization_rule for import
module.vpn_ireland.aws_ec2_client_vpn_authorization_rule.this["all-0.0.0.0/0"]: Refreshing state... [id=cvpn-endpoint-0cbcabe87524400f8,0.0.0.0/0]
╷
│ Error: Cannot import non-existent remote object
│ 
│ While attempting to import an existing object to "module.vpn_ireland.aws_ec2_client_vpn_authorization_rule.this[\"all-0.0.0.0/0\"]", the provider detected that no object exists with the
│ given id. Only pre-existing objects can be imported; check that the id is correct and that it is associated with the provider's configured region or endpoint, or use "terraform apply" to
│ create a new remote object for this resource.
╵
image

Relevant Error/Panic Output Snippet

No response

Terraform Configuration Files

resource "aws_ec2_client_vpn_authorization_rule" "this" {
  for_each = { for rule in var.authorization_rules : "${rule.group_id}-${rule.cidr}" => rule }

  client_vpn_endpoint_id = aws_ec2_client_vpn_endpoint.this.id
  description            = each.value.description
  target_network_cidr    = each.value.cidr
  authorize_all_groups   = each.value.group_id == "all" ? true : null
  access_group_id        = each.value.group_id == "all" ? null : each.value.group_id
}

Steps to Reproduce

terraform import 'module.vpn_ireland.aws_ec2_client_vpn_authorization_rule.this["all-0.0.0.0/0"]' 'cvpn-endpoint-0cbcabe87524400f8,0.0.0.0/0'

Debug Output

No response

Panic Output

No response

Important Factoids

No response

References

No response

Would you like to implement a fix?

No response

github-actions[bot] commented 1 year ago

Community Note

Voting for Prioritization

Volunteering to Work on This Issue

justinretzolk commented 1 year ago

Hey @sidekick-eimantas 👋 Thank you for taking the time to raise this! Is it possible to supply debug logs (redacted as needed) as well, so that we have all of the information that might help to investigate this?

OJFord commented 1 year ago

It works with a group ID; just not one that has authorize_all_groups = true.

Also, if it has the same target CIDR as one already imported (for a specific group) then it claims to be already in state. After removing it, importing it gives this error.

(I'm not sure of the utility of having two endpoints with same CIDR, but AWS allows it, so the provider should too.)

OJFord commented 1 year ago

It also fails to find it even if it creates it itself:

│ Error: error waiting for EC2 Client VPN Authorization Rule (cvpn-endpoint-deadbeef,192.168.0.0/16) create: couldn't find resource (21 retries)

sblask commented 1 year ago

I just ran into a problem that I believe is related. I could import a rule by endpoint ID and CIDR even though it was configured with a group ID. But the resource could not be managed by Terraform and I got errors like this:

Error: deleting EC2 Client VPN Authorization Rule (cvpn-endpoint-0e99ae41fe2f519d0,10.21.0.0/16): MissingParameter: You must specify either access-group-id or revoke-all-groups

I believe the problem was that the import created a resource with an ID that does not contain the group ID and the deletion used created request parameters based on the resource ID and not on what is in the state or Terraform config. terraform state rm and a re-import by endpoint ID, CIDR and group ID fixed the problem.

l13t commented 1 year ago

The issue is still reproducible in Terraform 1.3.9 and AWS Provider 4.{59,60}. In my case removing and importing resources again didn't work.

❯ tf import 'module.client_vpn_authorization_rule_sso.aws_ec2_client_vpn_authorization_rule.everyone-allowed-to-cpvn-endpoints["udp_10.243.0.0/16"]' 'cvpn-endpoint-0123456789abcdef0,10.243.0.0/16'
Acquiring state lock. This may take a few moments...
data.terraform_remote_state.vpn: Reading...
data.terraform_remote_state.vpn: Read complete after 2s
module.client_vpn_authorization_rule_sso.aws_ec2_client_vpn_authorization_rule.everyone-allowed-to-cpvn-endpoints["udp_10.243.0.0/16"]: Importing from ID "cvpn-endpoint-0123456789abcdef0,10.243.0.0/16"...
module.client_vpn_authorization_rule_sso.aws_ec2_client_vpn_authorization_rule.everyone-allowed-to-cpvn-endpoints["udp_10.243.0.0/16"]: Import prepared!
  Prepared aws_ec2_client_vpn_authorization_rule for import
module.client_vpn_authorization_rule_sso.aws_ec2_client_vpn_authorization_rule.everyone-allowed-to-cpvn-endpoints["udp_10.243.0.0/16"]: Refreshing state... [id=cvpn-endpoint-0123456789abcdef0,10.243.0.0/16]
╷
│ Error: Cannot import non-existent remote object
│
│ While attempting to import an existing object to
│ "module.client_vpn_authorization_rule_sso.aws_ec2_client_vpn_authorization_rule.everyone-allowed-to-cpvn-endpoints[\"udp_10.243.0.0/16\"]", the
│ provider detected that no object exists with the given id. Only pre-existing objects can be imported; check that the id is correct and that it is
│ associated with the provider's configured region or endpoint, or use "terraform apply" to create a new remote object for this resource.
╵

Releasing state lock. This may take a few moments...
❯ tfa -target 'module.client_vpn_authorization_rule_sso.aws_ec2_client_vpn_authorization_rule.everyone-allowed-to-cpvn-endpoints["udp_10.243.0.0/16"]'

Acquiring state lock. This may take a few moments...
data.terraform_remote_state.vpn: Reading...
data.terraform_remote_state.vpn: Read complete after 2s

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # module.client_vpn_authorization_rule_sso.aws_ec2_client_vpn_authorization_rule.everyone-allowed-to-cpvn-endpoints["udp_10.243.0.0/16"] will be created
  + resource "aws_ec2_client_vpn_authorization_rule" "everyone-allowed-to-cpvn-endpoints" {
      + authorize_all_groups   = true
      + client_vpn_endpoint_id = "cvpn-endpoint-0123456789abcdef0"
      + description            = "Allow everyone from 10.243.0.0/16 VPN client endpoint to talk with cpvn-endpoints"
      + id                     = (known after apply)
      + target_network_cidr    = "10.243.0.0/16"

      + timeouts {
          + create = "5m"
          + delete = "5m"
        }
    }

Plan: 1 to add, 0 to change, 0 to destroy.
╷
│ Warning: Resource targeting is in effect
│
│ You are creating a plan with the -target option, which means that the result of this plan may not represent all of the changes requested by the
│ current configuration.
│
│ The -target option is not for routine use, and is provided only for exceptional situations such as recovering from errors or mistakes, or when
│ Terraform specifically suggests to use it as part of an error message.
╵

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

module.client_vpn_authorization_rule_sso.aws_ec2_client_vpn_authorization_rule.everyone-allowed-to-cpvn-endpoints["udp_10.243.0.0/16"]: Creating...
╷
│ Warning: Applied changes may be incomplete
│
│ The plan was created with the -target option in effect, so some changes requested in the configuration may have been ignored and the output
│ values may not be fully updated. Run the following command to verify that no other changes are pending:
│     terraform plan
│
│ Note that the -target option is not suitable for routine use, and is provided only for exceptional situations such as recovering from errors or
│ mistakes, or when Terraform specifically suggests to use it as part of an error message.
╵
╷
│ Error: authorizing EC2 Client VPN Authorization Rule (cvpn-endpoint-0123456789abcdef0,10.243.0.0/16): InvalidClientVpnDuplicateAuthorizationRule: Rule already exists
│   status code: 400, request id: ---
│
│   with module.client_vpn_authorization_rule_sso.aws_ec2_client_vpn_authorization_rule.everyone-allowed-to-cpvn-endpoints["udp_10.243.0.0/16"],
│   on modules/authorization_rule/main.tf line 46, in resource "aws_ec2_client_vpn_authorization_rule" "everyone-allowed-to-cpvn-endpoints":
│   46: resource "aws_ec2_client_vpn_authorization_rule" "everyone-allowed-to-cpvn-endpoints" {
│
╵
Releasing state lock. This may take a few moments...
eherot commented 8 months ago

Digging into this a little it seems like it should actually be a fairly trivial fix. Either the import parser has to be updated to allow a rule ending in a blank group ID (e.g. cvpn-endpoint-XXXXXXXX,0.0.0.0/0,), or the format needs to be modified so that AccessAll=true can somehow be specified (maybe cvpn-endpoint-XXXXXXXX,0.0.0.0/0,AccessAll?)

e.g. Something like this...

--- a/internal/service/ec2/vpnclient_authorization_rule.go
+++ b/internal/service/ec2/vpnclient_authorization_rule.go
@@ -118,12 +118,22 @@ func resourceClientVPNAuthorizationRuleRead(ctx context.Context, d *schema.Resou
        var diags diag.Diagnostics
        conn := meta.(*conns.AWSClient).EC2Conn(ctx)

-       endpointID, targetNetworkCIDR, accessGroupID, err := ClientVPNAuthorizationRuleParseResourceID(d.Id())
+       endpointID, targetNetworkCIDR, groupAccessField, err := ClientVPNAuthorizationRuleParseResourceID(d.Id())

        if err != nil {
                return sdkdiag.AppendErrorf(diags, "reading EC2 Client VPN Authorization Rule (%s): %s", d.Id(), err)
        }

+       var accessGroupID string
+       var accessAll *bool
+       if groupAccessField == "AccessAll" {
+               accessGroupID = ""
+               accessAll = aws.Bool(true)
+       } else {
+               accessGroupID = groupAccessField
+               accessAll = aws.Bool(false)
+       }
+
        rule, err := FindClientVPNAuthorizationRuleByThreePartKey(ctx, conn, endpointID, targetNetworkCIDR, accessGroupID)

        if !d.IsNewResource() && tfresource.NotFound(err) {