Terraform, ElasticSearch: This site can’t be reached - terraform

I provisioned Elasticsearch. I got URL outputs of "domain_endpoint", "domain_hostname", "kibana_endpoint" and "kibana_hostname". But, I cannot hit any of these URLS. I got, "This site can’t be reached". What do I miss? Below is the code:
main.tf:
module "elasticsearch" {
source = "git::https://github.com/cloudposse/terraform-aws-elasticsearch.git?ref=tags/0.24.1"
security_groups = [data.terraform_remote_state.vpc.outputs.default_security_group_id]
vpc_id = data.terraform_remote_state.vpc.outputs.vpc_id
zone_awareness_enabled = var.zone_awareness_enabled
subnet_ids = slice(data.terraform_remote_state.vpc.outputs.private_subnets, 0, 2)
elasticsearch_version = var.elasticsearch_version
instance_type = var.instance_type
instance_count = var.instance_count
encrypt_at_rest_enabled = var.encrypt_at_rest_enabled
dedicated_master_enabled = var.dedicated_master_enabled
create_iam_service_linked_role = var.create_iam_service_linked_role
kibana_subdomain_name = var.kibana_subdomain_name
ebs_volume_size = var.ebs_volume_size
dns_zone_id = var.dns_zone_id
kibana_hostname_enabled = var.kibana_hostname_enabled
domain_hostname_enabled = var.domain_hostname_enabled
advanced_options = {
"rest.action.multi.allow_explicit_index" = "true"
}
context = module.this.context
}
terraform.tfvars:
enabled = true
region = "us-west-2"
namespace = "dev"
stage = "abcd"
name = "abcd"
instance_type = "m5.xlarge.elasticsearch"
elasticsearch_version = "7.7"
instance_count = 2
zone_awareness_enabled = true
encrypt_at_rest_enabled = false
dedicated_master_enabled = false
elasticsearch_subdomain_name = "abcd"
kibana_subdomain_name = "abcd"
ebs_volume_size = 250
create_iam_service_linked_role = false
dns_zone_id = "Z08006012KJUIEOPDLIUQ"
kibana_hostname_enabled = true
domain_hostname_enabled = true

You are placing your ES domain in VPC in private subnets. It does not matter if its public or private subent, public access does not apply here. From the AWS docs:
To perform even basic GET requests, your computer must be able to connect to the VPC. This connection often takes the form of a VPN, managed network, or proxy server.
Even if you place it in public subnet, it will not be accessible over internet. A popular solution to this issue is through ssh tunnel which is also described in AWS docs for ES:
Testing VPC Domains

Related

How to refer to resource created via module in same file?

Here is the setup
a module to create CloudFront distribution
use CloudFront distribution module to create a distribution for web app
add route53 record for the web app to point to CloudFront distribution
Here is the code
locals {
globals = jsondecode(file("${path.module}/../../../globals.json"))
}
module "cloudfront_distribution" {
source = "../../../modules/cloudfront-distribution/"
env = "prod"
resource_name = "www-example-com"
cloudfront_domain_name = "www.example.com"
cloudfront_domain_aliases = ["www.example.com"]
origin_domain_name = "app.example-origin.com"
subdomain_name = ""
price_class = "PriceClass_100"
origin_https_port = 443
origin_http_port = 80
origin_ssl_protocols = ["TLSv1.2"]
is_route53_record_needed = false
is_prerender_function_attached = true
}
resource "aws_route53_record" "www_example_com" {
zone_id = "123456"
name = "www"
type = "CNAME"
ttl = 5
records = [module.cloudfront_distribution.domain_name]
}
I am getting an error in the last line where I am trying to reference to the domain name of the CloudFront created to create the route53 record. This domain name is something like this d8493jg8r.cloudfront.net
You have to declare the distribution as an output inside the module. Then you can reference the module's outputs at the top level.

Terraform: Iterating a resources over multiple values?

I'm testing the PAN-OS provider from Palo Alto networks, with the goal of configuring a firewall as-code. I can easily make a security policy:
resource "panos_security_policy" "security_policy" {
rule {
name = var.name
source_zones = var.source_zones
source_addresses = var.source_addresses
source_users = var.source_users
destination_zones = var.destination_zones
destination_addresses = var.destination_addresses
applications = var.applications
services = var.services
categories = var.categories
action = var.action
}
}
I have 50+ rules that will need to be managed this way. I could brute-force each rule as an individual resource, or I could use a module with mapped values. But both of those seem like a lot of manual work and hard to maintain. Any ideas for the most efficient way to iterate this resource over a set of values? Anyone who has had to manage a large AWS security group with lots of rules may know of something.
You can use a for_each loop, e.g.
for_each = { for k, v in var.rules : k => v }
name = each.key
source_zones = each.value.source_zones
source_addresses = each.value.source_addresses
source_users = each.value.source_users
...
on variables file:
rules = {
rulename1 = {
source_zones = "foo"
source_address = "bar"
source_users = "baz"
}
rulename2 = {
source_zones = "foo"
source_address = "biz"
source_users = "buz"
}
}
Make sure to read this if you need further details.

AWS Redshift Terraform module: final_snapshot_identifier

I use the AWS Redshift Terraform module, https://github.com/terraform-aws-modules/terraform-aws-redshift to provision redshift. Per document, final_snapshot_identifier is not required. But, I got the error,
Error: only alphanumeric characters and hyphens allowed in "final_snapshot_identifier".
The document says, "final_snapshot_identifier: (Optional) The identifier of the final snapshot that is to be created immediately before deleting the cluster. If this parameter is provided, 'skip_final_snapshot' must be false", I can solve this problem by adding the code,
final_snapshot_identifier = var.final_snapshot_identifier
skip_final_snapshot = true
But, why?
module "redshift" {
source = "terraform-aws-modules/redshift/aws"
version = "2.7.0"
#redshift_subnet_group_name = var.redshift_subnet_group_name
subnets = data.terraform_remote_state.vpc.outputs.redshift_subnets
#parameter_group_name = var.parameter_group_name
cluster_identifier = var.cluster_identifier
cluster_database_name = var.cluster_database_name
encrypted = false
cluster_master_password = var.cluster_master_password
cluster_master_username = var.cluster_master_username
cluster_node_type = var.cluster_node_type
cluster_number_of_nodes = var.cluster_number_of_nodes
enhanced_vpc_routing = false
publicly_accessible = true
vpc_security_group_ids = [module.sg.this_security_group_id]
final_snapshot_identifier = var.final_snapshot_identifier
skip_final_snapshot = true
}
If you are providing value for final snapshot idenitifier,skip_final_snapshot should be false. But you have given as true
final_snapshot_identifier = var.final_snapshot_identifier
skip_final_snapshot = true

Terraform: Specify specific Docker Network Name for Output

I have a Containerized Network Function (CNF) that connects to three Docker Networks:
...
ip_address = "172.17.0.3"
ip_prefix_length = 16
ipc_mode = "private"
log_driver = "json-file"
log_opts = {}
logs = false
max_retry_count = 0
memory = 4096
memory_swap = -1
must_run = true
name = "c-router-52"
network_data = [
{
gateway = "172.17.0.1"
ip_address = "172.17.0.3"
ip_prefix_length = 16
network_name = "bridge"
},
{
gateway = "172.31.0.1"
ip_address = "172.31.0.4"
ip_prefix_length = 16
network_name = "inside-net"
},
{
gateway = "172.30.0.1"
ip_address = "172.30.0.3"
ip_prefix_length = 16
network_name = "outside-net"
},
]
network_mode = "default"
...
And I am trying to grab the 'outside-net' IP address for use as an input for another container. I am specifying like so:
${docker_container.c-router-52.network_data[2].ip_address}
When its the third element, it works fine.... But the problem is that Terraform (or Docker, one of the two) doesn't always put the 'outside-net' as the third network :(
Is there a way to specify the [network_name="outside-net"] rather than an index number?
Since your code example isn't complete I'm having to guess a little here, but it seems like what you want is a mapping from network name to IP address. You can derive such a data structure from your resource configuration using a for expression, which you can assign to a local value for use elsewhere in the configuration:
locals {
container_ip_addresses = {
for net in docker_container.c-router-52.network_data :
net.network_name => net.ip_address
}
}
With the above definition in your module, you can refer to local.container_ip_addresses elsewhere in your module to refer to this mapping, such as local.container_ip_addresses["outside-net"] to access the outside-net address in particular.
With the network_data structure you showed in your configuration, local.container_ip_addresses would have the following value:
{
bridge = "172.17.0.3"
inside-net = "172.31.0.4"
outside-net = "172.30.0.3"
}
If you need to access the other attributes of those network_data objects, rather than just the ip_address, you can generalize this by making the values of the mapping be the full network objects:
locals {
container_networks = {
for net in docker_container.c-router-52.network_data :
net.network_name => net
}
}
...which would then allow you to access all of the attributes via the network name keys:
local.container_networks["outside-net"].ip_address
local.container_networks["outside-net"].gateway
local.container_networks["outside-net"].ip_prefix_length

Terraform: How to get value of second public ip in module cloudposse ec2

How I can get value of second IP address from Terraform module EC2.
Module- https://github.com/cloudposse/terraform-aws-ec2-instance
I've created instance EC2 with parameter additional_ips_count = 1. In this situation instance has create with two network interface and I need get value public IP address of second network interface.
Normally the module allows me to extract the value of public ip from the value of public_ip. For example, if I create a module called server, I can get the value of the public IP address from the first network interface using the value module.server.public_ip but how to do it for the second network created using a variable additional_ips_count = 1.
You can parse out the values for the value returned from the output module.multiple_ip.additional_eni_ids.
module "multiple_ip" {
source = "git::https://github.com/cloudposse/terraform-aws-ec2-instance.git?ref=master"
ssh_key_pair = var.key_name
vpc_id = var.vpc_id
security_groups = [data.aws_security_group.this.id]
subnet = data.aws_subnet.private_subnet.id
associate_public_ip_address = true
name = "multiple-ip"
namespace = "eg"
stage = "dev"
additional_ips_count = 1
ebs_volume_count = 2
allowed_ports = [22, 80, 443]
instance_type = var.instance_type
}
output "multiple_ip_additional_eni_ids" {
value = module.multiple_ip.additional_eni_ids
}
output "z_additional_eni_public_ip" {
value = values(module.multiple_ip.additional_eni_ids)[0]
}
This will return the ip want.
Outputs:
multiple_ip_additional_eni_ids = {
"eni-0cc853fb9301b2bc8" = "100.20.97.243"
}
z_additional_eni_public_ip = 100.20.97.243

Resources