Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Errors with 3.0.0: Missing object attribute value, extra object attribute value, value conversion #507

Closed
joeybenamy opened this issue Apr 17, 2024 · 4 comments

Comments

@joeybenamy
Copy link

joeybenamy commented Apr 17, 2024

Backend is opentofu 1.6.2.

Errors:

│ Error: Missing Object Attribute Value
│ 
│   with twingate_resource.twingate_resource["Web-Oncolens RDS"],
│   on resources.tf line 1, in resource "twingate_resource" "twingate_resource":
│    1: resource "twingate_resource" "twingate_resource" {
│ 
│ While creating a Object value, a missing attribute value was detected. A
│ Object must contain values for all attributes, even if null or unknown.
│ This is always an issue with the provider and should be reported to the
│ provider developers.
│ 
│ Object Attribute Name (security_policy_id) Expected Type:
│ basetypes.StringType
╵
╷
│ Error: Extra Object Attribute Value
│ 
│   with twingate_resource.twingate_resource["Web-Oncolens RDS"],
│   on resources.tf line 1, in resource "twingate_resource" "twingate_resource":
│    1: resource "twingate_resource" "twingate_resource" {
│ 
│ While creating a Object value, an extra attribute value was detected. A
│ Object must not contain values beyond the expected attribute types. This is
│ always an issue with the provider and should be reported to the provider
│ developers.
│ 
│ Extra Object Attribute Name: service_account_id
│ Error: Value Conversion Error
│ 
│   with twingate_resource.twingate_resource["Web-Oncolens RDS"],
│   on resources.tf line 1, in resource "twingate_resource" "twingate_resource":
│    1: resource "twingate_resource" "twingate_resource" {
│ 
│ An unexpected error was encountered while verifying an attribute value
│ matched its expected type to prevent unexpected behavior or panics. This is
│ always an error in the provider. Please report the following to the
│ provider developer:
│ 
│ Expected framework type from provider logic:
│ types.SetType[types.ObjectType["service_account_id":basetypes.StringType]]
│ / underlying type:
│ tftypes.Set[tftypes.Object["service_account_id":tftypes.String]]
│ Received framework type from provider logic:
│ types.SetType[types.ObjectType["group_ids":types.SetType[basetypes.StringType],
│ "service_account_ids":types.SetType[basetypes.StringType]]] / underlying
│ type: tftypes.Set[tftypes.Object["group_ids":tftypes.Set[tftypes.String],
│ "service_account_ids":tftypes.Set[tftypes.String]]]
│ Path: access_service

Relevant Terraform:

terraform {
  required_providers {
    twingate = {
      source  = "Twingate/twingate"
      version = "3.0.0"
    }

    aws = {
      source  = "hashicorp/aws"
      version = "5.45.0"
    }
  }
}

resource "twingate_resource" "twingate_resource" {
  for_each           = var.resource_map
  name               = "${each.key} ${upper(var.env_name)}"
  address            = each.value["address"]
  remote_network_id  = twingate_remote_network.remote_network.id
  security_policy_id = "<REDACTED>"

  protocols = {
    allow_icmp = true
    tcp = {
      policy = "RESTRICTED"
      ports  = formatlist("%s", each.value["ports"])
    }
    udp = {
      policy = "DENY_ALL"
    }
  }

  dynamic "access_group" {
    for_each = [for group in data.twingate_groups.all_groups.groups : group.id if each.value["groups"] == group.name]
    content {
      group_id           = access_group.value
      security_policy_id = each.value["security_policy"] != null ? [for security_policy in data.twingate_security_policies.all.security_policies : security_policy.id if each.value["security_policy"] == security_policy.name] : "<REDACTED>"
    }
  }

  dynamic "access_service" {
    for_each = each.value["service_accounts"] != null ? [for service_account in data.twingate_service_accounts.all_service_accounts.service_accounts : service_account.id if each.value["service_accounts"] == service_account.name] : [null]
    content {
      service_account_id = access_service.value
    }
  }

  depends_on = [twingate_service_account.teamcity]
}

data "twingate_security_policies" "all" {}

data "twingate_groups" "all_groups" {}

data "twingate_service_accounts" "all_service_accounts" {
  depends_on = [twingate_service_account.teamcity]
}

resource "twingate_service_account" "teamcity" {
  name = "TeamCity ${upper(var.env_name)}"
}

resource "twingate_service_account_key" "teamcity" {
  name               = "TeamCity ${upper(var.env_name)} Key"
  service_account_id = twingate_service_account.teamcity.id
  expiration_time    = 365
}

variable "resource_map" {
  type = map(object({
    address          = string
    ports            = list(number)
    groups           = list(string)
    security_policy  = optional(string)
    service_accounts = optional(list(string))
  }))
}

relevant tfvars:

resource_map = {
    "Web-Oncolens RDS" = {
        address = "<REDACTED>,
        ports = [3306],
        groups = ["AWS Engineers"],
        service_accounts = ["TeamCity UAT"]
    },
}
@twingate-blee
Copy link
Member

@joeybenamy I was not able to reproduce the issue.

This is what I used

tofu --version
OpenTofu v1.6.2
on darwin_arm64
+ provider registry.opentofu.org/twingate/twingate v3.0.0

main.tf

terraform {
  required_providers {
    twingate = {
      source  = "Twingate/twingate"
      version = "3.0.0"
    }
  }
}

resource "twingate_remote_network" "debug" {
  name = "debug"
}

data "twingate_security_policy" "default" {
  name = "Default Policy"
}

resource "twingate_resource" "twingate_resource" {
  for_each           = var.resource_map
  name               = "${each.key} ${upper(var.env_name)}"
  address            = each.value["address"]
  remote_network_id  = twingate_remote_network.debug.id
  security_policy_id = data.twingate_security_policy.default.id

  protocols = {
    allow_icmp = true
    tcp = {
      policy = "RESTRICTED"
      ports  = formatlist("%s", each.value["ports"])
    }
    udp = {
      policy = "DENY_ALL"
    }
  }

  dynamic "access_group" {
    for_each = [for group in data.twingate_groups.all_groups.groups : group.id if each.value["groups"] == group.name]
    content {
      group_id           = access_group.value
      security_policy_id = each.value["security_policy"] != null ? [for security_policy in data.twingate_security_policies.all.security_policies : security_policy.id if each.value["security_policy"] == security_policy.name] : "<REDACTED>"
    }
  }

  dynamic "access_service" {
    for_each = each.value["service_accounts"] != null ? [for service_account in data.twingate_service_accounts.all_service_accounts.service_accounts : service_account.id if each.value["service_accounts"] == service_account.name] : [null]
    content {
      service_account_id = access_service.value
    }
  }

  depends_on = [twingate_service_account.teamcity]
}

data "twingate_security_policies" "all" {}

data "twingate_groups" "all_groups" {}

data "twingate_service_accounts" "all_service_accounts" {
  depends_on = [twingate_service_account.teamcity]
}

resource "twingate_service_account" "teamcity" {
  name = "TeamCity ${upper(var.env_name)}"
}

resource "twingate_service_account_key" "teamcity" {
  name               = "TeamCity ${upper(var.env_name)} Key"
  service_account_id = twingate_service_account.teamcity.id
  expiration_time    = 365
}

variable "resource_map" {
  type = map(object({
    address          = string
    ports            = list(number)
    groups           = list(string)
    security_policy  = optional(string)
    service_accounts = optional(list(string))
  }))
}

variable "env_name" {
  description = "Env name aka tier"
  type        = string
  default     = "test"
}

terraform.tfvars


resource_map = {
  "Web-Oncolens RDS" = {
    address          = "www.test.com",
    ports            = [3306],
    groups           = ["AWS Engineers"],
    service_accounts = ["TeamCity UAT"]
  }
}

Output

tofu apply
data.twingate_groups.all_groups: Reading...
data.twingate_security_policy.default: Reading...
data.twingate_security_policies.all: Reading...
data.twingate_security_policies.all: Read complete after 0s [id=security-policies-all]
data.twingate_security_policy.default: Read complete after 0s [id=U2VjdXJpdHlQb2xpY3k6NTEwMDQ=]
data.twingate_groups.all_groups: Read complete after 0s [id=all-groups]

OpenTofu used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create
 <= read (data resources)

OpenTofu will perform the following actions:

  # data.twingate_service_accounts.all_service_accounts will be read during apply
  # (depends on a resource or a module with changes pending)
 <= data "twingate_service_accounts" "all_service_accounts" {
      + id               = (known after apply)
      + service_accounts = (known after apply)
    }

  # twingate_remote_network.debug will be created
  + resource "twingate_remote_network" "debug" {
      + id       = (known after apply)
      + location = (known after apply)
      + name     = "debug"
    }

  # twingate_resource.twingate_resource["Web-Oncolens RDS"] will be created
  + resource "twingate_resource" "twingate_resource" {
      + address                     = "www.test.com"
      + id                          = (known after apply)
      + is_active                   = true
      + is_authoritative            = (known after apply)
      + is_browser_shortcut_enabled = false
      + is_visible                  = true
      + name                        = "Web-Oncolens RDS TEST"
      + protocols                   = {
          + allow_icmp = true
          + tcp        = {
              + policy = "RESTRICTED"
              + ports  = [
                  + "3306",
                ]
            }
          + udp        = {
              + policy = "DENY_ALL"
              + ports  = []
            }
        }
      + remote_network_id           = (known after apply)
      + security_policy_id          = "U2VjdXJpdHlQb2xpY3k6NTEwMDQ="
    }

  # twingate_service_account.teamcity will be created
  + resource "twingate_service_account" "teamcity" {
      + id   = (known after apply)
      + name = "TeamCity TEST"
    }

  # twingate_service_account_key.teamcity will be created
  + resource "twingate_service_account_key" "teamcity" {
      + expiration_time    = 365
      + id                 = (known after apply)
      + is_active          = (known after apply)
      + name               = "TeamCity TEST Key"
      + service_account_id = (known after apply)
      + token              = (sensitive value)
    }

Plan: 4 to add, 0 to change, 0 to destroy.

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

  Enter a value: yes

twingate_service_account.teamcity: Creating...
twingate_remote_network.debug: Creating...
twingate_service_account.teamcity: Creation complete after 0s [id=U2VydmljZUFjY291bnQ6YzE1OWY1NTAtMjU5My00NjkxLTg0ZTAtNzMyYWJiMTlmMDQ3]
data.twingate_service_accounts.all_service_accounts: Reading...
twingate_service_account_key.teamcity: Creating...
twingate_remote_network.debug: Creation complete after 0s [id=UmVtb3RlTmV0d29yazoxMDYwNjg=]
data.twingate_service_accounts.all_service_accounts: Read complete after 0s [id=all-services]
twingate_resource.twingate_resource["Web-Oncolens RDS"]: Creating...
twingate_service_account_key.teamcity: Creation complete after 1s [id=U2VydmljZUFjY291bnRLZXk6el9XQWV6dFNpWkxrTVctRWV6UFM0X3VqNkp4aUJwci0yLWstQzd4VjBfOA==]
twingate_resource.twingate_resource["Web-Oncolens RDS"]: Creation complete after 1s [id=UmVzb3VyY2U6MjQ2ODQxMA==]

Apply complete! Resources: 4 added, 0 changed, 0 destroyed.

@joeybenamy
Copy link
Author

joeybenamy commented Apr 23, 2024

@twingate-blee I appreciate you testing with OpenTofu and confirming. I will do some more troubleshooting on my side and let you know what I find.

@varxnnn
Copy link

varxnnn commented Apr 25, 2024

++ Facing the same issue.
I'm using Terraform 1.5.4, Twingate provider: 3.0.2.

resource "twingate_resource" "test" {
  name              = "test-name"
  address           = "test-url"
  remote_network_id = twingate_remote_network.aws_network.id
  dynamic access_group {
    for_each = toset([
      twingate_group.devops.id,
      twingate_group.engineering.id
    ])
    content {
      group_id = access_group.value.key
      security_policy_id = data.twingate_security_policy.default.id
      usage_based_autolock_duration_days = 90
    }
  }
  protocols = {
    allow_icmp = false
    tcp = {
      policy = "RESTRICTED"
      ports  = ["443"]
    }
    udp = {
      policy = "DENY_ALL"
    }
  }
}

When I run plan, I get this warning first:

│ Warning: Please update the access blocks.
│
│   with twingate_resource.test,
│   on twingate_resources.tf line 2, in resource "twingate_resource" "test":
│    2: resource "twingate_resource" "test" {
│
│ See the v2 to v3 migration guide in the Twingate Terraform Provider documentation
│ https://registry.terraform.io/providers/Twingate/twingate/latest/docs/guides/migration-v2-to-v3-guide

and then the following 2 errors:

│ Error: Missing Object Attribute Value
│
│   with twingate_resource.test,
│   on twingate_resources.tf line 2, in resource "twingate_resource" "test":
│    2: resource "twingate_resource" "test" {
│
│ While creating a Object value, a missing attribute value was detected. A Object must contain values for all attributes, even if null or unknown.
│ This is always an issue with the provider and should be reported to the provider developers.
│
│ Object Attribute Name (usage_based_autolock_duration_days) Expected Type: basetypes.Int64Type

__

│ Error: Value Conversion Error
│
│   with twingate_resource.test,
│   on twingate_resources.tf line 2, in resource "twingate_resource" "test":
│    2: resource "twingate_resource" "test" {
│
│ An unexpected error was encountered while verifying an attribute value matched its expected type to prevent unexpected behavior or panics. This
│ is always an error in the provider. Please report the following to the provider developer:
│
│ Expected framework type from provider logic: types.SetType[types.ObjectType["group_id":basetypes.StringType,
│ "security_policy_id":basetypes.StringType, "usage_based_autolock_duration_days":basetypes.Int64Type]] / underlying type:
│ tftypes.Set[tftypes.Object["group_id":tftypes.String, "security_policy_id":tftypes.String, "usage_based_autolock_duration_days":tftypes.Number]]
│ Received framework type from provider logic: types.SetType[types.ObjectType["group_ids":types.SetType[basetypes.StringType],
│ "service_account_ids":types.SetType[basetypes.StringType]]] / underlying type:
│ tftypes.Set[tftypes.Object["group_ids":tftypes.Set[tftypes.String], "service_account_ids":tftypes.Set[tftypes.String]]]
│ Path: access_group

@alexb-twingate
Copy link
Contributor

This has been resolved in v3.0.3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants