diff --git a/.gitignore b/.gitignore index c8f4224..7b75fb8 100644 --- a/.gitignore +++ b/.gitignore @@ -73,3 +73,4 @@ terraform.tfstate.d/ terraform.tfstate terraform.tfstate.backup .terraform.lock.hcl +.terraform.tfstate.lock.info \ No newline at end of file diff --git a/steps/aws/06-team-working/README.md b/steps/aws/06-team-working/README.md index d91eadf..694cb05 100644 --- a/steps/aws/06-team-working/README.md +++ b/steps/aws/06-team-working/README.md @@ -22,6 +22,30 @@ The module must be configurable through the following settings : | rds_instance_password | - | (sensitive) | | rds_instance_port | 3306 | 3306 | -To simplify the module, the deployment will only use the default VPC of your AWS account and all resources will be in the default subnet (see datasources.tf). Other resources in your module may be needed to deploy main components (AMI, Security Group...). Note that the DB instance port will have to be opened in the instance security group. +To simplify the module, the deployment will only use the default VPC of your AWS account and all resources will be in the first VPC subnet. Other resources in your module may be needed to deploy main components (AMI, Security Group...). Note that the DB instance port will have to be opened in the instance security group. +See main.tf to view how your module is expected to be used +See variables.tf to configure your rds instance credentials +Bonus : the prefered way to ssh connect to an EC2 instance is the EC2 Instance Connect Endpoint. Create the *aws_ec2_managed_prefix_list* datasource and the *aws_ec2_instance_connect_endpoint* resource to enable the secure connection through SSH by pluging the EICE feature to you VCP subnet. + +### Check + +The lab will be successful if your EC2 instance can connect your RDS database using your credentials : +```bash +# Install mariadb client +[ec2-user@ip-172-31-33-206 ~]$ sudo dnf install mariadb105 -y +[...] +# Check connection to RDS instance +[ec2-user@ip-172-31-33-206 ~]$ mariadb -h mysqldb.cze4eymgsizp.eu-west-1.rds.amazonaws.com -u cdarcy -p +Enter password: +Welcome to the MariaDB monitor. Commands end with ; or \g. +Your MySQL connection id is 27 +Server version: 8.0.39 Source distribution + +Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. + +Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. + +MySQL [(none)]> +``` \ No newline at end of file diff --git a/steps/aws/06-team-working/main.tf b/steps/aws/06-team-working/main.tf index e69de29..a0a48b4 100644 --- a/steps/aws/06-team-working/main.tf +++ b/steps/aws/06-team-working/main.tf @@ -0,0 +1,18 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "5.77.0" + } + } +} + +module my-app-instance { + source = "./modules/myschoolapp-module" + my_app_env = "development" + ec2_instance_count = 2 + rds_instance_size = 20 + rds_instance_id = "" + rds_instance_user = "" + rds_instance_password = "" +} diff --git a/steps/aws/06-team-working/modules/my-app-module/datasources.tf b/steps/aws/06-team-working/modules/my-app-module/datasources.tf new file mode 100644 index 0000000..cdccad8 --- /dev/null +++ b/steps/aws/06-team-working/modules/my-app-module/datasources.tf @@ -0,0 +1,12 @@ +# Get the default VPC ID +data "aws_vpc" "default" { + default = true +} + +# Get the default subnet IDs in the default VPC +data "aws_subnets" "default" { + filter { + name = "vpc-id" + values = [data.aws_vpc.default.id] + } +} \ No newline at end of file diff --git a/steps/aws/06-team-working/modules/my-app-module/resources.tf b/steps/aws/06-team-working/modules/my-app-module/resources.tf index 3d8d481..2320a64 100644 --- a/steps/aws/06-team-working/modules/my-app-module/resources.tf +++ b/steps/aws/06-team-working/modules/my-app-module/resources.tf @@ -1,7 +1,7 @@ # Define the AWS RDS instance resource -# resource "aws_db_instance" "default" { +# resource "aws_db_instance" "myschoolapp_db" { # } # Define the EC2 instance resources -# resource "aws_instance" "default" { +# resource "aws_instance" "myschoolapp_compute" { # } \ No newline at end of file diff --git a/steps/aws/06-team-working/solution/main.tf b/steps/aws/06-team-working/solution/main.tf index dc1af82..b655ff3 100644 --- a/steps/aws/06-team-working/solution/main.tf +++ b/steps/aws/06-team-working/solution/main.tf @@ -1,9 +1,18 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "5.77.0" + } + } +} + module my-app-instance { source = "./modules/myschoolapp-module" my_app_env = "development" ec2_instance_count = 2 rds_instance_size = 20 - rds_instance_id = "cdarcymysqldb" - rds_instance_user = "cdarcy" - rds_instance_password = "cdarcy_mysqldb_61672" -} \ No newline at end of file + rds_instance_id = "mysqldb" + rds_instance_user = var.rds_dbuser + rds_instance_password = var.rds_dbpassword +} diff --git a/steps/aws/06-team-working/solution/modules/myschoolapp-module/datasources.tf b/steps/aws/06-team-working/solution/modules/myschoolapp-module/datasources.tf index cdccad8..550348e 100644 --- a/steps/aws/06-team-working/solution/modules/myschoolapp-module/datasources.tf +++ b/steps/aws/06-team-working/solution/modules/myschoolapp-module/datasources.tf @@ -9,4 +9,17 @@ data "aws_subnets" "default" { name = "vpc-id" values = [data.aws_vpc.default.id] } +} + +# Get EC2 instance connect prefix list +data "aws_ec2_managed_prefix_list" "ec2_instance_connect" { + filter { + name = "owner-id" + values = ["AWS"] + } + + filter { + name = "prefix-list-name" + values = ["com.amazonaws.eu-west-1.ec2-instance-connect"] + } } \ No newline at end of file diff --git a/steps/aws/06-team-working/solution/modules/myschoolapp-module/resources.tf b/steps/aws/06-team-working/solution/modules/myschoolapp-module/resources.tf index e23bda7..92b75f2 100644 --- a/steps/aws/06-team-working/solution/modules/myschoolapp-module/resources.tf +++ b/steps/aws/06-team-working/solution/modules/myschoolapp-module/resources.tf @@ -1,3 +1,50 @@ +locals { + myschoolapp_subnet = element(data.aws_subnets.default.ids, 0) # Use the first subnet in the list +} + +# Define a security group that allows inbound traffic on the database port +resource "aws_security_group" "db_security_group" { + name = "db_security_group" + description = "Allow inbound traffic on the database port" + vpc_id = data.aws_vpc.default.id + + ingress { + from_port = var.rds_instance_port + to_port = var.rds_instance_port + protocol = "tcp" + security_groups = [ aws_security_group.ec2_security_group.id ] + } + + tags = { + Name = "MySchoolApp DB Traffic SG for ${var.my_app_env} environment" + } +} + +# Define a security group for EC2 instances +resource "aws_security_group" "ec2_security_group" { + name = "ec2_security_group" + description = "Allow inbound traffic on the SSH port for EC2 instance connect" + vpc_id = data.aws_vpc.default.id + + ingress { + from_port = 22 + to_port = 22 + protocol = "tcp" + self = true + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + tags = { + Name = "MySchoolApp EC2 Traffic SG for ${var.my_app_env} environment" + } +} + # Define the RDS instance resource resource "aws_db_instance" "myschoolapp_db" { identifier = var.rds_instance_id @@ -8,7 +55,7 @@ resource "aws_db_instance" "myschoolapp_db" { instance_class = var.rds_instance_class allocated_storage = var.rds_instance_size skip_final_snapshot = true - db_subnet_group_name = aws_db_subnet_group.myschoolapp_db_subnet_group.name + vpc_security_group_ids = [ aws_security_group.db_security_group.id ] # Enable deletion protection to prevent accidental deletion deletion_protection = false @@ -19,50 +66,20 @@ resource "aws_db_instance" "myschoolapp_db" { } } -# Define the DB Subnet Group resource -resource "aws_db_subnet_group" "myschoolapp_db_subnet_group" { - name = "${var.rds_instance_id}-subnet-group" - subnet_ids = data.aws_subnets.default.ids - - tags = { - Name = "MySchoolApp RDS Subnet Group for ${var.my_app_env} environment" - } -} - -# Define a security group that allows inbound traffic on the database port -resource "aws_security_group" "allow_db_traffic" { - name = "allow_db_traffic" - description = "Allow inbound traffic on the database port" - vpc_id = data.aws_vpc.default.id - - ingress { - from_port = var.rds_instance_port - to_port = var.rds_instance_port - protocol = "tcp" - cidr_blocks = [data.aws_vpc.default.cidr_block] - } - -# egress { -# from_port = 0 -# to_port = 0 -# protocol = "-1" -# cidr_blocks = ["0.0.0.0/0"] -# } - - tags = { - Name = "MySchoolApp DB Traffic SG for ${var.my_app_env} environment" - } -} - # Define the EC2 instance resource resource "aws_instance" "myschoolapp_compute" { count = var.ec2_instance_count ami = var.ec2_instance_ami_id instance_type = var.ec2_instance_class - subnet_id = element(data.aws_subnets.default.ids, 0) # Use the first subnet in the list - vpc_security_group_ids = [aws_security_group.allow_db_traffic.id] + subnet_id = local.myschoolapp_subnet + vpc_security_group_ids = [aws_security_group.ec2_security_group.id] tags = { Name = "MySchoolApp EC2 Instance for ${var.my_app_env} environment" } +} + +resource "aws_ec2_instance_connect_endpoint" "myeice" { + subnet_id = local.myschoolapp_subnet + security_group_ids = [ aws_security_group.ec2_security_group.id ] } \ No newline at end of file diff --git a/steps/aws/06-team-working/solution/modules/myschoolapp-module/variables.tf b/steps/aws/06-team-working/solution/modules/myschoolapp-module/variables.tf index e099da8..c7f94ab 100644 --- a/steps/aws/06-team-working/solution/modules/myschoolapp-module/variables.tf +++ b/steps/aws/06-team-working/solution/modules/myschoolapp-module/variables.tf @@ -72,5 +72,5 @@ variable "ec2_instance_class" { variable "ec2_instance_ami_id" { type = string description = "The ID of the AMI to use for the EC2 instance" - default = "ami-046b5b8111c19b3ac" + default = "ami-0fcc0bef51bad3cb2" } diff --git a/steps/aws/06-team-working/solution/variables.tf b/steps/aws/06-team-working/solution/variables.tf new file mode 100644 index 0000000..4b6ce0b --- /dev/null +++ b/steps/aws/06-team-working/solution/variables.tf @@ -0,0 +1,12 @@ + +variable "rds_dbuser" { + # configure eternally through a secret or an environment variable, eg. + # export TF_rds_dbuser="youruser" + sensitive = true +} + +variable "rds_dbpassword" { + # configure eternally through a secret or an environment variable, eg. + # export TF_rds_dbpassword="yourpassword" + sensitive = true +} \ No newline at end of file diff --git a/steps/aws/06-team-working/variables.tf b/steps/aws/06-team-working/variables.tf new file mode 100644 index 0000000..4b6ce0b --- /dev/null +++ b/steps/aws/06-team-working/variables.tf @@ -0,0 +1,12 @@ + +variable "rds_dbuser" { + # configure eternally through a secret or an environment variable, eg. + # export TF_rds_dbuser="youruser" + sensitive = true +} + +variable "rds_dbpassword" { + # configure eternally through a secret or an environment variable, eg. + # export TF_rds_dbpassword="yourpassword" + sensitive = true +} \ No newline at end of file