I have this terraform script:
provider "aws" {
region = "us-weast-1"
}
resource "aws_security_group" "allow_all" {
name = "allow_all"
description = "Allow all inbound traffic"
ingress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
vpc_id = "vpc-154c1701"
}
resource "aws_instance" "wso2-testing" {
ami = "ami-0f9cf087c1f27d9b1"
instance_type = "t2.small"
key_name = "mykeypair"
vpc_security_group_ids = ["${aws_security_group.allow_all.id}"]
}
The machine is created correctly, but i canĀ“t connect to ec2 instance using my key pair with ssh.
Always i have the error:
ssh: connect to host x.x.x.x port 22: Operation timed out
The VPC es aws default with internet gateway
You can add your own IP to security group using below snippet:
data "http" "myip"{
url = "https://ipv4.icanhazip.com"
}
ingress {
# TCP (change to whatever ports you need)
from_port = 0
to_port = 0
protocol = "-1"
# Please restrict your ingress to only necessary IPs and ports.
# Opening to 0.0.0.0/0 can lead to security vulnerabilities.
cidr_blocks = ["${chomp(data.http.myip.body)}/32"]
}
egress {
# Outbound traffic is set to all
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
You need to add your own IP into inbound rule of your security group.
Check my blog or git sample
https://sv-technical.blogspot.com/2019/12/terraform.html
https://github.com/svermaji/terraform
HTH
Related
I am deploying my AWS resources with Terraform, one of the resources happen to be of type aws_instance (EC2) this is acting as my Bastion Host. It is on the public subnet, I created a security group which allows SSH from my home IP. This security group works, as i am able to SSH into the Bastion Host.
resource "aws_security_group" "allow_home_to_bastion_ssh" {
name = "Home to bastion"
description = "Allow SSH - Home to Bastion"
vpc_id = var.vpc_id
ingress {
description = "SSH from Bastion"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["<My-Home-IP>/32"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
tags = {
Name = "Home to bastion"
}
}
I also created other security groups i'm adding to the node group configuration under the remote_access section as shown below
resource "aws_eks_node_group" "node_group" {
cluster_name = var.cluster_name
node_group_name = var.node_group_name
node_role_arn = var.node_pool_role_arn
subnet_ids = [var.subnet_1_id, var.subnet_2_id]
instance_types = ["t2.medium"]
scaling_config {
desired_size = 1
max_size = 1
min_size = 1
}
update_config {
max_unavailable = 1
}
remote_access {
ec2_ssh_key = "<My-Key-Pair.pem>"
source_security_group_ids = [
var.allow_http_id,
var.allow_ssh_id,
var.allow_tls_id,
var.allow_bastion_to_eks_node_id
]
}
}
The allow_ssh_id is shown below, as shown above this is added to the source_security_group_ids. I expect this to allow me to SSH from my Bastion Host to the EKS Node created by the node group since theyre all on the same CIDR range and VPC
resource "aws_security_group" "allow_ssh" {
name = var.sg_allow_ssh_name
description = "Allow SSH from CIDR"
vpc_id = var.vpc_id
ingress {
description = "SSH from VPC"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = [var.vpc_cidr_block]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = [var.vpc_cidr_block]
ipv6_cidr_blocks = ["::/0"]
}
the allow_bastion_to_eks_node_id is an additional security group i created which is also added to the node group, this is to specifically allow SSH the External IP of the Bastion Host onto the EKS Node. See code below
resource "aws_security_group" "bastion_allow_ssh" {
name = var.sg_allow_bastion_ssh_name
description = "Allow SSH - Bastion to EKS"
vpc_id = var.vpc_id
ingress {
description = "SSH from Bastion"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["${var.sg_allow_bastion_elastic_ssh}/32"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
tags = {
Name = var.sg_allow_bastion_ssh_name
}
}
as shown above, i am using the bastion elastic ip. Yet i cannot SSH to my EKS node from the Bastion Host. Not sure what is going on.
Not the bastion host is in a public subnet but using the same VPC as the EKS Node which is in the private subnet
SSH ERROR
ssh: connect to host port 22: Operation timed out
I hope everyone that sees this is doing well.
I'm still learning the ropes with Terraform and AWS.
I've created a VPC with 4 subnets in it. 1 subnet is public and the other 3 are private. I currently have 1 EC2 instance in my public subnet (a bastion box/server). I have also created a security group for this instance and have created a NACL rule that allows me to connect via ssh to this instance from my IP only. For some reason when I try to ssh onto this instance my terminal hangs and I see the following message:
OpenSSH_8.2p1 Ubuntu-4ubuntu0.1, OpenSSL 1.1.1f 31 Mar 2020
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 19: include /etc/ssh/ssh_config.d/*.conf matched no files
debug1: /etc/ssh/ssh_config line 21: Applying options for *
debug1: Connecting to 'instance_public_ip [instance_public_ip] port 22
and then it tells me the connection timed out.
I changed the rule to allow an ssh connection from all IPs (i.e. 0.0.0.0/0) but still get the same problem. The terraform code for the infrastructure is as follows:
# Elastic IP for bastion server
resource "aws_eip" "bastion_eip" {
instance = aws_instance.Bastion.id
vpc = true
}
# EIP association for bastion server
resource "aws_eip_association" "eip_assoc" {
instance_id = aws_instance.Bastion.id
allocation_id = aws_eip.bastion_eip.id
}
# Create internet gateway
resource "aws_internet_gateway" "main-gateway" {
vpc_id = aws_vpc.main-vpc.id
tags = {
Name = "main"
}
}
# Create route table for public subnet
resource "aws_route_table" "public-route-table" {
vpc_id = aws_vpc.main-vpc.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.main-gateway.id
}
tags = {
Name = "public-route-table"
}
}
# Create subnet 4
resource "aws_subnet" "subnet-4" {
vpc_id = aws_vpc.main-vpc.id
cidr_block = "10.0.4.0/24"
availability_zone = "eu-west-2a"
tags = {
Name = "subnet-public"
}
}
# Associate subnet 4 with public route table
resource "aws_route_table_association" "subnet-4" {
subnet_id = aws_subnet.subnet-4.id
route_table_id = aws_route_table.public-route-table.id
}
# Create bastion server security group (subnet 4)
resource "aws_security_group" "bastion-sg" {
name = "bastion-sg"
description = "Allow web traffic from specific IPs"
vpc_id = aws_vpc.main-vpc.id
# SSH Traffic
ingress {
description = "SSH"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"] #allow web traffic.
}
egress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "allow_access_bastion_server"
}
}
# Create NACL for public subnet with Prod server & bastion server
resource "aws_network_acl" "public_nacl" {
vpc_id = aws_vpc.main-vpc.id
subnet_ids = [aws_subnet.subnet-4.id]
# Allow inbound http traffic from internet
ingress {
protocol = "tcp"
rule_no = 100
action = "allow"
cidr_block = "0.0.0.0/0"
from_port = 80
to_port = 80
}
# Allow outbound http traffic to internet
egress {
protocol = "tcp"
rule_no = 100
action = "allow"
cidr_block = "0.0.0.0/0"
from_port = 80
to_port = 80
}
# Allow inbound SSH traffic from specific IP
ingress {
protocol = "tcp"
rule_no = 103
action = "allow"
cidr_block = "0.0.0.0/0"
from_port = 22
to_port = 22
}
# Allow outbound SSH traffic from specific IP
egress {
protocol = "tcp"
rule_no = 103
action = "allow"
cidr_block = "0.0.0.0/0"
from_port = 22
to_port = 22
}
tags = {
Name = "public NACL"
}
}
# Create bastion box
resource "aws_instance" "Bastion" {
ami = var.ami-id
instance_type = var.instance-type
key_name = "aws_key_name"
vpc_security_group_ids = ["security_group_id"]
subnet_id = "subnet_id"
tags = {
Name = "Bastion Server"
}
}
I've been looking at this a while now and can't really see where I've gone wrong. Is the issue with my security group or my IGW or route table? If there's any other information you feel is needed let me know :) and thanks for any help in advance
I think the problem is on the security group.
# SSH Traffic
ingress {
description = "SSH"
from_port = 0 # SSH client port is not a fixed port
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"] #allow web traffic. 46.64.73.251/32
}
egress {
from_port = 22
to_port = 0 # SSH client port is not a fixed port
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
I need to create aws security group rule resource aws_security_group_rule, attach it to AWS EC2 Windows instance and be able to RDP into it from anywhere.
sg.tf
resource "aws_security_group" "My_VPC_Security_Group" {
vpc_id = aws_vpc.My_VPC.id
name = "My VPC Security Group"
description = "My VPC Security Group"
}
You could use the following where 3389 is default RDP port:
resource "aws_security_group" "My_VPC_Security_Group" {
vpc_id = aws_vpc.My_VPC.id
name = "My VPC Security Group"
description = "My VPC Security Group"
ingress {
from_port = 3389
to_port = 3389
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
The below code worked for me, which creates security group rules using aws_security_group_rule as I wanted.
resource "aws_security_group" "My_VPC_Security_Group" {
vpc_id = aws_vpc.My_VPC.id
name = "My VPC Security Group"
description = "My VPC Security Group"
}
resource "aws_security_group_rule" "ingress_rule" {
type = "ingress"
from_port = 3389
to_port = 3389
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
security_group_id = aws_security_group.My_VPC_Security_Group.id
}
resource "aws_security_group_rule" "egress_rule" {
type = "egress"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
security_group_id = aws_security_group.My_VPC_Security_Group.id
}
I have creating t2.micro instance using following security group in terraform.
Allow 80 Port
resource "aws_security_group" "access-http" {
name = "Allow-80"
description = "Allow 80 inbound traffic"
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
Allow 8080 Port
resource "aws_security_group" "access-http-web" {
name = ""
description = "Allow 8080 inbound traffic"
ingress {
from_port = 8080
to_port = 8080
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
Allow 22 Port
resource "aws_security_group" "access-ssh" {
name = "Access-ssh"
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 1194
to_port = 1194
protocol = "udp"
cidr_blocks = ["0.0.0.0/0"]
}
}
If any security issue came in due this security group. I have used Network(VPC) and Subnet option is default selected one. Please advise me.
If this was me I would terminate the instance and create a new one. When you create the "Allow 22 Port" security group you should make sure the source address is your current IP address. If your public (home/office) IP address is dynamic then you will need to check each time you connect and update it in the Security Group via the console if it has changed.
I want to create 2 VPC security groups.
One for the Bastion host of the VPC and one for the Private subnet.
# BASTION #
resource "aws_security_group" "VPC-BastionSG" {
name = "VPC-BastionSG"
description = "The sec group for the Bastion instance"
vpc_id = "aws_vpc.VPC.id"
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["my.super.ip/32"]
}
egress {
# Access to the Private subnet from the bastion host[ssh]
from_port = 22
to_port = 22
protocol = "tcp"
security_groups = ["${aws_security_group.VPC-PrivateSG.id}"]
}
egress {
# Access to the Private subnet from the bastion host[jenkins]
from_port = 8686
to_port = 8686
protocol = "tcp"
security_groups = ["${aws_security_group.VPC-PrivateSG.id}"]
}
tags = {
Name = "VPC-BastionSG"
}
}
# PRIVATE #
resource "aws_security_group" "VPC-PrivateSG" {
name = "VPC-PrivateSG"
description = "The sec group for the private subnet"
vpc_id = "aws_vpc.VPC.id"
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
security_groups = ["${aws_security_group.VPC-BastionSG.id}"]
}
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
security_groups = ["${aws_security_group.VPC-PublicSG.id}"]
}
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
security_groups = ["${aws_security_group.VPC-PublicSG.id}"]
}
ingress {
from_port = 3306
to_port = 3306
protocol = "tcp"
security_groups = ["${aws_security_group.VPC-PublicSG.id}"]
}
ingress {
from_port = 8686
to_port = 8686
protocol = "tcp"
security_groups = ["${aws_security_group.VPC-BastionSG.id}"]
}
ingress {
# ALL TRAFFIC from the same subnet
from_port = 0
to_port = 0
protocol = "-1"
self = true
}
egress {
# ALL TRAFFIC to outside world
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "VPC-PrivateSG"
}
}
When I terraform plan it, this error is returned:
**`Error configuring: 1 error(s) occurred:
* Cycle: aws_security_group.VPC-BastionSG, aws_security_group.VPC-PrivateSG`**
If I comment out the ingress rules for the BastionSG from the PrivateSG the plan executes fine.
Also, if I comment out the egress rules for the PrivateSG from the BastionSG it also executes fine.
The AWS Scenario 2 for building a VPC with Public/Private subnets and Bastion host describes the architecture I am trying to setup.
I have the exact same settings configured via the AWS console and it plays fine.
Why isn't Terraform accepting it?
Is there another way to connect the Bastion security group with the Private security group?
EDIT
As I understand there is a circular reference between the two sec groups that somehow needs to break even though in AWS it is valid.
So, I thought of allowing all outbound traffic (0.0.0.0/0) from the Bastion sec group and not specifying it to individual security groups.
Would it have a bad security impact?
Terraform attempts to build a dependency chain for all of the resources defined in the folder that it is working on. Doing this enables it to work out if it needs to build things in a specific order and is pretty key to how it all works.
Your example is going to fail because you have a cyclic dependency (as Terraform helpfully points out) where each security group is dependent on the other one being created already.
Sometimes these can be tricky to solve and may mean you need to rethink what you're trying to do (as you mention, one option would be to simply allow all egress traffic out from the bastion host and only restrict the ingress traffic on the private instances) but in this case you have the option of using the aws_security_group_rule resource in combination with the aws_security_group resource.
This means we can define empty security groups with no rules in them at first which we can then use as targets for the security group rules we create for the groups.
A quick example might look something like this:
resource "aws_security_group" "bastion" {
name = "bastion"
description = "Bastion security group"
}
resource "aws_security_group_rule" "bastion-to-private-ssh-egress" {
type = "egress"
from_port = 22
to_port = 22
protocol = "tcp"
security_group_id = "${aws_security_group.bastion.id}"
source_security_group_id = "${aws_security_group.private.id}"
}
resource "aws_security_group" "private" {
name = "private"
description = "Private security group"
}
resource "aws_security_group_rule" "private-from-bastion-ssh-ingress" {
type = "ingress"
from_port = 22
to_port = 22
protocol = "tcp"
security_group_id = "${aws_security_group.private.id}"
source_security_group_id = "${aws_security_group.bastion.id}"
}
Now, Terraform can see that the dependency chain says that both security groups must be created before either of those security group rules as both of them are dependent on the groups already having been created.