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

multiple VPC Endpoint Services matched if more than one endpoint of the same type on an account #686

Open
cryptk opened this issue Aug 26, 2021 · 4 comments

Comments

@cryptk
Copy link

cryptk commented Aug 26, 2021

Description

If creating multiple VPCs on the same account, and creating the same endpoint type in those VPCs, you receive the following error:

Error: multiple VPC Endpoint Services matched; use additional constraints to reduce matches to a single VPC Endpoint Service

Versions

  • Terraform: 0.15.5
  • Provider(s):
  • provider registry.terraform.io/hashicorp/aws v3.54.0
  • provider registry.terraform.io/hashicorp/local v2.1.0
  • provider registry.terraform.io/hashicorp/null v3.1.0
  • provider registry.terraform.io/hashicorp/random v3.1.0
  • provider registry.terraform.io/hashicorp/template v2.2.0
  • Module: 3.6.0

Reproduction

Steps to reproduce the behavior:
Create multiple VPCs using the terraform-aws-modules/vpc module
create endpoints using the vpc-endpoints submodule, ensure that you create the same endpoint type in both VPCs

Expected behavior

Terraform should filter enough to differentiate endpoints that belong to different VPCs. Likely adding another filter for the VPC ID would fix this

Actual behavior

│ Error: multiple VPC Endpoint Services matched; use additional constraints to reduce matches to a single VPC Endpoint Service
│ 
│   with module.lab[0].module.vpc_endpoints.data.aws_vpc_endpoint_service.this["appmesh_envoy_management"],
│   on .terraform/modules/lab.vpc_endpoints/modules/vpc-endpoints/main.tf line 9, in data "aws_vpc_endpoint_service" "this":
│    9: data "aws_vpc_endpoint_service" "this" {
@bryantbiggs
Copy link
Member

hmm, looks like best we could do would be to add a conditional filter for tag https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeVpcEndpointServices.html

@dirk39
Copy link

dirk39 commented Sep 24, 2022

Hello everybody,
I tried to replicate the issue using the module examples unsuccessfully. What I've noticed is that the problem comes with the custom service endpoints and not with the AWS-managed ones. Trying to add a filter per tag break the AWS service endpoints:

Error: no matching EC2 VPC Endpoint Service found
   with module.vpc_endpoints_2.data.aws_vpc_endpoint_service.this["s3"],
   on terraform-aws-vpc/modules/vpc-endpoints/main.tf line 9, in data "aws_vpc_endpoint_service" "this":
    9: data "aws_vpc_endpoint_service" "this" {

One way to solve the issue could be by introducing a variable that determines if the service belongs to AWS or not. Another way (maybe easier) is just to define different service names.

What do you think?

@slancerk
Copy link

slancerk commented Mar 26, 2023

use tags
Error: multiple VPC Endpoint Services matched; use additional constraints to reduce matches to a single VPC Endpoint Service

@rahulpatilgit
Copy link

No issue was observed while testing.
Able to create endpoints in two VPCs in same account.

module "vpc1" {
  source = "./modules/terraform-aws-vpc"
  name   = "vpc1"
}

module "endpoints1" {
  source             = "./modules/terraform-aws-vpc/modules/vpc-endpoints"
  vpc_id             = module.vpc1.vpc_id
  security_group_ids = [module.vpc1.default_security_group_id]
 endpoints = {
    s3 = {
      service = "s3"
      tags    = { Name = "s3-vpc-endpoint-vpc1" }
    },
    dynamodb = {
      service         = "dynamodb"
      service_type    = "Gateway"
      route_table_ids = flatten([module.vpc1.intra_route_table_ids, module.vpc1.private_route_table_ids, module.vpc1.public_route_table_ids])
      policy          = data.aws_iam_policy_document.dynamodb_endpoint_policy1.json
      tags            = { Name = "dynamodb-vpc-endpoint" }
    },
    ssm = {
      service             = "ssm"
      private_dns_enabled = true
      subnet_ids          = module.vpc1.private_subnets
      security_group_ids  = [module.vpc1.default_security_group_id]
    },
    ssmmessages = {
      service             = "ssmmessages"
      private_dns_enabled = true
      subnet_ids          = module.vpc1.private_subnets
      security_group_ids  = [module.vpc1.default_security_group_id]
    },
    lambda = {
      service             = "lambda"
      private_dns_enabled = true
      subnet_ids          = module.vpc1.private_subnets
    },
    ecs = {
      service             = "ecs"
      private_dns_enabled = true
      subnet_ids          = module.vpc1.private_subnets
    },
    ecs_telemetry = {
      create              = false
      service             = "ecs-telemetry"
      private_dns_enabled = true
      subnet_ids          = module.vpc1.private_subnets
    },
    ec2 = {
      service             = "ec2"
      private_dns_enabled = true
      subnet_ids          = module.vpc1.private_subnets
      security_group_ids  = [module.vpc1.default_security_group_id]
    },
    ec2messages = {
      service             = "ec2messages"
      private_dns_enabled = true
      subnet_ids          = module.vpc1.private_subnets
      security_group_ids  = [module.vpc1.default_security_group_id]
    },
    ecr_api = {
      service             = "ecr.api"
      private_dns_enabled = true
      subnet_ids          = module.vpc1.private_subnets
      policy              = data.aws_iam_policy_document.generic_endpoint_policy1.json
    },
    ecr_dkr = {
      service             = "ecr.dkr"
      private_dns_enabled = true
      subnet_ids          = module.vpc1.private_subnets
      policy              = data.aws_iam_policy_document.generic_endpoint_policy1.json
    },
    kms = {
      service             = "kms"
      private_dns_enabled = true
      subnet_ids          = module.vpc1.private_subnets
      security_group_ids  = [module.vpc1.default_security_group_id]
    },
    codedeploy = {
      service             = "codedeploy"
      private_dns_enabled = true
      subnet_ids          = module.vpc1.private_subnets
    },
    codedeploy_commands_secure = {
      service             = "codedeploy-commands-secure"
      private_dns_enabled = true
      subnet_ids          = module.vpc1.private_subnets
    },
  }
}


data "aws_iam_policy_document" "generic_endpoint_policy1" {
  statement {
    effect    = "Deny"
    actions   = ["*"]
    resources = ["*"]

    principals {
      type        = "*"
      identifiers = ["*"]
    }

    condition {
      test     = "StringNotEquals"
      variable = "aws:SourceVpc"

      values = [module.vpc1.vpc_id]
    }
  }
}

data "aws_iam_policy_document" "dynamodb_endpoint_policy1" {
  statement {
    effect    = "Deny"
    actions   = ["dynamodb:*"]
    resources = ["*"]

    principals {
      type        = "*"
      identifiers = ["*"]
    }

    condition {
      test     = "StringNotEquals"
      variable = "aws:sourceVpce"

      values = [module.vpc1.vpc_id]
    }
  }
}

# =====================================================================================================

module "vpc2" {
  source = "./modules/terraform-aws-vpc"
  name   = "vpc2"
}

module "endpoints2" {
  source             = "./modules/terraform-aws-vpc/modules/vpc-endpoints"
  vpc_id             = module.vpc2.vpc_id
  security_group_ids = [module.vpc2.default_security_group_id]
 endpoints = {
    s3 = {
      service = "s3"
      tags    = { Name = "s3-vpc-endpoint-vpc2" }
    },
    dynamodb = {
      service         = "dynamodb"
      service_type    = "Gateway"
      route_table_ids = flatten([module.vpc2.intra_route_table_ids, module.vpc2.private_route_table_ids, module.vpc2.public_route_table_ids])
      policy          = data.aws_iam_policy_document.dynamodb_endpoint_policy2.json
      tags            = { Name = "dynamodb-vpc-endpoint" }
    },
    ssm = {
      service             = "ssm"
      private_dns_enabled = true
      subnet_ids          = module.vpc2.private_subnets
      security_group_ids  = [module.vpc2.default_security_group_id]
    },
    ssmmessages = {
      service             = "ssmmessages"
      private_dns_enabled = true
      subnet_ids          = module.vpc2.private_subnets
      security_group_ids  = [module.vpc2.default_security_group_id]
    },
    lambda = {
      service             = "lambda"
      private_dns_enabled = true
      subnet_ids          = module.vpc2.private_subnets
    },
    ecs = {
      service             = "ecs"
      private_dns_enabled = true
      subnet_ids          = module.vpc2.private_subnets
    },
    ecs_telemetry = {
      create              = false
      service             = "ecs-telemetry"
      private_dns_enabled = true
      subnet_ids          = module.vpc2.private_subnets
    },
    ec2 = {
      service             = "ec2"
      private_dns_enabled = true
      subnet_ids          = module.vpc2.private_subnets
      security_group_ids  = [module.vpc2.default_security_group_id]
    },
    ec2messages = {
      service             = "ec2messages"
      private_dns_enabled = true
      subnet_ids          = module.vpc2.private_subnets
      security_group_ids  = [module.vpc2.default_security_group_id]
    },
    ecr_api = {
      service             = "ecr.api"
      private_dns_enabled = true
      subnet_ids          = module.vpc2.private_subnets
      policy              = data.aws_iam_policy_document.generic_endpoint_policy2.json
    },
    ecr_dkr = {
      service             = "ecr.dkr"
      private_dns_enabled = true
      subnet_ids          = module.vpc2.private_subnets
      policy              = data.aws_iam_policy_document.generic_endpoint_policy2.json
    },
    kms = {
      service             = "kms"
      private_dns_enabled = true
      subnet_ids          = module.vpc2.private_subnets
      security_group_ids  = [module.vpc2.default_security_group_id]
    },
    codedeploy = {
      service             = "codedeploy"
      private_dns_enabled = true
      subnet_ids          = module.vpc2.private_subnets
    },
    codedeploy_commands_secure = {
      service             = "codedeploy-commands-secure"
      private_dns_enabled = true
      subnet_ids          = module.vpc2.private_subnets
    },
  }
}


data "aws_iam_policy_document" "generic_endpoint_policy2" {
  statement {
    effect    = "Deny"
    actions   = ["*"]
    resources = ["*"]

    principals {
      type        = "*"
      identifiers = ["*"]
    }

    condition {
      test     = "StringNotEquals"
      variable = "aws:SourceVpc"

      values = [module.vpc2.vpc_id]
    }
  }
}

data "aws_iam_policy_document" "dynamodb_endpoint_policy2" {
  statement {
    effect    = "Deny"
    actions   = ["dynamodb:*"]
    resources = ["*"]

    principals {
      type        = "*"
      identifiers = ["*"]
    }

    condition {
      test     = "StringNotEquals"
      variable = "aws:sourceVpce"

      values = [module.vpc2.vpc_id]
    }
  }
}

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

No branches or pull requests

5 participants