I think what you think is "kludgey" is the right way to do it.
For my purposes, where we operate in multiple AWS accounts across multiple regions, I've developed a module with no resources, but which just sets outputs based on a set of inputs, so for example, I can do:
module "metadata" {
source = "../modules/aws-metadata"
account = "main"
region = "pdx"
vpc = "nonprod"
env = "beta"
}
provider "aws" {
region = "${module.metadata.region_name}" # us-west-2 in this case
}
resource "aws_instance" "app" {
count = 3
vpc_security_group_ids = [
"${module.metadata.default_security_group}",
]
subnet_id = "${element(split(",", module.metadata.public_subnets), count.index)}"
#...
So the various outputs are lookups in big maps of, for example, the list of public subnets in the given account, region, vpc combination. In addition to subnets and security group IDs, we've got VPC IDs, Consul datacenter names and paths, cross-account role ARNs, standard tag values, all sorts of things.