diff --git a/.DS_Store b/.DS_Store index fa0f567..724735a 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/.github/.DS_Store b/.github/.DS_Store new file mode 100644 index 0000000..385f4b4 Binary files /dev/null and b/.github/.DS_Store differ diff --git a/.github/workflows/unit-testing.yaml b/.github/workflows/unit-testing.yaml new file mode 100644 index 0000000..b5ae8e9 --- /dev/null +++ b/.github/workflows/unit-testing.yaml @@ -0,0 +1,101 @@ +name: Unit Testing + +on: + workflow_dispatch: + +permissions: + actions: read + contents: read + security-events: write +#### +jobs: + tf-formatting: + name: 'Terraform Formatting' + runs-on: ubuntu-latest + steps: + - name: 'Checkout GitHub Repo' + uses: actions/checkout@v4 + + - name: 'Set up Terraform' + uses: hashicorp/setup-terraform@v1 + with: + terraform_version: 'latest' + + - name: 'Terraform init' + run: terraform init + + - name: 'Terraform Format' + run: terraform fmt -check + + - name: 'Terraform validate' + run: terraform validate + + - name: 'TFLint' + run: | + tflint --init + tflint +#### + trivy: + name: Trivy Vulnerability Scan + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Run Trivy vulnerability scanner in repo mode + uses: aquasecurity/trivy-action@0.28.0 + with: + scan-type: 'fs' + severity: 'CRITICAL' + format: 'sarif' + output: 'trivy-results.sarif' + ignore-unfixed: true +#### + - name: Upload Trivy scan results to GitHub Security tab + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: 'trivy-results.sarif' + + iac_scan: + name: IaC Scan + runs-on: ubuntu-24.04 + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Run Trivy vulnerability scanner in IaC mode + uses: aquasecurity/trivy-action@0.28.0 + with: + scan-type: 'config' + hide-progress: false + format: 'sarif' + output: 'trivy-results.sarif' + exit-code: '1' + severity: 'CRITICAL' + + - name: Upload Trivy scan results to GitHub Security tab + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: 'trivy-results.sarif' + + tfsec: + name: 'tfsec' + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: 'Install Tfsec' + uses: aquasecurity/tfsec-sarif-action@21ded20e8ca120cd9d3d6ab04ef746477542a608 + with: + sarif_file: tfsec.sarif +##### + checkov: + name: Run Checkov + runs-on: ubuntu-latest + steps: + - name: 'Run Checkov' + uses: bridgecrewio/checkov-action@v12 + with: + output_format: cli,sarif + output_file_path: console,results.sarif diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1c99dc1 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.terraform/ diff --git a/Azure-WAN/.gitignore b/Azure-WAN/.gitignore new file mode 100644 index 0000000..1e1ac26 --- /dev/null +++ b/Azure-WAN/.gitignore @@ -0,0 +1,41 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl + +# Ignore the .DS_Store files created by macOS +.DS_Store \ No newline at end of file diff --git a/Documentation b/Documentation new file mode 100644 index 0000000..b920e34 --- /dev/null +++ b/Documentation @@ -0,0 +1,46 @@ +######################################################### +# Topics I'm going to explore in this module +######################################################### + + +### Conditional logic + - Conditionally create VPC + - Based off the bool the subsequent resources associated to the VPC will be created or not + - Create IGW based off of bool + - That IGW should then have logic in a locals variable, that says. "if the vpc bool == true and the public route table == true then create a route to the internet gateway" + - example logic: + locals{ + create_route_to_igw = var.create_vpc && var.create_igw && local.create_public_route_table + } + - Create NAT Gateway based off of bool + - That NAT should then have logic in a locals variable, that says. "if the vpc bool == true and the private subnet creation == true then create a route to the NAT gateway" + - example logic: + locals{ + create_route_to_nat = var.create_vpc && var.create_igw && local.create_private_route_table + } +### Count + - Couple conditional logic with the Count meta argument + - Based off of the conditions bool will determine how many of the VPCs are created + +### Dynamic Resource Allocation + - Based on how many VPCs are created will result in how many Private, Public Subnets are created + - Along with Route tables for Public and Private subs + - Internet Gateway + - NAT Gateway + +### Dynamic CIDR Blocks + - Use one of the Terraform functions to create CIDRs for subnets based off of the VPC created. + +### Dynamic Resource Creation: + - allow the user to specify how many of a given resource is created + - + +### map(string) variables for tags with string interpolation + - Name + - Environment + - example: + variable "tags"{ + description = "tags for each resource" + type = map(string) + default = {} + } \ No newline at end of file diff --git a/IAM/.DS_Store b/IAM/.DS_Store new file mode 100644 index 0000000..d65e215 Binary files /dev/null and b/IAM/.DS_Store differ diff --git a/IAM/.gitignore b/IAM/.gitignore new file mode 100644 index 0000000..1e1ac26 --- /dev/null +++ b/IAM/.gitignore @@ -0,0 +1,41 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl + +# Ignore the .DS_Store files created by macOS +.DS_Store \ No newline at end of file diff --git a/IAM/CloudWatch-Logging/.gitignore b/IAM/CloudWatch-Logging/.gitignore new file mode 100644 index 0000000..1e1ac26 --- /dev/null +++ b/IAM/CloudWatch-Logging/.gitignore @@ -0,0 +1,41 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl + +# Ignore the .DS_Store files created by macOS +.DS_Store \ No newline at end of file diff --git a/VPC-Peering/Modules/single-vpc-to-vpc/05-outputs.tf b/IAM/CloudWatch-Logging/main.tf similarity index 100% rename from VPC-Peering/Modules/single-vpc-to-vpc/05-outputs.tf rename to IAM/CloudWatch-Logging/main.tf diff --git a/IAM/CloudWatch-Logging/outputs.tf b/IAM/CloudWatch-Logging/outputs.tf new file mode 100644 index 0000000..e69de29 diff --git a/IAM/CloudWatch-Logging/variables.tf b/IAM/CloudWatch-Logging/variables.tf new file mode 100644 index 0000000..e69de29 diff --git a/IAM/SSM-Policy/.gitignore b/IAM/SSM-Policy/.gitignore new file mode 100644 index 0000000..1e1ac26 --- /dev/null +++ b/IAM/SSM-Policy/.gitignore @@ -0,0 +1,41 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl + +# Ignore the .DS_Store files created by macOS +.DS_Store \ No newline at end of file diff --git a/IAM/SSM-Policy/main.tf b/IAM/SSM-Policy/main.tf new file mode 100644 index 0000000..cccb1d3 --- /dev/null +++ b/IAM/SSM-Policy/main.tf @@ -0,0 +1,86 @@ +### use the IAM policy created for SSM ### + +resource "aws_iam_policy" "ssm_policy" { + name = "AmazonSSMManagedInstanceCore" + path = "/" + description = "SSM policy" + + # Terraform's "jsonencode" function converts a + # Terraform expression result to valid JSON syntax. + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + "Effect": "Allow", + "Action": [ + "ssm:DescribeAssociation", + "ssm:GetDeployablePatchSnapshotForInstance", + "ssm:GetDocument", + "ssm:DescribeDocument", + "ssm:GetManifest", + "ssm:GetParameter", + "ssm:GetParameters", + "ssm:ListAssociations", + "ssm:ListInstanceAssociations", + "ssm:PutInventory", + "ssm:PutComplianceItems", + "ssm:PutConfigurePackageResult", + "ssm:UpdateAssociationStatus", + "ssm:UpdateInstanceAssociationStatus", + "ssm:UpdateInstanceInformation" + ], + "Resource": "*" + }, + { + "Effect": "Allow", + "Action": [ + "ssmmessages:CreateControlChannel", + "ssmmessages:CreateDataChannel", + "ssmmessages:OpenControlChannel", + "ssmmessages:OpenDataChannel" + ], + "Resource": "*" + }, + { + "Effect": "Allow", + "Action": [ + "ec2messages:AcknowledgeMessage", + "ec2messages:DeleteMessage", + "ec2messages:FailMessage", + "ec2messages:GetEndpoint", + "ec2messages:GetMessages", + "ec2messages:SendReply" + ], + "Resource": "*" + } + ] + }) +} + +data "aws_iam_policy_document" "ssm_policy_doc" { + statement { + actions = [ + "sts:AssumeRole" + ] + principals { + type = "Service" + identifiers = ["ec2.amazonaws.com"] + } + effect = "Allow" + } +} + +resource "aws_iam_role" "ssm_role" { + name = "AmazonSSMManagedInstanceCore1" + assume_role_policy = data.aws_iam_policy_document.ssm_policy_doc.json +} + +resource "aws_iam_role_policy_attachment" "attach_ssm_policy" { + role = aws_iam_role.ssm_role.name + policy_arn = aws_iam_policy.ssm_policy.arn +} + +resource "aws_iam_instance_profile" "ssm_profile" { + name = "AmazonSSMManagedInstanceCore2" + role = aws_iam_role.ssm_role.name +} \ No newline at end of file diff --git a/IAM/SSM-Policy/outputs.tf b/IAM/SSM-Policy/outputs.tf new file mode 100644 index 0000000..6916d96 --- /dev/null +++ b/IAM/SSM-Policy/outputs.tf @@ -0,0 +1,18 @@ +output "iam_instance_profile" { + description = "IAM Instance Profile for SSM" + value = aws_iam_instance_profile.ssm_profile.name +} +output "ssm_policy_arn" { + description = "ARN of the SSM IAM Policy" + value = aws_iam_policy.ssm_policy.arn +} + +output "ssm_role_name" { + description = "Name of the SSM IAM Role" + value = aws_iam_role.ssm_role.name +} + +output "aws_iam_policy" { + description = "IAM Policy for SSM" + value = aws_iam_policy.ssm_policy +} \ No newline at end of file diff --git a/IAM/SSM-Policy/variables.tf b/IAM/SSM-Policy/variables.tf new file mode 100644 index 0000000..e69de29 diff --git a/S2S-VPN/.DS_Store b/S2S-VPN/.DS_Store new file mode 100644 index 0000000..05d51ee Binary files /dev/null and b/S2S-VPN/.DS_Store differ diff --git a/S2S-VPN/.gitignore b/S2S-VPN/.gitignore new file mode 100644 index 0000000..1e1ac26 --- /dev/null +++ b/S2S-VPN/.gitignore @@ -0,0 +1,41 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl + +# Ignore the .DS_Store files created by macOS +.DS_Store \ No newline at end of file diff --git a/S2S-VPN/Environments/dev/.gitignore b/S2S-VPN/Environments/dev/.gitignore new file mode 100644 index 0000000..1e1ac26 --- /dev/null +++ b/S2S-VPN/Environments/dev/.gitignore @@ -0,0 +1,41 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl + +# Ignore the .DS_Store files created by macOS +.DS_Store \ No newline at end of file diff --git a/S2S-VPN/Environments/dev/backend.tf b/S2S-VPN/Environments/dev/backend.tf new file mode 100644 index 0000000..e69de29 diff --git a/S2S-VPN/Environments/dev/main.tf b/S2S-VPN/Environments/dev/main.tf new file mode 100644 index 0000000..e69de29 diff --git a/S2S-VPN/Environments/dev/providers.tf b/S2S-VPN/Environments/dev/providers.tf new file mode 100644 index 0000000..e69de29 diff --git a/S2S-VPN/Environments/dev/variables.tf b/S2S-VPN/Environments/dev/variables.tf new file mode 100644 index 0000000..e69de29 diff --git a/S2S-VPN/Environments/prod/.gitignore b/S2S-VPN/Environments/prod/.gitignore new file mode 100644 index 0000000..1e1ac26 --- /dev/null +++ b/S2S-VPN/Environments/prod/.gitignore @@ -0,0 +1,41 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl + +# Ignore the .DS_Store files created by macOS +.DS_Store \ No newline at end of file diff --git a/S2S-VPN/Environments/prod/backend.tf b/S2S-VPN/Environments/prod/backend.tf new file mode 100644 index 0000000..e69de29 diff --git a/S2S-VPN/Environments/prod/main.tf b/S2S-VPN/Environments/prod/main.tf new file mode 100644 index 0000000..e69de29 diff --git a/S2S-VPN/Environments/prod/providers.tf b/S2S-VPN/Environments/prod/providers.tf new file mode 100644 index 0000000..e69de29 diff --git a/S2S-VPN/Environments/prod/variables.tf b/S2S-VPN/Environments/prod/variables.tf new file mode 100644 index 0000000..e69de29 diff --git a/S2S-VPN/Environments/test/.gitignore b/S2S-VPN/Environments/test/.gitignore new file mode 100644 index 0000000..1e1ac26 --- /dev/null +++ b/S2S-VPN/Environments/test/.gitignore @@ -0,0 +1,41 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl + +# Ignore the .DS_Store files created by macOS +.DS_Store \ No newline at end of file diff --git a/S2S-VPN/Environments/test/backend.tf b/S2S-VPN/Environments/test/backend.tf new file mode 100644 index 0000000..e69de29 diff --git a/S2S-VPN/Environments/test/main.tf b/S2S-VPN/Environments/test/main.tf new file mode 100644 index 0000000..e69de29 diff --git a/S2S-VPN/Environments/test/providers.tf b/S2S-VPN/Environments/test/providers.tf new file mode 100644 index 0000000..e69de29 diff --git a/S2S-VPN/Environments/test/variables.tf b/S2S-VPN/Environments/test/variables.tf new file mode 100644 index 0000000..e69de29 diff --git a/S2S-VPN/modules/.DS_Store b/S2S-VPN/modules/.DS_Store new file mode 100644 index 0000000..3d37759 Binary files /dev/null and b/S2S-VPN/modules/.DS_Store differ diff --git a/TransitGatway/.DS_Store b/TransitGatway/.DS_Store new file mode 100644 index 0000000..9498eeb Binary files /dev/null and b/TransitGatway/.DS_Store differ diff --git a/TransitGatway/.gitignore b/TransitGatway/.gitignore new file mode 100644 index 0000000..1e1ac26 --- /dev/null +++ b/TransitGatway/.gitignore @@ -0,0 +1,41 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl + +# Ignore the .DS_Store files created by macOS +.DS_Store \ No newline at end of file diff --git a/TransitGatway/Environments/dev/.gitignore b/TransitGatway/Environments/dev/.gitignore new file mode 100644 index 0000000..1e1ac26 --- /dev/null +++ b/TransitGatway/Environments/dev/.gitignore @@ -0,0 +1,41 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl + +# Ignore the .DS_Store files created by macOS +.DS_Store \ No newline at end of file diff --git a/TransitGatway/Environments/prod/.gitignore b/TransitGatway/Environments/prod/.gitignore new file mode 100644 index 0000000..1e1ac26 --- /dev/null +++ b/TransitGatway/Environments/prod/.gitignore @@ -0,0 +1,41 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl + +# Ignore the .DS_Store files created by macOS +.DS_Store \ No newline at end of file diff --git a/TransitGatway/Environments/test/.gitignore b/TransitGatway/Environments/test/.gitignore new file mode 100644 index 0000000..1e1ac26 --- /dev/null +++ b/TransitGatway/Environments/test/.gitignore @@ -0,0 +1,41 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl + +# Ignore the .DS_Store files created by macOS +.DS_Store \ No newline at end of file diff --git a/VNET/.gitignore b/VNET/.gitignore new file mode 100644 index 0000000..1e1ac26 --- /dev/null +++ b/VNET/.gitignore @@ -0,0 +1,41 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl + +# Ignore the .DS_Store files created by macOS +.DS_Store \ No newline at end of file diff --git a/VNET/environment/.gitignore b/VNET/environment/.gitignore new file mode 100644 index 0000000..1e1ac26 --- /dev/null +++ b/VNET/environment/.gitignore @@ -0,0 +1,41 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl + +# Ignore the .DS_Store files created by macOS +.DS_Store \ No newline at end of file diff --git a/VNET/environment/dev/.gitignore b/VNET/environment/dev/.gitignore new file mode 100644 index 0000000..1e1ac26 --- /dev/null +++ b/VNET/environment/dev/.gitignore @@ -0,0 +1,41 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl + +# Ignore the .DS_Store files created by macOS +.DS_Store \ No newline at end of file diff --git a/VNET/environment/test-v1/.gitignore b/VNET/environment/test-v1/.gitignore new file mode 100644 index 0000000..1e1ac26 --- /dev/null +++ b/VNET/environment/test-v1/.gitignore @@ -0,0 +1,41 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl + +# Ignore the .DS_Store files created by macOS +.DS_Store \ No newline at end of file diff --git a/VNET/environment/test-v1/backend.tf b/VNET/environment/test-v1/backend.tf new file mode 100644 index 0000000..1f6d9a8 --- /dev/null +++ b/VNET/environment/test-v1/backend.tf @@ -0,0 +1,9 @@ +terraform { + backend "azurerm" { + resource_group_name = "tf_state" + storage_account_name = "tfstatefile84" + container_name = "testtfstate" + key = "multiclonetwork.terraform.tfstate" + subscription_id = "" + } +} \ No newline at end of file diff --git a/VNET/environment/test-v1/main.tf b/VNET/environment/test-v1/main.tf new file mode 100644 index 0000000..118050d --- /dev/null +++ b/VNET/environment/test-v1/main.tf @@ -0,0 +1,245 @@ +############################################################################################# +# Local Variables +############################################################################################# + +locals { + environment = "test-v1" + vnet_name = "vnet-${local.environment}" + location = "eastus" + second_location = "westus" + name = "smooth" + global_name = "${local.name}-${local.environment}" + tags = { + environment = local.environment + name = local.name + } + vnet_address_space = ["10.0.0.0/16"] + vnet2_address_space = ["10.10.0.0/16"] +} + +############################################################################################# +# Resource Group Module +############################################################################################# + +module "resource_group" { + source = "../../modules/resource-group" + resource_groups = { + smooths_rg1 = { + name = "smooths-rg1" + location = local.location + } + smooth_rg2 = { + name = "smooth-rg2" + location = local.second_location + } + } + tags = local.tags + +} + +############################################################################################# +# Virtual Network Module +############################################################################################# + + +module "virtual_network" { + source = "../../modules/virtual-network" + virtual_network = { + smooths_vnet1 = { + name = local.vnet_name + address_space = local.vnet_address_space + location = local.location + resource_group_name = module.resource_group.resource_group_name["smooths_rg1"] + } + smooths_vnet2 = { + name = local.vnet_name + address_space = local.vnet2_address_space + location = local.second_location + resource_group_name = module.resource_group.resource_group_name["smooth_rg2"] + } + + } + tags = local.tags +} + +############################################################################################# +# Subnet Module +############################################################################################# + +module "subnets" { + source = "../../modules/subnet" + subnets = { + smooths_subnet1 = { + name = "smooths-subnet1" + resource_group_name = module.resource_group.resource_group_name["smooths_rg1"] + virtual_network_name = module.virtual_network.virutal_network_name["smooths_vnet1"] + address_prefixes = ["10.0.1.0/24"] + + service_endpoints = [ + "Microsoft.Storage", + "Microsoft.Sql", + ] + } + smooths_subnet2 = { + name = "smooths-subnet2" + resource_group_name = module.resource_group.resource_group_name["smooths_rg1"] + virtual_network_name = module.virtual_network.virutal_network_name["smooths_vnet1"] + address_prefixes = ["10.0.2.0/24"] + } + smooth_subnet1 = { + name = "smooths-subnet1" + resource_group_name = module.resource_group.resource_group_name["smooth_rg2"] + virtual_network_name = module.virtual_network.virutal_network_name["smooths_vnet2"] + address_prefixes = ["10.10.10.0/24"] + + } + smooth_subnet2 = { + name = "smooths-subnet2" + resource_group_name = module.resource_group.resource_group_name["smooth_rg2"] + virtual_network_name = module.virtual_network.virutal_network_name["smooths_vnet2"] + address_prefixes = ["10.10.1.0/24"] + + delegation = { + name = "delegation1" + + service_delegation = { + name = "Microsoft.ContainerInstance/containerGroups" + actions = [ + "Microsoft.Network/networkinterfaces/*", + "Microsoft.Network/virtualNetworks/subnets/join/action", + + ] + } + } + } + } +} +######################################################################################## +# Linux VM +######################################################################################## + +module "linux_vm" { + source = "../../../virtual-machines/Azure/Linux-VM" + + network_interface = { + nic1 = { + name = "linux-nic1" + location = local.location + ip_configuration = { + name = "internal" + subnet_id = module.subnets.subnet_id["smooths_subnet1"] + private_ip_address_allocation = "Dynamic" + } + } + nic2 = { + name = "linux-nic2" + location = local.location + ip_configuration = { + name = "internal" + subnet_id = module.subnets.subnet_id["smooth_subnet1"] + private_ip_address_allocation = "Dynamic" + } + } + } + linux_vm = { + Vm1 = { + name = "Linux-VM1" + resource_group_name = odule.resource_group.resource_group_name["smooths_rg1"] + location = local.location + size = "Standard_F2" + admin_username = "adminuser" + network_interface_ids = [module.linux_vm.network_interface_ids["nic1"]] + } + + Vm2 = { + name = "Linux-VM2" + resource_group_name = odule.resource_group.resource_group_name["smooths_rg2"] + location = local.location + size = "Standard_F2" + admin_username = "adminuser" + network_interface_ids = [module.linux_vm.network_interface_ids["nic2"]] + } + } +} + +######################################################################################### +# Storage Account +######################################################################################### + +module "storage_accounts" { + source = "../../modules/storage-account" + storage_accounts = { + smooths_sa1 = { + name = "smoothssa1" + resource_group_name = module.resource_group.resource_group_name["smooths_rg1"] + location = local.location + account_tier = "Standard" + account_replication_type = "LRS" + } + smooths_sa2 = { + name = "smoothssa2" + resource_group_name = module.resource_group.resource_group_name["smooth_rg2"] + location = local.second_location + account_tier = "Standard" + account_replication_type = "LRS" + } + } + storage_containers = { + smooths_container1 = { + name = "smooths-container1" + storage_account_id = module.storage_accounts.storage_account_id["smooths_sa1"] + container_access_type = "private" + } + smooths_container2 = { + name = "smooths-container2" + storage_account_id = module.storage_accounts.storage_account_id["smooths_sa2"] + container_access_type = "private" + } + } + tags = local.tags +} + +######################################################################################### +# Network Security Group +######################################################################################### + +module "network_security_group" { + source = "../../modules/network-security-group" + + network_security_groups = { + smooths_nsg1 = { + name = "smooths-nsg1" + location = local.location + resource_group_name = module.resource_group.resource_group_name["smooths_rg1"] + } + } + network_security_group_rules = { + smooths_nsg_rule1 = { + name = "smooths-nsg-rule1" + priority = 100 + direction = "Inbound" + access = "Allow" + protocol = "Tcp" + source_address_prefix = "*" + destination_address_prefix = "*" + source_port_range = "*" + destination_port_range = "80" + target_nsg_key = "smooths_nsg1" + resource_group_name = module.resource_group.resource_group_name["smooths_rg1"] + } + smooths_nsg_rule2 = { + name = "smooths-nsg-rule2" + priority = 200 + direction = "Outbound" + access = "Allow" + protocol = "Tcp" + source_address_prefix = "*" + destination_address_prefix = "*" + source_port_range = "*" + destination_port_range = "443" + target_nsg_key = "smooths_nsg1" + resource_group_name = module.resource_group.resource_group_name["smooths_rg1"] + } + } + tags = local.tags +} diff --git a/VNET/environment/test-v1/providers.tf b/VNET/environment/test-v1/providers.tf new file mode 100644 index 0000000..eeb0764 --- /dev/null +++ b/VNET/environment/test-v1/providers.tf @@ -0,0 +1,22 @@ +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "4.34.0" + } + } +} +# Configure the Microsoft Azure Provider +provider "azurerm" { + subscription_id = "" + features { + resource_group { + prevent_deletion_if_contains_resources = false + } + key_vault { + purge_soft_delete_on_destroy = true + recover_soft_deleted_key_vaults = true + } + + } +} \ No newline at end of file diff --git a/VNET/environment/test-v1/variables.tf b/VNET/environment/test-v1/variables.tf new file mode 100644 index 0000000..e69de29 diff --git a/VNET/modules/network-security-group/main.tf b/VNET/modules/network-security-group/main.tf new file mode 100644 index 0000000..c86b9d4 --- /dev/null +++ b/VNET/modules/network-security-group/main.tf @@ -0,0 +1,26 @@ +#################################################################################### +# Network Security Group Module +#################################################################################### + +resource "azurerm_network_security_group" "this" { + for_each = var.network_security_groups + name = each.value.name + location = each.value.location + resource_group_name = each.value.resource_group_name +} + +resource "azurerm_network_security_rule" "this" { + for_each = var.network_security_group_rules + name = each.value.name + priority = each.value.priority + direction = each.value.direction + access = each.value.access + protocol = each.value.protocol + source_address_prefix = each.value.source_address_prefix + destination_address_prefix = each.value.destination_address_prefix + source_port_range = each.value.source_port_range + destination_port_range = each.value.destination_port_range + network_security_group_name = azurerm_network_security_group.this[each.value.target_nsg_key].name + resource_group_name = azurerm_network_security_group.this[each.value.target_nsg_key].resource_group_name +} + diff --git a/VNET/modules/network-security-group/outputs.tf b/VNET/modules/network-security-group/outputs.tf new file mode 100644 index 0000000..e69de29 diff --git a/VNET/modules/network-security-group/variables.tf b/VNET/modules/network-security-group/variables.tf new file mode 100644 index 0000000..e7498ee --- /dev/null +++ b/VNET/modules/network-security-group/variables.tf @@ -0,0 +1,35 @@ +#################################################################################### +# Network Security Group Variables +#################################################################################### + + +variable "tags" { + description = "Tags to apply to all resources" + type = map(string) +} + +variable "network_security_groups" { + description = "Map of network security groups to create" + type = map(object({ + name = string + location = string + resource_group_name = string + })) +} + +variable "network_security_group_rules" { + description = "Map of network security group rules to create" + type = map(object({ + name = string + priority = number + direction = string # e.g. "Inbound", "Outbound" + access = string # e.g. "Allow", "Deny" + protocol = string # e.g. "Tcp", "Udp", "*" + source_address_prefix = optional(string, "*") + destination_address_prefix = optional(string, "*") + source_port_range = optional(string, "*") + destination_port_range = optional(string, "*") + target_nsg_key = optional(string, null) # Key to reference the target NSG in the azurerm_network_security_group resource + + })) +} \ No newline at end of file diff --git a/VNET/modules/resource-group/.gitignore b/VNET/modules/resource-group/.gitignore new file mode 100644 index 0000000..1e1ac26 --- /dev/null +++ b/VNET/modules/resource-group/.gitignore @@ -0,0 +1,41 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl + +# Ignore the .DS_Store files created by macOS +.DS_Store \ No newline at end of file diff --git a/VNET/modules/resource-group/main.tf b/VNET/modules/resource-group/main.tf new file mode 100644 index 0000000..66d050a --- /dev/null +++ b/VNET/modules/resource-group/main.tf @@ -0,0 +1,13 @@ +##################################################################### +# Resource Group Module +####################################################################### + + + +resource "azurerm_resource_group" "this" { + for_each = var.resource_groups + name = each.value.name + location = each.value.location + + tags = var.tags +} \ No newline at end of file diff --git a/VNET/modules/resource-group/outputs.tf b/VNET/modules/resource-group/outputs.tf new file mode 100644 index 0000000..074ba06 --- /dev/null +++ b/VNET/modules/resource-group/outputs.tf @@ -0,0 +1,11 @@ +output "resource_group_name" { + description = "The name of the resource group." + value = {for k ,v in azurerm_resource_group.this : k => v.name} + +} + +output "location" { + description = "The location of the resource group." + value = {for k ,v in azurerm_resource_group.this : k => v.location} + +} \ No newline at end of file diff --git a/VNET/modules/resource-group/variables.tf b/VNET/modules/resource-group/variables.tf new file mode 100644 index 0000000..ee81305 --- /dev/null +++ b/VNET/modules/resource-group/variables.tf @@ -0,0 +1,16 @@ +##################################################################### +# Resource Group Variables +####################################################################### + +variable "resource_groups" { + description = "Map of resource groups to create" + type = map(object({ + name = string + location = string + })) +} + +variable "tags"{ + description = "Tags to apply to the resource group" + type = map(string) +} \ No newline at end of file diff --git a/VNET/modules/storage-account/.gitignore b/VNET/modules/storage-account/.gitignore new file mode 100644 index 0000000..1e1ac26 --- /dev/null +++ b/VNET/modules/storage-account/.gitignore @@ -0,0 +1,41 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl + +# Ignore the .DS_Store files created by macOS +.DS_Store \ No newline at end of file diff --git a/VNET/modules/storage-account/main.tf b/VNET/modules/storage-account/main.tf new file mode 100644 index 0000000..b27b0d8 --- /dev/null +++ b/VNET/modules/storage-account/main.tf @@ -0,0 +1,29 @@ +######################################################################################### +# Storage Account +######################################################################################### + +resource "azurerm_storage_account" "this" { + for_each = var. storage_accounts + name = each.value.name + resource_group_name = each.value.resource_group_name + location = each.value.location + account_tier = each.value.account_tier + account_replication_type = each.value.account_replication_type + + tags = var.tags + + + +} + +######################################################################################### +# Container Variables +######################################################################################### +resource "azurerm_storage_container" "this" { + for_each = var.storage_containers + name = each.value.name + storage_account_id = each.value.storage_account_id + container_access_type = each.value.container_access_type + + depends_on = [ azurerm_storage_account.this ] +} \ No newline at end of file diff --git a/VNET/modules/storage-account/outputs.tf b/VNET/modules/storage-account/outputs.tf new file mode 100644 index 0000000..6673839 --- /dev/null +++ b/VNET/modules/storage-account/outputs.tf @@ -0,0 +1,4 @@ +output "storage_account_id" { + description = "Storage account ID." + value = {for k, v in azurerm_storage_account.this : k => v.id} +} \ No newline at end of file diff --git a/VNET/modules/storage-account/variables.tf b/VNET/modules/storage-account/variables.tf new file mode 100644 index 0000000..aae37fe --- /dev/null +++ b/VNET/modules/storage-account/variables.tf @@ -0,0 +1,34 @@ +######################################################################################### +# Storage Account Variables +######################################################################################### + +variable "storage_accounts" { + description = "Map of storage accounts to create" + type = map(object({ + name = string + location = string + resource_group_name = string + account_tier = string # e.g. "Standard", "Premium" + account_replication_type = string # e.g. "Standard_LRS", "Premium_LRS", etc. + })) +} + + +######################################################################################### +# Container Variables +######################################################################################### + +variable "storage_containers" { + description = "Map of storage containers to create" + type = map(object({ + name = string + storage_account_id = string + container_access_type = string # e.g. "private", "blob", "container" + })) +} + +variable "tags" { + description = "Tags to apply to the storage accounts and containers" + type = map(string) + +} \ No newline at end of file diff --git a/VNET/modules/subnet/.gitignore b/VNET/modules/subnet/.gitignore new file mode 100644 index 0000000..1e1ac26 --- /dev/null +++ b/VNET/modules/subnet/.gitignore @@ -0,0 +1,41 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl + +# Ignore the .DS_Store files created by macOS +.DS_Store \ No newline at end of file diff --git a/VNET/modules/subnet/main.tf b/VNET/modules/subnet/main.tf new file mode 100644 index 0000000..7137f55 --- /dev/null +++ b/VNET/modules/subnet/main.tf @@ -0,0 +1,25 @@ +################################################################################ +# Subnet Module +################################################################################ + +resource "azurerm_subnet" "this" { + for_each = var.subnets + name = each.value.name + resource_group_name = each.value.resource_group_name + virtual_network_name = each.value.virtual_network_name + address_prefixes = each.value.address_prefixes + + dynamic "delegation" { + for_each = each.value.delegation == null ? [] : [each.value.delegation] + + content { + name = delegation.value.name + + service_delegation { + name = delegation.value.service_delegation.name + actions = delegation.value.service_delegation.actions + } + } + } + service_endpoints = each.value.service_endpoints +} \ No newline at end of file diff --git a/VNET/modules/subnet/outputs.tf b/VNET/modules/subnet/outputs.tf new file mode 100644 index 0000000..3309ec8 --- /dev/null +++ b/VNET/modules/subnet/outputs.tf @@ -0,0 +1,9 @@ +output "subnet_id" { + description = "The ID of the subnet." + value = {for k, v in azurerm_subnet.this : k => v.id} + +} +output "subnet_address_prefixes" { + description = "subnet address prefixes aka subnet CIDR." + value = {for k, v in azurerm_subnet.this : k => v.address_prefixes} +} \ No newline at end of file diff --git a/VNET/modules/subnet/variables.tf b/VNET/modules/subnet/variables.tf new file mode 100644 index 0000000..2bd9a00 --- /dev/null +++ b/VNET/modules/subnet/variables.tf @@ -0,0 +1,24 @@ +################################################################################ +# Subnet Variables +################################################################################ + +variable "subnets" { + description = "Map of subnets to create" + type = map(object({ + name = string + address_prefixes = list(string) + virtual_network_name = string + resource_group_name = string + service_endpoints = optional(list(string), []) + network_security_group_id = optional(string, null) + delegation = optional(object({ + name = string + service_delegation = object({ + name = string + actions = list(string) + }) + service_endpoints = optional(list(string), []), + })) + })) + +} \ No newline at end of file diff --git a/VNET/modules/virtual-network/.gitignore b/VNET/modules/virtual-network/.gitignore new file mode 100644 index 0000000..1e1ac26 --- /dev/null +++ b/VNET/modules/virtual-network/.gitignore @@ -0,0 +1,41 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl + +# Ignore the .DS_Store files created by macOS +.DS_Store \ No newline at end of file diff --git a/VNET/modules/virtual-network/main.tf b/VNET/modules/virtual-network/main.tf new file mode 100644 index 0000000..36edbe8 --- /dev/null +++ b/VNET/modules/virtual-network/main.tf @@ -0,0 +1,14 @@ +################################################################################ +# Virtul Network Module +################################################################################ + +resource "azurerm_virtual_network" "this" { + for_each = var.virtual_network + name = each.value.name + address_space = each.value.address_space + location = each.value.location + resource_group_name = each.value.resource_group_name + + tags = var.tags + +} \ No newline at end of file diff --git a/VNET/modules/virtual-network/outputs.tf b/VNET/modules/virtual-network/outputs.tf new file mode 100644 index 0000000..3c31a7d --- /dev/null +++ b/VNET/modules/virtual-network/outputs.tf @@ -0,0 +1,18 @@ +output "virutal_network_name" { + description = "The name of the virtual network." + value = {for k, v in azurerm_virtual_network.this : k => v.name} + +} + +output "virutal_network_id" { + description = "The ID of the virtual network." + value = {for k, v in azurerm_virtual_network.this : k => v.id} + +} +output "vnet_address_space" { + description = "The address space of the virtual network." + value = {for k, v in azurerm_virtual_network.this : k => v.address_space} + +} + + diff --git a/VNET/modules/virtual-network/variables.tf b/VNET/modules/virtual-network/variables.tf new file mode 100644 index 0000000..593b74f --- /dev/null +++ b/VNET/modules/virtual-network/variables.tf @@ -0,0 +1,18 @@ +################################################################################ +# Virtul Network Variables +################################################################################ + +variable "virtual_network" { + description = "Map of virtual networks to create" + type = map(object({ + name = string + address_space = list(string) + location = string + resource_group_name = string + })) +} +variable "tags" { + description = "Tags to apply all resources" + type = map(string) + +} \ No newline at end of file diff --git a/VPC-Peering/Environments/dev/backend.tf b/VPC-Peering/Environments/dev/backend.tf index 409aaf7..080c06f 100644 --- a/VPC-Peering/Environments/dev/backend.tf +++ b/VPC-Peering/Environments/dev/backend.tf @@ -1,7 +1,7 @@ terraform { backend "s3" { bucket = "terraform-state-bucket1237546" - key = "dev-vpc-by-terraform-state.tfstate" + key = "dev-vpc-peering-terraform-state.tfstate" region = "us-east-1" use_lockfile = true } diff --git a/VPC-Peering/Environments/dev/main.tf b/VPC-Peering/Environments/dev/main.tf index e69de29..c495f5f 100644 --- a/VPC-Peering/Environments/dev/main.tf +++ b/VPC-Peering/Environments/dev/main.tf @@ -0,0 +1,347 @@ +locals { + region = "us-east-1" + region_2 = "us-east-1" + tags = { + Environment = "dev" + Project = "VPC-Peering" + Owner = "Smooth" + } + + name = "vpc-peering-dev" + + vpc_names = { + requester = "${local.name}-requester" + accepter = "${local.name}-accepter" + } +} + + +################################################################### +# VPC Module +################################################################### + +module "vpc" { + source = "../../../VPC/Modules/vpc" + + + tags = local.tags + # name = local.name + vpc_attributes = { + "requester_vpc" = { + cidr_block = "10.0.0.0/16" + enable_dns_support = true + enable_dns_hostnames = true + region = local.region + name = local.vpc_names.requester + }, + "accepter_vpc" = { + cidr_block = "10.10.0.0/16" + enable_dns_support = true + enable_dns_hostnames = true + region = local.region_2 + name = local.vpc_names.accepter + + } + } +} + +################################################################### +# Subnet Module +################################################################### + +module "subnets" { + source = "../../../VPC/modules/subnets" + name = local.name + tags = local.tags + + private_subnets = { + "requester-priv-subnet-1" = { + cidr_block = ["10.0.0.0/24"] + availability_zone = ["us-east-1a"] + map_public_ip_on_launch = false + vpc_id = module.vpc.vpc_id["requester_vpc"] + } + + "accepter-priv-subnet-1" = { + cidr_block = ["10.10.0.0/24"] + availability_zone = ["us-east-1a"] + map_public_ip_on_launch = false + vpc_id = module.vpc.vpc_id["accepter_vpc"] + } + } + public_subnets = { + "requester-pub-subnet-2" = { + cidr_block = ["10.0.1.0/24"] + availability_zone = ["us-east-1b"] + map_public_ip_on_launch = true + vpc_id = module.vpc.vpc_id["requester_vpc"] + + } + "accepter-pub-subnet-2" = { + cidr_block = ["10.10.1.0/24"] + availability_zone = ["us-east-1b"] + map_public_ip_on_launch = true + vpc_id = module.vpc.vpc_id["accepter_vpc"] + } + } +} + +################################################################### +# VPC Peering Module``` +################################################################### + +module "peerings" { + source = "../../modules/single-vpc-to-vpc-v2" + + vpc_peering_connection = { + "peering_connection" = { + vpc_id = module.vpc.vpc_id["requester_vpc"] # Requester VPC ID + peer_vpc_id = module.vpc.vpc_id["accepter_vpc"] # accepter VPC ID + + auto_accept = true # Auto accept the connection + name = "requester-peering" + + } + } + vpc_peering_accepter = { + accepter-peer = { + vpc_peering_connection_id = module.peerings.this_connection["peering_connection"] # VPC Peering Connection ID + auto_accept = true + name = "accepter-peer" # Auto accept the connection + } + } + + tags = local.tags + depends_on = [module.vpc, module.subnets] + +} + +################################################################### +# IGW - NAT Module +################################################################### + +module "igw-nat" { + source = "../../../VPC/modules/igw-nat" + eip = { + requester_eip = {} + accepter_eip = {} + } + + nat_gateway = { + requester-nat = { + allocation_id = module.igw-nat.allocation_id["requester_eip"] + subnet_id = module.subnets.public_subnets["requester-pub-subnet-2"] + } + accepter-nat = { + allocation_id = module.igw-nat.allocation_id["accepter_eip"] + subnet_id = module.subnets.public_subnets["accepter-pub-subnet-2"] + } + } + internet_gateway = { + requester-igw = { + vpc_id = module.vpc.vpc_id["requester_vpc"] + } + accepter-igw = { + vpc_id = module.vpc.vpc_id["accepter_vpc"] + } + } + tags = local.tags + name = "${local.name}-igw" + +} + +################################################################### +# Route table Module +################################################################### + +module "route-tables" { + source = "../../../VPC/modules/route-tables" + + tags = local.tags + name = local.name + public_route_tables = { + requester_pub_rt = { + vpc_id = module.vpc.vpc_id["requester_vpc"] + } + accepter_pub_rt = { + vpc_id = module.vpc.vpc_id["accepter_vpc"] + } + } + + private_route_tables = { + requester_priv_rt = { + vpc_id = module.vpc.vpc_id["requester_vpc"] + } + + accepter_priv_rt = { + vpc_id = module.vpc.vpc_id["accepter_vpc"] + } + } + + ############################################################################### + # Public Routes + ############################################################################### + public_routes = { + route-requester-igw = { + vpc_id = module.vpc.vpc_id["requester_vpc"] + route_table_id = module.route-tables.public_route_table_id["requester_pub_rt"] + gateway_id = module.igw-nat.igw_id["requester-igw"] + destination_cidr_block = "0.0.0.0/0" + + } + + route-accepter-igw = { + vpc_id = module.vpc.vpc_id["accepter_vpc"] + route_table_id = module.route-tables.public_route_table_id["accepter_pub_rt"] + gateway_id = module.igw-nat.igw_id["accepter-igw"] + destination_cidr_block = "0.0.0.0/0" + } + } + ############################################################################### + # Private Routes + ############################################################################### + + private_routes = { + route-requester-peer = { + route_table_id = module.route-tables.private_route_table_id["requester_priv_rt"] + vpc_peering_connection_id = module.peerings.this_connection["peering_connection"] + destination_cidr_block = module.vpc.vpc_cidr["accepter_vpc"] + } + route-requester-nat = { + route_table_id = module.route-tables.private_route_table_id["requester_priv_rt"] + nat_gateway_id = module.igw-nat.nat_id["requester-nat"] + destination_cidr_block = "0.0.0.0/0" + } + route-accepter-peer = { + route_table_id = module.route-tables.private_route_table_id["accepter_priv_rt"] + vpc_peering_connection_id = module.peerings.this_connection["peering_connection"] + destination_cidr_block = module.vpc.vpc_cidr["requester_vpc"] + } + route-accepter-nat = { + route_table_id = module.route-tables.private_route_table_id["accepter_priv_rt"] + nat_gateway_id = module.igw-nat.nat_id["accepter-nat"] + destination_cidr_block = "0.0.0.0/0" + } + + } + + ############################################################################### + # Route table associations + ############################################################################# + public_route_table_associations = { + pub-requester-assoc = { + route_table_id = module.route-tables.public_route_table_id["requester_pub_rt"] + subnet_id = module.subnets.public_subnets["requester-pub-subnet-2"] + } + pub-accepter-assoc = { + route_table_id = module.route-tables.public_route_table_id["accepter_pub_rt"] + subnet_id = module.subnets.public_subnets["accepter-pub-subnet-2"] + } + } + private_route_table_associations = { + priv-requester-assoc = { + route_table_id = module.route-tables.private_route_table_id["requester_priv_rt"] + subnet_id = module.subnets.private_subnets["requester-priv-subnet-1"] + } + priv-accepter-assoc = { + route_table_id = module.route-tables.private_route_table_id["accepter_priv_rt"] + subnet_id = module.subnets.private_subnets["accepter-priv-subnet-1"] + } + } + +} + +######################################################################## +# EC2 Module +######################################################################## + +module "ec2-instance" { + source = "../../../virtual-machines/AWS/EC2" + + tags = local.tags + name = local.name + + instance_attributes = { + requester_instance = { + instance_type = "t2.micro" + iam_instance_profile = module.ssm_policy.iam_instance_profile + subnet_id = module.subnets.private_subnets["requester-priv-subnet-1"] + vpc_security_group_ids = [module.security-groups.security_group_ids["requester_sg"]] + + } + accepter_instance = { + instance_type = "t2.micro" + iam_instance_profile = module.ssm_policy.iam_instance_profile + subnet_id = module.subnets.private_subnets["accepter-priv-subnet-1"] + vpc_security_group_ids = [module.security-groups.security_group_ids["accepter_sg"]] + + + } + accepter_instance2 = { + instance_type = "t2.micro" + iam_instance_profile = module.ssm_policy.iam_instance_profile + subnet_id = module.subnets.public_subnets["accepter-pub-subnet-2"] + vpc_security_group_ids = [module.security-groups.security_group_ids["accepter_sg"]] + + + } + } + +} +######################################################################## +# IAM SSM Policy +######################################################################## + +module "ssm_policy" { + source = "../../../IAM/SSM-Policy" + +} + +######################################################################## +# Secuirty Group +######################################################################## + +module "security-groups" { + source = "../../../vpc/modules/security-groups" + tags = local.tags + name = local.name + + security_groups = { + requester_sg = { + vpc_id = module.vpc.vpc_id["requester_vpc"] + description = "requester security group allow icmp" + } + accepter_sg = { + vpc_id = module.vpc.vpc_id["accepter_vpc"] + description = "accepter security group allow icmp" + } + } + ingress_rules = { + requester_ingress_icmp = { + type = "ingress" + from_port = -1 + to_port = -1 + protocol = "icmp" + security_group_id = module.security-groups.security_group_ids["requester_sg"] + cidr_blocks = ["0.0.0.0/0"] + + } + accepter_ingress_icmp = { + type = "ingress" + from_port = -1 + to_port = -1 + protocol = "icmp" + security_group_id = module.security-groups.security_group_ids["accepter_sg"] + cidr_blocks = ["0.0.0.0/0"] + } + } + egress_rules = { + requester_egress_rule = { + security_group_id = module.security-groups.security_group_ids["requester_sg"] + } + accepter_egress_rule = { + security_group_id = module.security-groups.security_group_ids["accepter_sg"] + } + } + +} \ No newline at end of file diff --git a/VPC-Peering/Environments/dev/providers.tf b/VPC-Peering/Environments/dev/providers.tf index e69de29..b3d0f7f 100644 --- a/VPC-Peering/Environments/dev/providers.tf +++ b/VPC-Peering/Environments/dev/providers.tf @@ -0,0 +1,21 @@ +terraform { + required_version = ">= 1.0" + required_providers { + aws = { + source = "hashicorp/aws" + version = "6.0.0-beta2" + configuration_aliases = [aws.us-east, aws.us-west] + } + } + +} +provider "aws" { + region = local.region + alias = "us-west" +} + +provider "aws" { + region = local.region_2 + alias = "us-east" +} +## \ No newline at end of file diff --git a/VPC-Peering/Environments/test/main.tf b/VPC-Peering/Environments/test/main.tf index 0c5baa7..50a06a0 100644 --- a/VPC-Peering/Environments/test/main.tf +++ b/VPC-Peering/Environments/test/main.tf @@ -9,30 +9,35 @@ module "single-vpc-to-vpc" { } ### Source VPC Variables ### - environment = var.environment - source_region = var.source_region - source_vpc_name = "${var.source_vpc_name}-${var.environment}" - source_cidr = var.source_cidr - source_subnet1_cidr = var.source_subnet1_cidr - source_subnet1_name = "${var.source_subnet1_name}-${var.environment}" - source_subnet1_az = var.source_subnet1_az - source_subnet2_name = "${var.source_subnet2_name}-${var.environment}" - source_subnet2_cidr = var.source_subnet2_cidr - source_subnet2_az = var.source_subnet2_az - source_rt_name = "${var.source_rt_name}-${var.environment}" - source_pub_sub_cidr = var.source_pub_sub_cidr + environment = var.environment + requestor_vpc_region = var.requestor_vpc_region + requester_vpc_name = "${var.requester_vpc_name}-${var.environment}" + requester_vpc_cidr = var.requester_vpc_cidr + requester_vpc_pub_sub_cidr = var.requester_vpc_pub_sub_cidr + requester_subnet1_cidr = var.requester_subnet1_cidr + requester_subnet1_name = "${var.requester_subnet1_name}-${var.environment}" + requester_subnet1_az = var.requester_subnet1_az + requester_subnet2_name = "${var.requester_subnet2_name}-${var.environment}" + requester_subnet2_cidr = var.requester_subnet2_cidr + requester_subnet2_az = var.requester_subnet2_az + requester_rt_name = "${var.requester_rt_name}-${var.environment}" + requester_ami_id = var.requester_ami_id + instance_type = var.instance_type + ### Destination VPC Variables ### - dest_region = var.dest_region - dest_vpc_name = "${var.dest_vpc_name}-${var.environment}" - dest_cidr = var.dest_cidr - dest_pub_sub_cidr = var.dest_pub_sub_cidr - dest_subnet1_cidr = var.dest_subnet1_cidr - dest_subnet1_name = "${var.dest_subnet1_name}-${var.environment}" - dest_subnet1_az = var.dest_subnet1_az - dest_subnet2_name = "${var.dest_subnet2_name}-${var.environment}" - dest_subnet2_cidr = var.dest_subnet2_cidr - dest_subnet2_az = var.dest_subnet2_az - dest_rt_name = "${var.dest_rt_name}-${var.environment}" + acceptor_region = var.acceptor_region + acceptor_vpc_name = "${var.acceptor_vpc_name}-${var.environment}" + acceptor_cidr = var.acceptor_cidr + acceptor_subnet1_cidr = var.acceptor_subnet1_cidr + acceptor_subnet1_name = "${var.acceptor_subnet1_name}-${var.environment}" + acceptor_subnet1_az = var.acceptor_subnet1_az + acceptor_subnet2_name = "${var.acceptor_subnet2_name}-${var.environment}" + acceptor_subnet2_cidr = var.acceptor_subnet2_cidr + acceptor_subnet2_az = var.acceptor_subnet2_az + acceptor_rt_name = "${var.acceptor_rt_name}-${var.environment}" + acceptor_pub_sub_cidr = var.acceptor_pub_sub_cidr + acceptor_ami_id = var.acceptor_ami_id + map_public_ip_on_launch = var.map_public_ip_on_launch } \ No newline at end of file diff --git a/VPC-Peering/Environments/test/providers.tf b/VPC-Peering/Environments/test/providers.tf index eb77739..b2e9cdf 100644 --- a/VPC-Peering/Environments/test/providers.tf +++ b/VPC-Peering/Environments/test/providers.tf @@ -11,10 +11,10 @@ terraform { provider "aws" { alias = "us-east" - region = var.source_region + region = var.requestor_vpc_region } provider "aws" { alias = "us-west" - region = var.dest_region + region = var.acceptor_region } \ No newline at end of file diff --git a/VPC-Peering/Environments/test/terraform.tfvars b/VPC-Peering/Environments/test/terraform.tfvars index 1a0adb1..657d007 100644 --- a/VPC-Peering/Environments/test/terraform.tfvars +++ b/VPC-Peering/Environments/test/terraform.tfvars @@ -1,26 +1,31 @@ -### ------ Source VPC Variables ------ ### -source_region = "us-east-1" -environment = "test" -source_cidr = "10.0.0.0/16" -source_vpc_name = "source-vpc" -source_subnet1_cidr = "10.0.0.0/24" -source_subnet1_name = "source-subnet-1" -source_subnet1_az = "us-east-1a" -source_subnet2_name = "source-subnet-2" -source_subnet2_cidr = "10.0.1.0/24" -source_subnet2_az = "us-east-1b" -source_rt_name = "source-route-table" -source_pub_sub_cidr = "10.0.2.0/24" +### ------ requester VPC Variables ------ ### +requestor_vpc_region = "us-east-1" +environment = "test" +requester_vpc_cidr = "10.0.0.0/16" +requester_vpc_name = "requester-vpc" +requester_subnet1_cidr = "10.0.0.0/24" +requester_subnet1_name = "requester-subnet-1" +requester_subnet1_az = "us-east-1a" +requester_subnet2_name = "requester-subnet-2" +requester_subnet2_cidr = "10.0.1.0/24" +requester_subnet2_az = "us-east-1b" +requester_rt_name = "requester-route-table" +requester_vpc_pub_sub_cidr = "10.0.2.0/24" +requester_ami_id = "ami-0554aa6767e249943" +instance_type = "t2.micro" -### ------ Destination VPC Variables ------ ### -dest_region = "us-west-2" -dest_cidr = "10.10.0.0/16" -dest_vpc_name = "destination-vpc" -dest_subnet1_cidr = "10.10.0.0/24" -dest_subnet1_name = "destination-subnet-1" -dest_subnet1_az = "us-west-2a" -dest_subnet2_name = "destination-subnet-2" -dest_subnet2_cidr = "10.10.1.0/24" -dest_subnet2_az = "us-west-2b" -dest_rt_name = "destination-route-table" -dest_pub_sub_cidr = "10.10.2.0/24" \ No newline at end of file + +### ------ acceptor VPC Variables ------ ### +acceptor_region = "us-west-2" +acceptor_cidr = "10.10.0.0/16" +acceptor_vpc_name = "acceptor-vpc" +acceptor_subnet1_cidr = "10.10.0.0/24" +acceptor_subnet1_name = "acceptor-subnet-1" +acceptor_subnet1_az = "us-west-2a" +acceptor_subnet2_name = "acceptor-subnet-2" +acceptor_subnet2_cidr = "10.10.1.0/24" +acceptor_subnet2_az = "us-west-2b" +acceptor_rt_name = "acceptor-route-table" +acceptor_pub_sub_cidr = "10.10.2.0/24" +map_public_ip_on_launch = false +acceptor_ami_id = "ami-04999cd8f2624f834" \ No newline at end of file diff --git a/VPC-Peering/Environments/test/variables.tf b/VPC-Peering/Environments/test/variables.tf index 4d9b019..933a272 100644 --- a/VPC-Peering/Environments/test/variables.tf +++ b/VPC-Peering/Environments/test/variables.tf @@ -1,139 +1,163 @@ variable "environment" { description = "The environment for the VPC (e.g., dev, staging, prod)" type = string - + } -variable "source_region" { +variable "requestor_vpc_region" { description = "The AWS region for the source VPC" type = string } -variable "dest_region" { +variable "acceptor_region" { description = "The AWS region for the destination VPC" type = string - + } ### Source VPC Variables ### -variable "source_vpc_name" { + +variable "requester_vpc_name" { description = "Name for the source VPC" type = string - + } -variable "source_cidr" { + +variable "requester_vpc_cidr" { description = "CIDR block for the destination VPC" type = string } -variable "source_pub_sub_cidr" { +variable "requester_vpc_pub_sub_cidr" { description = "CIDR block for the public subnet" - type = string + type = string } -variable "source_subnet1_cidr" { +variable "requester_subnet1_cidr" { description = "CIDR block for the first destination subnet" type = string + +} -} - -variable "source_subnet1_name" { +variable "requester_subnet1_name" { description = "Name for the first destination subnet" type = string - + } -variable "source_subnet1_az" { +variable "requester_subnet1_az" { description = "Availability Zone for the first destination subnet" - type = string - + type = string + } -variable "source_subnet2_name" { +variable "requester_subnet2_name" { description = "Name for the second destination subnet" type = string - + } -variable "source_subnet2_cidr" { +variable "requester_subnet2_cidr" { description = "CIDR block for the second destination subnet" type = string - + } -variable "source_subnet2_az" { +variable "requester_subnet2_az" { description = "Availability Zone for the second destination subnet" type = string - + } -variable "source_rt_name" { +variable "requester_rt_name" { description = "Name for the destination route table" - type = string - + type = string + } -### Destination VPC Variables ### +### Acceptor VPC Variables ### -variable "dest_vpc_name" { +variable "acceptor_vpc_name" { description = "Name for the source VPC" type = string - + } - -variable "dest_cidr" { +variable "acceptor_cidr" { description = "CIDR block for the destination VPC" type = string } -variable "dest_subnet1_cidr" { +variable "acceptor_subnet1_cidr" { description = "CIDR block for the first destination subnet" type = string + +} -} - -variable "dest_subnet1_name" { +variable "acceptor_subnet1_name" { description = "Name for the first destination subnet" type = string - + } -variable "dest_subnet1_az" { +variable "acceptor_subnet1_az" { description = "Availability Zone for the first destination subnet" - type = string - + type = string + } -variable "dest_subnet2_name" { +variable "acceptor_subnet2_name" { description = "Name for the second destination subnet" type = string + +} +variable "acceptor_pub_sub_cidr" { + description = "CIDR block for the public subnet" + type = string } -variable "dest_subnet2_cidr" { +variable "acceptor_subnet2_cidr" { description = "CIDR block for the second destination subnet" type = string - + } -variable "dest_subnet2_az" { +variable "acceptor_subnet2_az" { description = "Availability Zone for the second destination subnet" type = string - + } -variable "dest_rt_name" { +variable "acceptor_rt_name" { description = "Name for the destination route table" - type = string + type = string + +} +variable "map_public_ip_on_launch" { + description = "Whether to map public IPs on launch for subnets, defaults to false" + type = bool + default = false + +} + +### EC2 Instance Variables ### +variable "requester_ami_id" { + description = "ami id for the source VPC EC2 instance. MUST BE REGION SPECIFIC" + type = string } -variable "dest_pub_sub_cidr" { - description = "CIDR block for the public subnet" +variable "acceptor_ami_id" { + description = "ami id for the destination VPC EC2 instance. MUST BE REGION SPECIFIC" + type = string +} +variable "instance_type" { + description = "Instance type for the EC2 instances in both VPCs" type = string + default = "t2.micro" } \ No newline at end of file diff --git a/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/01-vpcs.tf b/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/01-vpcs.tf new file mode 100644 index 0000000..854835e --- /dev/null +++ b/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/01-vpcs.tf @@ -0,0 +1,39 @@ +#tfsec:ignore:aws-ec2-require-vpc-flow-logs-for-all-vpcs +resource "aws_vpc" "vpc_a" { + cidr_block = var.vpc_a_cidr + instance_tenancy = "default" + enable_dns_support = true + enable_dns_hostnames = true + + + + tags = { + Name = var.vpc_a_name + } +} +#tfsec:ignore:aws-ec2-require-vpc-flow-logs-for-all-vpcs +resource "aws_vpc" "vpc_b" { + cidr_block = var.vpc_b_cidr + instance_tenancy = "default" + enable_dns_support = true + enable_dns_hostnames = true + + + + tags = { + Name = var.vpc_b_name + } +} +#tfsec:ignore:aws-ec2-require-vpc-flow-logs-for-all-vpcs +resource "aws_vpc" "vpc_c" { + cidr_block = var.vpc_c_cidr + instance_tenancy = "default" + enable_dns_support = true + enable_dns_hostnames = true + + + + tags = { + Name = var.vpc_c_name + } +} diff --git a/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/02-subnets.tf b/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/02-subnets.tf new file mode 100644 index 0000000..01d5584 --- /dev/null +++ b/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/02-subnets.tf @@ -0,0 +1,39 @@ +### -------- vpc a subnets -------- ### + +resource "aws_subnet" "vpc_a_subnet_1" { + vpc_id = aws_vpc.vpc_a.id + cidr_block = var.vpc_a_subnet_1_cidr + availability_zone = var.vpc_a_subnet_1_availability_zone + map_public_ip_on_launch = false + + tags = { + Name = "${var.vpc_a_name}-subnet-1" + } + +} +### -------- vpc b subnets -------- ### + +resource "aws_subnet" "vpc_b_subnet_1" { + vpc_id = aws_vpc.vpc_b.id + cidr_block = var.vpc_b_subnet_1_cidr + availability_zone = var.vpc_b_subnet_1_availability_zone + map_public_ip_on_launch = false + + tags = { + Name = "${var.vpc_b_name}-subnet-1" + } + +} +### -------- vpc c subnets -------- ### + +resource "aws_subnet" "vpc_c_subnet_1" { + vpc_id = aws_vpc.vpc_c.id + cidr_block = var.vpc_c_subnet_1_cidr + availability_zone = var.vpc_c_subnet_1_availability_zone + map_public_ip_on_launch = false + + tags = { + Name = "${var.vpc_c_name}-subnet-1" + } + +} \ No newline at end of file diff --git a/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/03-igw-nat.tf b/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/03-igw-nat.tf new file mode 100644 index 0000000..e316445 --- /dev/null +++ b/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/03-igw-nat.tf @@ -0,0 +1,80 @@ +### --------- vpc a eip ----------- ### + +resource "aws_eip" "vpc_a_eip" { + tags = { + Name = "${var.vpc_a_name}-eip" + } +} + +### vpc a nat gateway ### +resource "aws_nat_gateway" "vpc_a_nat_gateway" { + allocation_id = aws_eip.vpc_a_eip.id + subnet_id = aws_subnet.vpc_a_subnet_1.id + + tags = { + Name = "${var.vpc_a_name}-nat-gateway" + } +} + +### vpc a internet gateway ### +resource "aws_internet_gateway" "vpc_a_internet_gateway" { + vpc_id = aws_vpc.vpc_a.id + + tags = { + Name = "${var.vpc_a_name}-internet-gateway" + } +} + +### ---------- vpc b eip ----------- ### + +resource "aws_eip" "vpc_b_eip" { + tags = { + Name = "${var.vpc_b_name}-eip" + } +} + +### vpc a nat gateway ### +resource "aws_nat_gateway" "vpc_b_nat_gateway" { + allocation_id = aws_eip.vpc_b_eip.id + subnet_id = aws_subnet.vpc_b_subnet_1.id + + tags = { + Name = "${var.vpc_b_name}-nat-gateway" + } +} + +### vpc a internet gateway ### +resource "aws_internet_gateway" "vpc_b_internet_gateway" { + vpc_id = aws_vpc.vpc_b.id + + tags = { + Name = "${var.vpc_b_name}-internet-gateway" + } +} + +### --------- vpc c eip ----------- ### + +resource "aws_eip" "vpc_c_eip" { + tags = { + Name = "${var.vpc_c_name}-eip" + } +} + +### vpc a nat gateway ### +resource "aws_nat_gateway" "vpc_c_nat_gateway" { + allocation_id = aws_eip.vpc_c_eip.id + subnet_id = aws_subnet.vpc_c_subnet_1.id + + tags = { + Name = "${var.vpc_c_name}-nat-gateway" + } +} + +### vpc a internet gateway ### +resource "aws_internet_gateway" "vpc_c_internet_gateway" { + vpc_id = aws_vpc.vpc_c.id + + tags = { + Name = "${var.vpc_c_name}-internet-gateway" + } +} \ No newline at end of file diff --git a/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/04-route-tables.tf b/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/04-route-tables.tf new file mode 100644 index 0000000..f59ae03 --- /dev/null +++ b/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/04-route-tables.tf @@ -0,0 +1,83 @@ +### -------- vpc a route table --------- ### +resource "aws_route_table" "vpc_a_route_table" { + vpc_id = aws_vpc.vpc_a.id + + route { + cidr_block = "0.0.0.0/0" + gateway_id = aws_nat_gateway.vpc_a_nat_gateway.id + + } + + route { + cidr_block = var.vpc_b_cidr + vpc_peering_connection_id = aws_vpc_peering_connection.connection_a.id + + } + + route { + cidr_block = var.vpc_c_cidr + vpc_peering_connection_id = aws_vpc_peering_connection.connection_b.id + + } + + tags = { + Name = "${var.vpc_a_name}-route-table" + } + + depends_on = [ aws_vpc.vpc_a ] +} + +### -------- vpc b route table --------- ### +resource "aws_route_table" "vpc_b_route_table" { + vpc_id = aws_vpc.vpc_b.id + + route { + cidr_block = "0.0.0.0/0" + gateway_id = aws_nat_gateway.vpc_b_nat_gateway.id + + } + route { + cidr_block = var.vpc_c_cidr + vpc_peering_connection_id = aws_vpc_peering_connection.connection_c.id + + } + + route { + cidr_block = var.vpc_a_cidr + vpc_peering_connection_id = aws_vpc_peering_connection.connection_a.id + + } + + + tags = { + Name = "${var.vpc_b_name}-route-table" + } + depends_on = [ aws_vpc.vpc_b, aws_vpc.vpc_c ] +} + +### -------- vpc c route table --------- ### +resource "aws_route_table" "vpc_c_route_table" { + vpc_id = aws_vpc.vpc_c.id + + route { + cidr_block = "0.0.0.0/0" + gateway_id = aws_nat_gateway.vpc_c_nat_gateway.id + + } + + route { + cidr_block = var.vpc_a_cidr + vpc_peering_connection_id = aws_vpc_peering_connection.connection_b.id + + } + + route { + cidr_block = var.vpc_b_cidr + vpc_peering_connection_id = aws_vpc_peering_connection.connection_c.id + + } + tags = { + Name = "${var.vpc_c_name}-route-table" + } + depends_on = [ aws_vpc.vpc_c, aws_vpc.vpc_a ] +} \ No newline at end of file diff --git a/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/05-route-table-association.tf b/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/05-route-table-association.tf new file mode 100644 index 0000000..2ec14e6 --- /dev/null +++ b/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/05-route-table-association.tf @@ -0,0 +1,24 @@ +### --------- vpc A route table association --------- ### +resource "aws_route_table_association" "vpc_a_subnet_1_association" { + subnet_id = aws_subnet.vpc_a_subnet_1.id + route_table_id = aws_route_table.vpc_a_route_table.id + + depends_on = [ aws_route_table.vpc_a_route_table ] + +} + +### --------- vpc B route table association --------- ### +resource "aws_route_table_association" "vpc_b_subnet_1_association" { + subnet_id = aws_subnet.vpc_b_subnet_1.id + route_table_id = aws_route_table.vpc_b_route_table.id + + depends_on = [ aws_route_table.vpc_b_route_table ] +} + +### --------- vpc C route table association --------- ### +resource "aws_route_table_association" "vpc_c_subnet_1_association" { + subnet_id = aws_subnet.vpc_c_subnet_1.id + route_table_id = aws_route_table.vpc_c_route_table.id + + depends_on = [ aws_route_table.vpc_c_route_table ] +} \ No newline at end of file diff --git a/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/06-peerings.tf b/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/06-peerings.tf new file mode 100644 index 0000000..de654f6 --- /dev/null +++ b/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/06-peerings.tf @@ -0,0 +1,101 @@ +data "aws_caller_identity" "peer" {} + +### ------------ VPC A -> VPC B ------------ ### +resource "aws_vpc_peering_connection" "connection_a" { + + peer_owner_id = data.aws_caller_identity.peer.account_id + peer_vpc_id = aws_vpc.vpc_b.id ## Accepter VPC ID + vpc_id = aws_vpc.vpc_a.id ## Requester VPC ID + auto_accept = false + peer_region = var.aws_region + + tags = { + Name = "vpc a -> vpc b" + } + + depends_on = [ aws_vpc.vpc_a, aws_vpc.vpc_b ] +} + + +### Accepters/Destination side of the connection ### +resource "aws_vpc_peering_connection_accepter" "vpc_a_accepter" { + vpc_peering_connection_id = aws_vpc_peering_connection.connection_a.id + auto_accept = true + + + + tags = { + Side = "Accepter" + Name = "vpc b -> vpc a" + } + + depends_on = [ aws_vpc.vpc_a, aws_vpc.vpc_b ] +} + + +### ------------ VPC A -> VPC C ------------ ### +resource "aws_vpc_peering_connection" "connection_b" { + + peer_owner_id = data.aws_caller_identity.peer.account_id + peer_vpc_id = aws_vpc.vpc_c.id ## Accepter VPC ID + vpc_id = aws_vpc.vpc_a.id ## Requester VPC ID + auto_accept = false + peer_region = var.aws_region + + tags = { + Name = "vpc a -> vpc c" + } + + depends_on = [ aws_vpc.vpc_a, aws_vpc.vpc_c ] +} + + +### Accepters/Destination side of the connection ### +resource "aws_vpc_peering_connection_accepter" "vpc_c_accepter" { + vpc_peering_connection_id = aws_vpc_peering_connection.connection_b.id + auto_accept = true + + + + tags = { + Side = "Accepter" + Name = "vpc c -> vpc a" + } + + depends_on = [ aws_vpc.vpc_a, aws_vpc.vpc_c ] +} + + + + +### ------------ VPC C -> VPC B ------------ ### +resource "aws_vpc_peering_connection" "connection_c" { + + peer_owner_id = data.aws_caller_identity.peer.account_id + peer_vpc_id = aws_vpc.vpc_b.id ## Accepter VPC ID + vpc_id = aws_vpc.vpc_c.id ## Requester VPC ID + auto_accept = false + peer_region = var.aws_region + + tags = { + Name = "vpc c -> vpc b" + } + + depends_on = [ aws_vpc.vpc_a, aws_vpc.vpc_c ] +} + + +### Accepters/Destination side of the connection ### +resource "aws_vpc_peering_connection_accepter" "vpc_b_accepter" { + vpc_peering_connection_id = aws_vpc_peering_connection.connection_c.id + auto_accept = true + + + + tags = { + Side = "Accepter" + Name = "vpc b -> vpc c" + } + + depends_on = [ aws_vpc.vpc_b, aws_vpc.vpc_c ] +} \ No newline at end of file diff --git a/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/07-iam.tf b/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/07-iam.tf new file mode 100644 index 0000000..cccb1d3 --- /dev/null +++ b/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/07-iam.tf @@ -0,0 +1,86 @@ +### use the IAM policy created for SSM ### + +resource "aws_iam_policy" "ssm_policy" { + name = "AmazonSSMManagedInstanceCore" + path = "/" + description = "SSM policy" + + # Terraform's "jsonencode" function converts a + # Terraform expression result to valid JSON syntax. + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + "Effect": "Allow", + "Action": [ + "ssm:DescribeAssociation", + "ssm:GetDeployablePatchSnapshotForInstance", + "ssm:GetDocument", + "ssm:DescribeDocument", + "ssm:GetManifest", + "ssm:GetParameter", + "ssm:GetParameters", + "ssm:ListAssociations", + "ssm:ListInstanceAssociations", + "ssm:PutInventory", + "ssm:PutComplianceItems", + "ssm:PutConfigurePackageResult", + "ssm:UpdateAssociationStatus", + "ssm:UpdateInstanceAssociationStatus", + "ssm:UpdateInstanceInformation" + ], + "Resource": "*" + }, + { + "Effect": "Allow", + "Action": [ + "ssmmessages:CreateControlChannel", + "ssmmessages:CreateDataChannel", + "ssmmessages:OpenControlChannel", + "ssmmessages:OpenDataChannel" + ], + "Resource": "*" + }, + { + "Effect": "Allow", + "Action": [ + "ec2messages:AcknowledgeMessage", + "ec2messages:DeleteMessage", + "ec2messages:FailMessage", + "ec2messages:GetEndpoint", + "ec2messages:GetMessages", + "ec2messages:SendReply" + ], + "Resource": "*" + } + ] + }) +} + +data "aws_iam_policy_document" "ssm_policy_doc" { + statement { + actions = [ + "sts:AssumeRole" + ] + principals { + type = "Service" + identifiers = ["ec2.amazonaws.com"] + } + effect = "Allow" + } +} + +resource "aws_iam_role" "ssm_role" { + name = "AmazonSSMManagedInstanceCore1" + assume_role_policy = data.aws_iam_policy_document.ssm_policy_doc.json +} + +resource "aws_iam_role_policy_attachment" "attach_ssm_policy" { + role = aws_iam_role.ssm_role.name + policy_arn = aws_iam_policy.ssm_policy.arn +} + +resource "aws_iam_instance_profile" "ssm_profile" { + name = "AmazonSSMManagedInstanceCore2" + role = aws_iam_role.ssm_role.name +} \ No newline at end of file diff --git a/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/08-EC2.tf b/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/08-EC2.tf new file mode 100644 index 0000000..e69de29 diff --git a/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/09-security-groups.tf b/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/09-security-groups.tf new file mode 100644 index 0000000..c20ca22 --- /dev/null +++ b/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/09-security-groups.tf @@ -0,0 +1,87 @@ +### -------------- Security Group VPC A ------------- ### +resource "aws_security_group" "vpc_a_sg" { + vpc_id = aws_vpc.vpc_a.id + description = "Security group for VPC A" +} + +resource "aws_security_group_rule" "icmp_source" { + type = "ingress" + from_port = -1 + to_port = -1 + protocol = "icmp" + security_group_id = aws_security_group.vpc_a_sg.id + cidr_blocks = [var.acceptor_cidr] + + + description = "Allow ICMP from destination VPC" + + depends_on = [ aws_security_group.vpc_a_sg ] +} + + + +resource "aws_vpc_security_group_egress_rule" "source_egress" { + security_group_id = aws_security_group.vpc_a_sg.id + + cidr_ipv4 = "0.0.0.0/0" #tfsec:ignore:aws-vpc-no-public-egress-sgr + ip_protocol = "-1" + +} +### -------------- Security Group VPC B ------------- ### +resource "aws_security_group" "vpc_b_sg" { + vpc_id = aws_vpc.vpc_b.id + description = "Security group for VPC B" +} + +resource "aws_security_group_rule" "icmp_source" { + type = "ingress" + from_port = -1 + to_port = -1 + protocol = "icmp" + security_group_id = aws_security_group.vpc_b_sg.id + cidr_blocks = [var.acceptor_cidr] + + + description = "Allow ICMP from destination VPC" + + depends_on = [ aws_security_group.vpc_b_sg ] +} + + + +resource "aws_vpc_security_group_egress_rule" "source_egress" { + security_group_id = aws_security_group.vpc_b_sg.id + + cidr_ipv4 = "0.0.0.0/0" #tfsec:ignore:aws-vpc-no-public-egress-sgr + ip_protocol = "-1" + +} +### -------------- Security Group VPC C ------------- ### +resource "aws_security_group" "vpc_c_sg" { + vpc_id = aws_vpc.vpc_c.id + description = "Security group for source VPC" +} + +resource "aws_security_group_rule" "icmp_source" { + type = "ingress" + from_port = -1 + to_port = -1 + protocol = "icmp" + security_group_id = aws_security_group.vpc_c_sg.id + cidr_blocks = [var.acceptor_cidr] + + + description = "Allow ICMP from destination VPC" + + depends_on = [ aws_security_group.vpc_c_sg ] +} + + + +resource "aws_vpc_security_group_egress_rule" "source_egress" { + security_group_id = aws_security_group.vpc_c_sg.id + + cidr_ipv4 = "0.0.0.0/0" #tfsec:ignore:aws-vpc-no-public-egress-sgr + ip_protocol = "-1" + +} \ No newline at end of file diff --git a/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/10-variables.tf b/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/10-variables.tf new file mode 100644 index 0000000..9009978 --- /dev/null +++ b/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/10-variables.tf @@ -0,0 +1,75 @@ +variable "aws_region" { + description = "AWS region where the VPCs will be created" + type = string + default = "us-east-1" + +} +variable "environment" { + description = "Environment for the VPCs (e.g., dev, staging, prod)" + type = string + +} + +### VPC Variables ### +variable "vpc_a_cidr" { + description = "CIDR block for VPC A" + type = string + +} +variable "vpc_b_cidr" { + description = "CIDR block for VPC B" + type = string + +} +variable "vpc_c_cidr" { + description = "CIDR block for VPC C" + type = string + +} +variable "vpc_a_name" { + description = "Name for VPC A" + type = string +} +variable "vpc_b_name" { + description = "Name for VPC B" + type = string +} +variable "vpc_c_name" { + description = "Name for VPC C" + type = string +} + +### Subnet Variables ### + +### Subnet CIDR blocks for each Subnet ### +variable "vpc_a_subnet_1_cidr" { + description = "CIDR block for VPC A Subnet 1" + type = string +} +variable "vpc_b_subnet_1_cidr" { + description = "CIDR block for VPC B Subnet 1" + type = string +} +variable "vpc_c_subnet_1_cidr" { + description = "CIDR block for VPC C Subnet 1" + type = string +} + +### Subnet Availability Zones for each Subnet ### + +variable "vpc_a_subnet_1_availability_zone" { + description = "Availability Zone for VPC A Subnet 1" + type = string + +} + +variable "vpc_b_subnet_1_availability_zone" { + description = "Availability Zone for VPC B Subnet 1" + type = string + +} +variable "vpc_c_subnet_1_availability_zone" { + description = "Availability Zone for VPC C Subnet 1" + type = string + +} \ No newline at end of file diff --git a/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/11-outputs.tf b/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/11-outputs.tf new file mode 100644 index 0000000..e69de29 diff --git a/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/main.tf b/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/main.tf new file mode 100644 index 0000000..e69de29 diff --git a/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/outputs.tf b/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/outputs.tf new file mode 100644 index 0000000..e69de29 diff --git a/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/readme b/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/readme new file mode 100644 index 0000000..c338984 --- /dev/null +++ b/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/readme @@ -0,0 +1,3 @@ +## What I want to explore in this section + - forech + - \ No newline at end of file diff --git a/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/variables.tf b/VPC-Peering/Modules/multi-vpc-to-multi-vpc-v2/variables.tf new file mode 100644 index 0000000..e69de29 diff --git a/VPC-Peering/Modules/multi-vpc-to-multi-vpc/01-vpcs.tf b/VPC-Peering/Modules/multi-vpc-to-multi-vpc/01-vpcs.tf new file mode 100644 index 0000000..854835e --- /dev/null +++ b/VPC-Peering/Modules/multi-vpc-to-multi-vpc/01-vpcs.tf @@ -0,0 +1,39 @@ +#tfsec:ignore:aws-ec2-require-vpc-flow-logs-for-all-vpcs +resource "aws_vpc" "vpc_a" { + cidr_block = var.vpc_a_cidr + instance_tenancy = "default" + enable_dns_support = true + enable_dns_hostnames = true + + + + tags = { + Name = var.vpc_a_name + } +} +#tfsec:ignore:aws-ec2-require-vpc-flow-logs-for-all-vpcs +resource "aws_vpc" "vpc_b" { + cidr_block = var.vpc_b_cidr + instance_tenancy = "default" + enable_dns_support = true + enable_dns_hostnames = true + + + + tags = { + Name = var.vpc_b_name + } +} +#tfsec:ignore:aws-ec2-require-vpc-flow-logs-for-all-vpcs +resource "aws_vpc" "vpc_c" { + cidr_block = var.vpc_c_cidr + instance_tenancy = "default" + enable_dns_support = true + enable_dns_hostnames = true + + + + tags = { + Name = var.vpc_c_name + } +} diff --git a/VPC-Peering/Modules/multi-vpc-to-multi-vpc/02-subnets.tf b/VPC-Peering/Modules/multi-vpc-to-multi-vpc/02-subnets.tf new file mode 100644 index 0000000..01d5584 --- /dev/null +++ b/VPC-Peering/Modules/multi-vpc-to-multi-vpc/02-subnets.tf @@ -0,0 +1,39 @@ +### -------- vpc a subnets -------- ### + +resource "aws_subnet" "vpc_a_subnet_1" { + vpc_id = aws_vpc.vpc_a.id + cidr_block = var.vpc_a_subnet_1_cidr + availability_zone = var.vpc_a_subnet_1_availability_zone + map_public_ip_on_launch = false + + tags = { + Name = "${var.vpc_a_name}-subnet-1" + } + +} +### -------- vpc b subnets -------- ### + +resource "aws_subnet" "vpc_b_subnet_1" { + vpc_id = aws_vpc.vpc_b.id + cidr_block = var.vpc_b_subnet_1_cidr + availability_zone = var.vpc_b_subnet_1_availability_zone + map_public_ip_on_launch = false + + tags = { + Name = "${var.vpc_b_name}-subnet-1" + } + +} +### -------- vpc c subnets -------- ### + +resource "aws_subnet" "vpc_c_subnet_1" { + vpc_id = aws_vpc.vpc_c.id + cidr_block = var.vpc_c_subnet_1_cidr + availability_zone = var.vpc_c_subnet_1_availability_zone + map_public_ip_on_launch = false + + tags = { + Name = "${var.vpc_c_name}-subnet-1" + } + +} \ No newline at end of file diff --git a/VPC-Peering/Modules/multi-vpc-to-multi-vpc/03-igw-nat.tf b/VPC-Peering/Modules/multi-vpc-to-multi-vpc/03-igw-nat.tf new file mode 100644 index 0000000..e316445 --- /dev/null +++ b/VPC-Peering/Modules/multi-vpc-to-multi-vpc/03-igw-nat.tf @@ -0,0 +1,80 @@ +### --------- vpc a eip ----------- ### + +resource "aws_eip" "vpc_a_eip" { + tags = { + Name = "${var.vpc_a_name}-eip" + } +} + +### vpc a nat gateway ### +resource "aws_nat_gateway" "vpc_a_nat_gateway" { + allocation_id = aws_eip.vpc_a_eip.id + subnet_id = aws_subnet.vpc_a_subnet_1.id + + tags = { + Name = "${var.vpc_a_name}-nat-gateway" + } +} + +### vpc a internet gateway ### +resource "aws_internet_gateway" "vpc_a_internet_gateway" { + vpc_id = aws_vpc.vpc_a.id + + tags = { + Name = "${var.vpc_a_name}-internet-gateway" + } +} + +### ---------- vpc b eip ----------- ### + +resource "aws_eip" "vpc_b_eip" { + tags = { + Name = "${var.vpc_b_name}-eip" + } +} + +### vpc a nat gateway ### +resource "aws_nat_gateway" "vpc_b_nat_gateway" { + allocation_id = aws_eip.vpc_b_eip.id + subnet_id = aws_subnet.vpc_b_subnet_1.id + + tags = { + Name = "${var.vpc_b_name}-nat-gateway" + } +} + +### vpc a internet gateway ### +resource "aws_internet_gateway" "vpc_b_internet_gateway" { + vpc_id = aws_vpc.vpc_b.id + + tags = { + Name = "${var.vpc_b_name}-internet-gateway" + } +} + +### --------- vpc c eip ----------- ### + +resource "aws_eip" "vpc_c_eip" { + tags = { + Name = "${var.vpc_c_name}-eip" + } +} + +### vpc a nat gateway ### +resource "aws_nat_gateway" "vpc_c_nat_gateway" { + allocation_id = aws_eip.vpc_c_eip.id + subnet_id = aws_subnet.vpc_c_subnet_1.id + + tags = { + Name = "${var.vpc_c_name}-nat-gateway" + } +} + +### vpc a internet gateway ### +resource "aws_internet_gateway" "vpc_c_internet_gateway" { + vpc_id = aws_vpc.vpc_c.id + + tags = { + Name = "${var.vpc_c_name}-internet-gateway" + } +} \ No newline at end of file diff --git a/VPC-Peering/Modules/multi-vpc-to-multi-vpc/04-route-tables.tf b/VPC-Peering/Modules/multi-vpc-to-multi-vpc/04-route-tables.tf new file mode 100644 index 0000000..f59ae03 --- /dev/null +++ b/VPC-Peering/Modules/multi-vpc-to-multi-vpc/04-route-tables.tf @@ -0,0 +1,83 @@ +### -------- vpc a route table --------- ### +resource "aws_route_table" "vpc_a_route_table" { + vpc_id = aws_vpc.vpc_a.id + + route { + cidr_block = "0.0.0.0/0" + gateway_id = aws_nat_gateway.vpc_a_nat_gateway.id + + } + + route { + cidr_block = var.vpc_b_cidr + vpc_peering_connection_id = aws_vpc_peering_connection.connection_a.id + + } + + route { + cidr_block = var.vpc_c_cidr + vpc_peering_connection_id = aws_vpc_peering_connection.connection_b.id + + } + + tags = { + Name = "${var.vpc_a_name}-route-table" + } + + depends_on = [ aws_vpc.vpc_a ] +} + +### -------- vpc b route table --------- ### +resource "aws_route_table" "vpc_b_route_table" { + vpc_id = aws_vpc.vpc_b.id + + route { + cidr_block = "0.0.0.0/0" + gateway_id = aws_nat_gateway.vpc_b_nat_gateway.id + + } + route { + cidr_block = var.vpc_c_cidr + vpc_peering_connection_id = aws_vpc_peering_connection.connection_c.id + + } + + route { + cidr_block = var.vpc_a_cidr + vpc_peering_connection_id = aws_vpc_peering_connection.connection_a.id + + } + + + tags = { + Name = "${var.vpc_b_name}-route-table" + } + depends_on = [ aws_vpc.vpc_b, aws_vpc.vpc_c ] +} + +### -------- vpc c route table --------- ### +resource "aws_route_table" "vpc_c_route_table" { + vpc_id = aws_vpc.vpc_c.id + + route { + cidr_block = "0.0.0.0/0" + gateway_id = aws_nat_gateway.vpc_c_nat_gateway.id + + } + + route { + cidr_block = var.vpc_a_cidr + vpc_peering_connection_id = aws_vpc_peering_connection.connection_b.id + + } + + route { + cidr_block = var.vpc_b_cidr + vpc_peering_connection_id = aws_vpc_peering_connection.connection_c.id + + } + tags = { + Name = "${var.vpc_c_name}-route-table" + } + depends_on = [ aws_vpc.vpc_c, aws_vpc.vpc_a ] +} \ No newline at end of file diff --git a/VPC-Peering/Modules/multi-vpc-to-multi-vpc/05-route-table-association.tf b/VPC-Peering/Modules/multi-vpc-to-multi-vpc/05-route-table-association.tf new file mode 100644 index 0000000..2ec14e6 --- /dev/null +++ b/VPC-Peering/Modules/multi-vpc-to-multi-vpc/05-route-table-association.tf @@ -0,0 +1,24 @@ +### --------- vpc A route table association --------- ### +resource "aws_route_table_association" "vpc_a_subnet_1_association" { + subnet_id = aws_subnet.vpc_a_subnet_1.id + route_table_id = aws_route_table.vpc_a_route_table.id + + depends_on = [ aws_route_table.vpc_a_route_table ] + +} + +### --------- vpc B route table association --------- ### +resource "aws_route_table_association" "vpc_b_subnet_1_association" { + subnet_id = aws_subnet.vpc_b_subnet_1.id + route_table_id = aws_route_table.vpc_b_route_table.id + + depends_on = [ aws_route_table.vpc_b_route_table ] +} + +### --------- vpc C route table association --------- ### +resource "aws_route_table_association" "vpc_c_subnet_1_association" { + subnet_id = aws_subnet.vpc_c_subnet_1.id + route_table_id = aws_route_table.vpc_c_route_table.id + + depends_on = [ aws_route_table.vpc_c_route_table ] +} \ No newline at end of file diff --git a/VPC-Peering/Modules/multi-vpc-to-multi-vpc/06-peerings.tf b/VPC-Peering/Modules/multi-vpc-to-multi-vpc/06-peerings.tf new file mode 100644 index 0000000..de654f6 --- /dev/null +++ b/VPC-Peering/Modules/multi-vpc-to-multi-vpc/06-peerings.tf @@ -0,0 +1,101 @@ +data "aws_caller_identity" "peer" {} + +### ------------ VPC A -> VPC B ------------ ### +resource "aws_vpc_peering_connection" "connection_a" { + + peer_owner_id = data.aws_caller_identity.peer.account_id + peer_vpc_id = aws_vpc.vpc_b.id ## Accepter VPC ID + vpc_id = aws_vpc.vpc_a.id ## Requester VPC ID + auto_accept = false + peer_region = var.aws_region + + tags = { + Name = "vpc a -> vpc b" + } + + depends_on = [ aws_vpc.vpc_a, aws_vpc.vpc_b ] +} + + +### Accepters/Destination side of the connection ### +resource "aws_vpc_peering_connection_accepter" "vpc_a_accepter" { + vpc_peering_connection_id = aws_vpc_peering_connection.connection_a.id + auto_accept = true + + + + tags = { + Side = "Accepter" + Name = "vpc b -> vpc a" + } + + depends_on = [ aws_vpc.vpc_a, aws_vpc.vpc_b ] +} + + +### ------------ VPC A -> VPC C ------------ ### +resource "aws_vpc_peering_connection" "connection_b" { + + peer_owner_id = data.aws_caller_identity.peer.account_id + peer_vpc_id = aws_vpc.vpc_c.id ## Accepter VPC ID + vpc_id = aws_vpc.vpc_a.id ## Requester VPC ID + auto_accept = false + peer_region = var.aws_region + + tags = { + Name = "vpc a -> vpc c" + } + + depends_on = [ aws_vpc.vpc_a, aws_vpc.vpc_c ] +} + + +### Accepters/Destination side of the connection ### +resource "aws_vpc_peering_connection_accepter" "vpc_c_accepter" { + vpc_peering_connection_id = aws_vpc_peering_connection.connection_b.id + auto_accept = true + + + + tags = { + Side = "Accepter" + Name = "vpc c -> vpc a" + } + + depends_on = [ aws_vpc.vpc_a, aws_vpc.vpc_c ] +} + + + + +### ------------ VPC C -> VPC B ------------ ### +resource "aws_vpc_peering_connection" "connection_c" { + + peer_owner_id = data.aws_caller_identity.peer.account_id + peer_vpc_id = aws_vpc.vpc_b.id ## Accepter VPC ID + vpc_id = aws_vpc.vpc_c.id ## Requester VPC ID + auto_accept = false + peer_region = var.aws_region + + tags = { + Name = "vpc c -> vpc b" + } + + depends_on = [ aws_vpc.vpc_a, aws_vpc.vpc_c ] +} + + +### Accepters/Destination side of the connection ### +resource "aws_vpc_peering_connection_accepter" "vpc_b_accepter" { + vpc_peering_connection_id = aws_vpc_peering_connection.connection_c.id + auto_accept = true + + + + tags = { + Side = "Accepter" + Name = "vpc b -> vpc c" + } + + depends_on = [ aws_vpc.vpc_b, aws_vpc.vpc_c ] +} \ No newline at end of file diff --git a/VPC-Peering/Modules/multi-vpc-to-multi-vpc/07-iam.tf b/VPC-Peering/Modules/multi-vpc-to-multi-vpc/07-iam.tf new file mode 100644 index 0000000..cccb1d3 --- /dev/null +++ b/VPC-Peering/Modules/multi-vpc-to-multi-vpc/07-iam.tf @@ -0,0 +1,86 @@ +### use the IAM policy created for SSM ### + +resource "aws_iam_policy" "ssm_policy" { + name = "AmazonSSMManagedInstanceCore" + path = "/" + description = "SSM policy" + + # Terraform's "jsonencode" function converts a + # Terraform expression result to valid JSON syntax. + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + "Effect": "Allow", + "Action": [ + "ssm:DescribeAssociation", + "ssm:GetDeployablePatchSnapshotForInstance", + "ssm:GetDocument", + "ssm:DescribeDocument", + "ssm:GetManifest", + "ssm:GetParameter", + "ssm:GetParameters", + "ssm:ListAssociations", + "ssm:ListInstanceAssociations", + "ssm:PutInventory", + "ssm:PutComplianceItems", + "ssm:PutConfigurePackageResult", + "ssm:UpdateAssociationStatus", + "ssm:UpdateInstanceAssociationStatus", + "ssm:UpdateInstanceInformation" + ], + "Resource": "*" + }, + { + "Effect": "Allow", + "Action": [ + "ssmmessages:CreateControlChannel", + "ssmmessages:CreateDataChannel", + "ssmmessages:OpenControlChannel", + "ssmmessages:OpenDataChannel" + ], + "Resource": "*" + }, + { + "Effect": "Allow", + "Action": [ + "ec2messages:AcknowledgeMessage", + "ec2messages:DeleteMessage", + "ec2messages:FailMessage", + "ec2messages:GetEndpoint", + "ec2messages:GetMessages", + "ec2messages:SendReply" + ], + "Resource": "*" + } + ] + }) +} + +data "aws_iam_policy_document" "ssm_policy_doc" { + statement { + actions = [ + "sts:AssumeRole" + ] + principals { + type = "Service" + identifiers = ["ec2.amazonaws.com"] + } + effect = "Allow" + } +} + +resource "aws_iam_role" "ssm_role" { + name = "AmazonSSMManagedInstanceCore1" + assume_role_policy = data.aws_iam_policy_document.ssm_policy_doc.json +} + +resource "aws_iam_role_policy_attachment" "attach_ssm_policy" { + role = aws_iam_role.ssm_role.name + policy_arn = aws_iam_policy.ssm_policy.arn +} + +resource "aws_iam_instance_profile" "ssm_profile" { + name = "AmazonSSMManagedInstanceCore2" + role = aws_iam_role.ssm_role.name +} \ No newline at end of file diff --git a/VPC-Peering/Modules/multi-vpc-to-multi-vpc/08-EC2.tf b/VPC-Peering/Modules/multi-vpc-to-multi-vpc/08-EC2.tf new file mode 100644 index 0000000..e69de29 diff --git a/VPC-Peering/Modules/multi-vpc-to-multi-vpc/09-security-groups.tf b/VPC-Peering/Modules/multi-vpc-to-multi-vpc/09-security-groups.tf new file mode 100644 index 0000000..c20ca22 --- /dev/null +++ b/VPC-Peering/Modules/multi-vpc-to-multi-vpc/09-security-groups.tf @@ -0,0 +1,87 @@ +### -------------- Security Group VPC A ------------- ### +resource "aws_security_group" "vpc_a_sg" { + vpc_id = aws_vpc.vpc_a.id + description = "Security group for VPC A" +} + +resource "aws_security_group_rule" "icmp_source" { + type = "ingress" + from_port = -1 + to_port = -1 + protocol = "icmp" + security_group_id = aws_security_group.vpc_a_sg.id + cidr_blocks = [var.acceptor_cidr] + + + description = "Allow ICMP from destination VPC" + + depends_on = [ aws_security_group.vpc_a_sg ] +} + + + +resource "aws_vpc_security_group_egress_rule" "source_egress" { + security_group_id = aws_security_group.vpc_a_sg.id + + cidr_ipv4 = "0.0.0.0/0" #tfsec:ignore:aws-vpc-no-public-egress-sgr + ip_protocol = "-1" + +} +### -------------- Security Group VPC B ------------- ### +resource "aws_security_group" "vpc_b_sg" { + vpc_id = aws_vpc.vpc_b.id + description = "Security group for VPC B" +} + +resource "aws_security_group_rule" "icmp_source" { + type = "ingress" + from_port = -1 + to_port = -1 + protocol = "icmp" + security_group_id = aws_security_group.vpc_b_sg.id + cidr_blocks = [var.acceptor_cidr] + + + description = "Allow ICMP from destination VPC" + + depends_on = [ aws_security_group.vpc_b_sg ] +} + + + +resource "aws_vpc_security_group_egress_rule" "source_egress" { + security_group_id = aws_security_group.vpc_b_sg.id + + cidr_ipv4 = "0.0.0.0/0" #tfsec:ignore:aws-vpc-no-public-egress-sgr + ip_protocol = "-1" + +} +### -------------- Security Group VPC C ------------- ### +resource "aws_security_group" "vpc_c_sg" { + vpc_id = aws_vpc.vpc_c.id + description = "Security group for source VPC" +} + +resource "aws_security_group_rule" "icmp_source" { + type = "ingress" + from_port = -1 + to_port = -1 + protocol = "icmp" + security_group_id = aws_security_group.vpc_c_sg.id + cidr_blocks = [var.acceptor_cidr] + + + description = "Allow ICMP from destination VPC" + + depends_on = [ aws_security_group.vpc_c_sg ] +} + + + +resource "aws_vpc_security_group_egress_rule" "source_egress" { + security_group_id = aws_security_group.vpc_c_sg.id + + cidr_ipv4 = "0.0.0.0/0" #tfsec:ignore:aws-vpc-no-public-egress-sgr + ip_protocol = "-1" + +} \ No newline at end of file diff --git a/VPC-Peering/Modules/multi-vpc-to-multi-vpc/10-variables.tf b/VPC-Peering/Modules/multi-vpc-to-multi-vpc/10-variables.tf new file mode 100644 index 0000000..9009978 --- /dev/null +++ b/VPC-Peering/Modules/multi-vpc-to-multi-vpc/10-variables.tf @@ -0,0 +1,75 @@ +variable "aws_region" { + description = "AWS region where the VPCs will be created" + type = string + default = "us-east-1" + +} +variable "environment" { + description = "Environment for the VPCs (e.g., dev, staging, prod)" + type = string + +} + +### VPC Variables ### +variable "vpc_a_cidr" { + description = "CIDR block for VPC A" + type = string + +} +variable "vpc_b_cidr" { + description = "CIDR block for VPC B" + type = string + +} +variable "vpc_c_cidr" { + description = "CIDR block for VPC C" + type = string + +} +variable "vpc_a_name" { + description = "Name for VPC A" + type = string +} +variable "vpc_b_name" { + description = "Name for VPC B" + type = string +} +variable "vpc_c_name" { + description = "Name for VPC C" + type = string +} + +### Subnet Variables ### + +### Subnet CIDR blocks for each Subnet ### +variable "vpc_a_subnet_1_cidr" { + description = "CIDR block for VPC A Subnet 1" + type = string +} +variable "vpc_b_subnet_1_cidr" { + description = "CIDR block for VPC B Subnet 1" + type = string +} +variable "vpc_c_subnet_1_cidr" { + description = "CIDR block for VPC C Subnet 1" + type = string +} + +### Subnet Availability Zones for each Subnet ### + +variable "vpc_a_subnet_1_availability_zone" { + description = "Availability Zone for VPC A Subnet 1" + type = string + +} + +variable "vpc_b_subnet_1_availability_zone" { + description = "Availability Zone for VPC B Subnet 1" + type = string + +} +variable "vpc_c_subnet_1_availability_zone" { + description = "Availability Zone for VPC C Subnet 1" + type = string + +} \ No newline at end of file diff --git a/VPC-Peering/Modules/multi-vpc-to-multi-vpc/11-outputs.tf b/VPC-Peering/Modules/multi-vpc-to-multi-vpc/11-outputs.tf new file mode 100644 index 0000000..e69de29 diff --git a/VPC-Peering/Modules/multi-vpc-to-multi-vpc/readme b/VPC-Peering/Modules/multi-vpc-to-multi-vpc/readme new file mode 100644 index 0000000..c338984 --- /dev/null +++ b/VPC-Peering/Modules/multi-vpc-to-multi-vpc/readme @@ -0,0 +1,3 @@ +## What I want to explore in this section + - forech + - \ No newline at end of file diff --git a/VPC-Peering/Modules/single-vpc-to-vpc-v2/main.tf b/VPC-Peering/Modules/single-vpc-to-vpc-v2/main.tf new file mode 100644 index 0000000..a5c7f04 --- /dev/null +++ b/VPC-Peering/Modules/single-vpc-to-vpc-v2/main.tf @@ -0,0 +1,30 @@ +data "aws_caller_identity" "peer" { +} + +### Requesters/Source side of the connection ### +resource "aws_vpc_peering_connection" "this_connection" { + + for_each = var. vpc_peering_connection + peer_owner_id = data.aws_caller_identity.peer.account_id + peer_vpc_id = each.value.peer_vpc_id ## Accepter VPC ID + vpc_id = each.value.vpc_id ## Requester VPC ID + auto_accept = each.value.auto_accept ## Auto accept the connection + peer_region = each.value.peer_region ## Destination VPC region + + tags = var.tags + +} + + +### Accepters/Destination side of the connection ### +resource "aws_vpc_peering_connection_accepter" "dest_peer" { + for_each = aws_vpc_peering_connection.this_connection + vpc_peering_connection_id = each.value.id ## VPC Peering Connection ID + auto_accept = each.value.auto_accept ## Auto accept the connection + + + +tags = var.tags + + +} \ No newline at end of file diff --git a/VPC-Peering/Modules/single-vpc-to-vpc-v2/outputs.tf b/VPC-Peering/Modules/single-vpc-to-vpc-v2/outputs.tf new file mode 100644 index 0000000..6bab74c --- /dev/null +++ b/VPC-Peering/Modules/single-vpc-to-vpc-v2/outputs.tf @@ -0,0 +1,3 @@ +output "this_connection" { + value = { for k, v in aws_vpc_peering_connection.this_connection : k => v.id } +} \ No newline at end of file diff --git a/VPC-Peering/Modules/single-vpc-to-vpc-v2/variables.tf b/VPC-Peering/Modules/single-vpc-to-vpc-v2/variables.tf new file mode 100644 index 0000000..d8ac88e --- /dev/null +++ b/VPC-Peering/Modules/single-vpc-to-vpc-v2/variables.tf @@ -0,0 +1,29 @@ +################################################################### +# VPC Peering Variables +################################################################### + +variable "vpc_peering_connection" { + description = "Map of VPC Peering Connection attributes" + type = map(object({ + name = optional(string) + vpc_id = string # Requester VPC ID + peer_vpc_id = string # Accepter VPC ID + peer_region = optional(string) # Destination VPC region + auto_accept = bool + })) +} + +variable "vpc_peering_accepter" { + description = "Map of VPC Peering Accepter attributes" + type = map(object({ + vpc_peering_connection_id = string + auto_accept = bool + name = optional(string) + })) +} + +variable "tags" { + description = "Map of tags to apply to the VPC Peering Connection and Accepter" + type = map(string) + +} \ No newline at end of file diff --git a/VPC-Peering/Modules/single-vpc-to-vpc/01-source-vpc.tf b/VPC-Peering/Modules/single-vpc-to-vpc/01-source-vpc.tf index 382eda8..e66b3c5 100644 --- a/VPC-Peering/Modules/single-vpc-to-vpc/01-source-vpc.tf +++ b/VPC-Peering/Modules/single-vpc-to-vpc/01-source-vpc.tf @@ -1,6 +1,7 @@ -resource "aws_vpc" "source_vpc" { #tfsec:ignore:aws-ec2-require-vpc-flow-logs-for-all-vpcs - cidr_block = var.source_cidr +#tfsec:ignore:aws-ec2-require-vpc-flow-logs-for-all-vpcs +resource "aws_vpc" "requester_vpc" { + cidr_block = var.requester_vpc_cidr instance_tenancy = "default" enable_dns_support = true enable_dns_hostnames = true @@ -8,212 +9,45 @@ resource "aws_vpc" "source_vpc" { #tfsec:ignore:aws-ec2-require-vpc-flow-logs-f tags = { - Name = var.source_vpc_name + Name = var.requester_vpc_name } } -### Public Subnet ### -resource "aws_subnet" "source_public_subnet" { - provider = aws.us-east - vpc_id = aws_vpc.source_vpc.id - cidr_block = var.source_pub_sub_cidr - availability_zone = var.source_subnet1_az - map_public_ip_on_launch = true #tfsec:ignore:aws-ec2-no-public-ip-subnet - - tags = { - Name = "${var.source_vpc_name}-public-subnet" - } -} - -## Private Subnets ## -resource "aws_subnet" "source_subnet1" { - provider = aws.us-east - vpc_id = aws_vpc.source_vpc.id - cidr_block = var.source_subnet1_cidr - availability_zone = var.source_subnet1_az - map_public_ip_on_launch = false - - tags = { - Name = var.source_subnet1_name - } -} - - -resource "aws_subnet" "source_subnet2" { - provider = aws.us-east - vpc_id = aws_vpc.source_vpc.id - cidr_block = var.source_subnet2_cidr - availability_zone = var.source_subnet2_az - map_public_ip_on_launch = false - - tags = { - Name = var.source_subnet2_name - } -} - -### Private route table for source VPC ### -resource "aws_route_table" "this_source_rt" { - vpc_id = aws_vpc.source_vpc.id - provider = aws.us-east - - route { - cidr_block = var.dest_cidr - vpc_peering_connection_id = aws_vpc_peering_connection.this_connection.id - } - route { - cidr_block = "0.0.0.0/0" - nat_gateway_id = aws_nat_gateway.source_nat_gw.id - - } - tags = { - Name = var.source_rt_name - } - depends_on = [ aws_vpc.source_vpc ] -} - -### Public route table association for source VPC ### -resource "aws_route_table" "public_source_rt" { - vpc_id = aws_vpc.source_vpc.id - provider = aws.us-east - - route { - cidr_block = "0.0.0.0/0" - gateway_id = aws_internet_gateway.this_igw.id - } - - route { - cidr_block = var.dest_cidr - vpc_peering_connection_id = aws_vpc_peering_connection.this_connection.id - } - tags = { - Name = "${var.source_vpc_name}-public-route-table" - } - depends_on = [ aws_vpc.source_vpc ] -} - -resource "aws_route_table_association" "a" { - provider = aws.us-east - subnet_id = aws_subnet.source_subnet1.id - route_table_id = aws_route_table.this_source_rt.id - - depends_on = [ aws_route_table.this_source_rt ] -} - -resource "aws_route_table_association" "b" { - provider = aws.us-east - subnet_id = aws_subnet.source_subnet2.id - route_table_id = aws_route_table.this_source_rt.id - - depends_on = [ aws_route_table.this_source_rt ] -} - -resource "aws_route_table_association" "pub_a" { - provider = aws.us-east - subnet_id = aws_subnet.source_public_subnet.id - route_table_id = aws_route_table.public_source_rt.id - - depends_on = [ aws_route_table.public_source_rt ] -} ### Elastic IP for NAT Gateway ### -resource "aws_eip" "source_nat_eip" { +resource "aws_eip" "requester_nat_eip" { provider = aws.us-east tags = { - Name = "${var.source_vpc_name}-nat-eip" + Name = "${var.requester_vpc_name}-nat-eip" } - depends_on = [ aws_vpc.source_vpc ] + depends_on = [ aws_vpc.requester_vpc ] } -resource "aws_nat_gateway" "source_nat_gw" { +resource "aws_nat_gateway" "requester_nat_gw" { provider = aws.us-east - allocation_id = aws_eip.source_nat_eip.id - subnet_id = aws_subnet.source_public_subnet.id + allocation_id = aws_eip.requester_nat_eip.id + subnet_id = aws_subnet.requester_public_subnet.id tags = { - Name = "${var.source_vpc_name}-nat-gateway" + Name = "${var.requester_vpc_name}-nat-gateway" } - depends_on = [aws_eip.source_nat_eip ] + depends_on = [aws_eip.requester_nat_eip ] } ### Internet Gateway ### resource "aws_internet_gateway" "this_igw" { provider = aws.us-east - vpc_id = aws_vpc.source_vpc.id + vpc_id = aws_vpc.requester_vpc.id - depends_on = [ aws_vpc.source_vpc ] + depends_on = [ aws_vpc.requester_vpc ] tags = { - Name = "${var.source_vpc_name}-igw" + Name = "${var.requester_vpc_name}-igw" } } -### Security Group for Source VPC ### -resource "aws_security_group" "source_sg" { - provider = aws.us-east - vpc_id = aws_vpc.source_vpc.id - description = "Security group for source VPC" -} - -resource "aws_security_group_rule" "icmp_source" { - provider = aws.us-east - type = "ingress" - from_port = -1 - to_port = -1 - protocol = "icmp" - security_group_id = aws_security_group.source_sg.id - cidr_blocks = [var.dest_cidr] #tfsec:ignore:aws-vpc-no-public-ingress-sgr - - - description = "Allow ICMP from destination VPC" - - depends_on = [ aws_security_group.source_sg ] -} -resource "aws_security_group_rule" "ssh_source" { - provider = aws.us-east - type = "ingress" - from_port = 22 - to_port = 22 - protocol = "tcp" - security_group_id = aws_security_group.source_sg.id - cidr_blocks = ["0.0.0.0/0"] #tfsec:ignore:aws-vpc-no-public-ingress-sgr - - description = "Allow ICMP from destination VPC" - - depends_on = [ aws_security_group.source_sg ] -} - - -resource "aws_vpc_security_group_egress_rule" "source_egress" { - security_group_id = aws_security_group.source_sg.id - provider = aws.us-east - - cidr_ipv4 = "0.0.0.0/0" #tfsec:ignore:aws-vpc-no-public-ingress-sgr - ip_protocol = "-1" - -} - - -# } -### EC2 Instance in Source VPC ### -resource "aws_instance" "source_instance" { - provider = aws.us-east - ami = "ami-084568db4383264d4" # use the ami from your specific region - instance_type = "t2.micro" - subnet_id = aws_subnet.source_public_subnet.id - vpc_security_group_ids = [aws_security_group.source_sg.id] - metadata_options { - http_tokens = "required" - } - root_block_device { - encrypted = true - } - tags = { - Name = "${var.source_vpc_name}-instance" - } - depends_on = [aws_vpc.source_vpc, aws_subnet.source_subnet1] -} \ No newline at end of file diff --git a/VPC-Peering/Modules/single-vpc-to-vpc/02-destination-vpc.tf b/VPC-Peering/Modules/single-vpc-to-vpc/02-destination-vpc.tf index 5ee3ad5..161365e 100644 --- a/VPC-Peering/Modules/single-vpc-to-vpc/02-destination-vpc.tf +++ b/VPC-Peering/Modules/single-vpc-to-vpc/02-destination-vpc.tf @@ -1,219 +1,50 @@ -resource "aws_vpc" "destination_vpc" { #tfsec:ignore:aws-ec2-require-vpc-flow-logs-for-all-vpcs - cidr_block = var.dest_cidr +#tfsec:ignore:aws-ec2-require-vpc-flow-logs-for-all-vpcs +resource "aws_vpc" "acceptor_vpc" { + cidr_block = var.acceptor_cidr instance_tenancy = "default" + enable_dns_support = true enable_dns_hostnames = true provider = aws.us-west tags = { - Name = var.dest_vpc_name + Name = var.acceptor_vpc_name Environment = var.environment } } -resource "aws_subnet" "dest_subnet1" { - provider = aws.us-west - vpc_id = aws_vpc.destination_vpc.id - cidr_block = var.dest_subnet1_cidr - availability_zone = var.dest_subnet1_az - map_public_ip_on_launch = false - - tags = { - Name = var.dest_subnet1_name - } -} - - -resource "aws_subnet" "dest_subnet2" { - provider = aws.us-west - vpc_id = aws_vpc.destination_vpc.id - cidr_block = var.dest_subnet2_cidr - availability_zone = var.dest_subnet2_az - map_public_ip_on_launch = false - - tags = { - Name = var.dest_subnet2_name - } -} - -### Public Subnet ### -resource "aws_subnet" "dest_public_subnet" { - provider = aws.us-west - vpc_id = aws_vpc.destination_vpc.id - cidr_block = var.dest_pub_sub_cidr - availability_zone = var.dest_subnet1_az - map_public_ip_on_launch = true #tfsec:ignore:aws-ec2-no-public-ip-subnet - - tags = { - Name = "${var.dest_vpc_name}-public-subnet" - } -} - -### Private route table for destination VPC ### -resource "aws_route_table" "this_rt" { - vpc_id = aws_vpc.destination_vpc.id - provider = aws.us-west - - route { - cidr_block = var.source_cidr - vpc_peering_connection_id = aws_vpc_peering_connection.this_connection.id - } - route { - cidr_block = "0.0.0.0/0" - nat_gateway_id = aws_nat_gateway.dest_nat_gw.id - } - - tags = { - Name = var.dest_rt_name - } - depends_on = [ aws_vpc.destination_vpc ] -} - -### Route Table for Public Subnet ### -resource "aws_route_table" "this_pub_rt" { - vpc_id = aws_vpc.destination_vpc.id - provider = aws.us-west - - route { - cidr_block = "0.0.0.0/0" - gateway_id = aws_internet_gateway.dest_igw.id - - } - route { - cidr_block = var.source_cidr - vpc_peering_connection_id = aws_vpc_peering_connection.this_connection.id - } - - tags = { - Name = "${var.dest_vpc_name}-public-route-table" - } - depends_on = [ aws_vpc.destination_vpc ] -} - -resource "aws_route_table_association" "c" { - provider = aws.us-west - subnet_id = aws_subnet.dest_subnet1.id - route_table_id = aws_route_table.this_rt.id - - depends_on = [ aws_route_table.this_rt ] -} - -resource "aws_route_table_association" "d" { - provider = aws.us-west - subnet_id = aws_subnet.dest_subnet2.id - route_table_id = aws_route_table.this_rt.id - - depends_on = [ aws_route_table.this_rt ] -} - -resource "aws_route_table_association" "dest_d" { - provider = aws.us-west - subnet_id = aws_subnet.dest_public_subnet.id - route_table_id = aws_route_table.this_pub_rt.id - - depends_on = [ aws_route_table.this_pub_rt ] -} - - ### Elastic IP for NAT Gateway ### -resource "aws_eip" "nat_eip" { +resource "aws_eip" "acceptor_nat_eip" { provider = aws.us-west tags = { - Name = "${var.dest_vpc_name}-nat-eip" + Name = "${var.acceptor_vpc_name}-nat-eip" } - depends_on = [ aws_vpc.destination_vpc ] + depends_on = [ aws_vpc.acceptor_vpc ] } -resource "aws_nat_gateway" "dest_nat_gw" { +resource "aws_nat_gateway" "acceptor_nat_gw" { provider = aws.us-west - allocation_id = aws_eip.nat_eip.id - subnet_id = aws_subnet.dest_public_subnet.id + allocation_id = aws_eip.acceptor_nat_eip.id + subnet_id = aws_subnet.acceptor_public_subnet.id tags = { - Name = "${var.dest_vpc_name}-nat-gateway" + Name = "${var.acceptor_vpc_name}-nat-gateway" } - depends_on = [ aws_eip.nat_eip ] + depends_on = [ aws_eip.acceptor_nat_eip ] } ### Internet Gateway ### -resource "aws_internet_gateway" "dest_igw" { +resource "aws_internet_gateway" "acceptor_igw" { provider = aws.us-west - vpc_id = aws_vpc.destination_vpc.id + vpc_id = aws_vpc.acceptor_vpc.id - depends_on = [ aws_vpc.destination_vpc ] + depends_on = [ aws_vpc.acceptor_vpc ] tags = { - Name = "${var.dest_vpc_name}-igw" + Name = "${var.acceptor_vpc_name}-igw" } -} - -### Security Group for destination VPC ### - -resource "aws_security_group" "dest_sg" { - provider = aws.us-west - vpc_id = aws_vpc.destination_vpc.id - description = "Security group for destination VPC" -} - -resource "aws_security_group_rule" "ssh_dest" { - provider = aws.us-west - type = "ingress" - from_port = 22 - to_port = 22 - protocol = "tcp" - security_group_id = aws_security_group.dest_sg.id - cidr_blocks = ["0.0.0.0/0"] #tfsec:ignore:aws-vpc-no-public-ingress-sgr - - description = "Allow ICMP from source VPC" - - depends_on = [ aws_security_group.dest_sg ] -} -resource "aws_security_group_rule" "icmp_dest" { - provider = aws.us-west - type = "ingress" - from_port = -1 - to_port = -1 - protocol = "icmp" - security_group_id = aws_security_group.dest_sg.id - cidr_blocks = [var.source_cidr] #tfsec:ignore:aws-vpc-no-public-ingress-sgr - - description = "Allow ICMP from source VPC" - - depends_on = [ aws_security_group.dest_sg ] -} - - -resource "aws_vpc_security_group_egress_rule" "dest_egress" { - security_group_id = aws_security_group.dest_sg.id - provider = aws.us-west - - cidr_ipv4 = "0.0.0.0/0" #tfsec:ignore:aws-vpc-no-public-ingress-sgr - ip_protocol = "-1" - - -} - -### EC2 Instance in Source VPC ### -resource "aws_instance" "dest_instance" { - provider = aws.us-west - ami = "ami-075686beab831bb7f" # use the ami from your specific region - instance_type = "t2.micro" - subnet_id = aws_subnet.dest_subnet1.id - vpc_security_group_ids = [aws_security_group.dest_sg.id] - metadata_options { - http_tokens = "required" - } - - root_block_device { - encrypted = true - } - tags = { - Name = "${var.dest_vpc_name}-instance" - } - - depends_on = [aws_vpc.destination_vpc, aws_subnet.dest_subnet1] } \ No newline at end of file diff --git a/VPC-Peering/Modules/single-vpc-to-vpc/03-peering.tf b/VPC-Peering/Modules/single-vpc-to-vpc/03-peering.tf index f72ee54..8004564 100644 --- a/VPC-Peering/Modules/single-vpc-to-vpc/03-peering.tf +++ b/VPC-Peering/Modules/single-vpc-to-vpc/03-peering.tf @@ -6,16 +6,16 @@ data "aws_caller_identity" "peer" { resource "aws_vpc_peering_connection" "this_connection" { provider = aws.us-east peer_owner_id = data.aws_caller_identity.peer.account_id - peer_vpc_id = aws_vpc.destination_vpc.id ## Accepter VPC ID - vpc_id = aws_vpc.source_vpc.id ## Requester VPC ID + peer_vpc_id = aws_vpc.acceptor_vpc.id ## Accepter VPC ID + vpc_id = aws_vpc.requester_vpc.id ## Requester VPC ID auto_accept = false - peer_region = var.dest_region ## Destination VPC region + peer_region = var.acceptor_region ## Destination VPC region tags = { Name = "east -> west" } - depends_on = [ aws_vpc.source_vpc, aws_vpc.destination_vpc ] + depends_on = [ aws_vpc.requester_vpc, aws_vpc.acceptor_vpc ] } @@ -32,5 +32,5 @@ resource "aws_vpc_peering_connection_accepter" "dest_peer" { Name = "west -> east" } - depends_on = [ aws_vpc.source_vpc, aws_vpc.destination_vpc ] -} + depends_on = [ aws_vpc.requester_vpc, aws_vpc.acceptor_vpc ] +} \ No newline at end of file diff --git a/VPC-Peering/Modules/single-vpc-to-vpc/04-subnet.tf b/VPC-Peering/Modules/single-vpc-to-vpc/04-subnet.tf new file mode 100644 index 0000000..9d28536 --- /dev/null +++ b/VPC-Peering/Modules/single-vpc-to-vpc/04-subnet.tf @@ -0,0 +1,78 @@ +### Subnets for Source VPC ### +### Public Subnet ### +resource "aws_subnet" "requester_public_subnet" { + provider = aws.us-east + vpc_id = aws_vpc.requester_vpc.id + cidr_block = var.requester_vpc_pub_sub_cidr + availability_zone = var.requester_subnet1_az + map_public_ip_on_launch = var.map_public_ip_on_launch #tfsec:ignore:aws-ec2-no-public-ip-subnet + + tags = { + Name = "${var.requester_vpc_name}-public-subnet" + } +} + +## Private Subnets ## +resource "aws_subnet" "requester_subnet1" { + provider = aws.us-east + vpc_id = aws_vpc.requester_vpc.id + cidr_block = var.requester_subnet1_cidr + availability_zone = var.requester_subnet1_az + map_public_ip_on_launch = var.map_public_ip_on_launch + + tags = { + Name = var.requester_subnet1_name + } +} + + +resource "aws_subnet" "requester_subnet2" { + provider = aws.us-east + vpc_id = aws_vpc.requester_vpc.id + cidr_block = var.requester_subnet2_cidr + availability_zone = var.requester_subnet2_az + map_public_ip_on_launch = var.map_public_ip_on_launch + + tags = { + Name = var.requester_subnet2_name + } +} + +### Subnets for Destination VPC ### +resource "aws_subnet" "acceptor_subnet1" { + provider = aws.us-west + vpc_id = aws_vpc.acceptor_vpc.id + cidr_block = var.acceptor_subnet1_cidr + availability_zone = var.acceptor_subnet1_az + map_public_ip_on_launch = var.map_public_ip_on_launch + + tags = { + Name = var.acceptor_subnet1_name + } +} + + +resource "aws_subnet" "acceptor_subnet2" { + provider = aws.us-west + vpc_id = aws_vpc.acceptor_vpc.id + cidr_block = var.acceptor_subnet2_cidr + availability_zone = var.acceptor_subnet2_az + map_public_ip_on_launch = var.map_public_ip_on_launch + + tags = { + Name = var.acceptor_subnet2_name + } +} + +### Public Subnet ### +resource "aws_subnet" "acceptor_public_subnet" { + provider = aws.us-west + vpc_id = aws_vpc.acceptor_vpc.id + cidr_block = var.acceptor_pub_sub_cidr + availability_zone = var.acceptor_subnet1_az + map_public_ip_on_launch = var.map_public_ip_on_launch #tfsec:ignore:aws-ec2-no-public-ip-subnet + + tags = { + Name = "${var.acceptor_vpc_name}-public-subnet" + } +} \ No newline at end of file diff --git a/VPC-Peering/Modules/single-vpc-to-vpc/05-EC2.tf b/VPC-Peering/Modules/single-vpc-to-vpc/05-EC2.tf new file mode 100644 index 0000000..08d2d11 --- /dev/null +++ b/VPC-Peering/Modules/single-vpc-to-vpc/05-EC2.tf @@ -0,0 +1,42 @@ +### EC2 Instance in Source VPC ### +resource "aws_instance" "source_instance" { + provider = aws.us-east + ami = var.requester_ami_id # use the ami from your specific region + instance_type = var.instance_type + iam_instance_profile = aws_iam_instance_profile.ssm_profile.name + subnet_id = aws_subnet.requester_subnet1.id ## Ensure this is the private subnet, for SSM access + vpc_security_group_ids = [aws_security_group.requester_sg.id] + metadata_options { + http_tokens = "required" + } + root_block_device { + encrypted = true + } + tags = { + Name = "${var.requester_vpc_name}-instance" + } + + depends_on = [aws_vpc.requester_vpc, aws_subnet.requester_subnet1] +} + +### EC2 Instance in Destination VPC ### +resource "aws_instance" "acceptor_instance" { + provider = aws.us-west + ami = var.acceptor_ami_id # use the ami from your specific region + instance_type = var.instance_type + iam_instance_profile = aws_iam_instance_profile.ssm_profile.name + subnet_id = aws_subnet.acceptor_subnet1.id ## Ensure this is the private subnet, for SSM access + vpc_security_group_ids = [aws_security_group.acceptor_sg.id] + metadata_options { + http_tokens = "required" + } + + root_block_device { + encrypted = true + } + tags = { + Name = "${var.acceptor_vpc_name}-instance" + } + + depends_on = [aws_vpc.acceptor_vpc, aws_subnet.acceptor_subnet1] +} \ No newline at end of file diff --git a/VPC-Peering/Modules/single-vpc-to-vpc/06-security-groups.tf b/VPC-Peering/Modules/single-vpc-to-vpc/06-security-groups.tf new file mode 100644 index 0000000..57a2614 --- /dev/null +++ b/VPC-Peering/Modules/single-vpc-to-vpc/06-security-groups.tf @@ -0,0 +1,69 @@ +### -------------- Security Group for Source VPC ------------- ### +resource "aws_security_group" "requester_sg" { + provider = aws.us-east + vpc_id = aws_vpc.requester_vpc.id + description = "Security group for source VPC" +} + +resource "aws_security_group_rule" "icmp_source" { + provider = aws.us-east + type = "ingress" + from_port = -1 + to_port = -1 + protocol = "icmp" + security_group_id = aws_security_group.requester_sg.id + cidr_blocks = [var.acceptor_cidr] + + + description = "Allow ICMP from destination VPC" + + depends_on = [ aws_security_group.requester_sg ] +} + + + +resource "aws_vpc_security_group_egress_rule" "source_egress" { + security_group_id = aws_security_group.requester_sg.id + provider = aws.us-east + + cidr_ipv4 = "0.0.0.0/0" #tfsec:ignore:aws-vpc-no-public-egress-sgr + ip_protocol = "-1" + +} + + +### ---------------- Destination VPC Security Group ------------- ### + +### Security Group for destination VPC ### + +resource "aws_security_group" "acceptor_sg" { + provider = aws.us-west + vpc_id = aws_vpc.acceptor_vpc.id + description = "Security group for destination VPC" +} + +resource "aws_security_group_rule" "icmp_dest" { + provider = aws.us-west + type = "ingress" + from_port = -1 + to_port = -1 + protocol = "icmp" + security_group_id = aws_security_group.acceptor_sg.id + cidr_blocks = [var.requester_vpc_cidr] + + description = "Allow ICMP from source VPC" + + depends_on = [ aws_security_group.acceptor_sg ] +} + + + +resource "aws_vpc_security_group_egress_rule" "dest_egress" { + security_group_id = aws_security_group.acceptor_sg.id + provider = aws.us-west + + cidr_ipv4 = "0.0.0.0/0" #tfsec:ignore:aws-vpc-no-public-egress-sgr + ip_protocol = "-1" + + +} \ No newline at end of file diff --git a/VPC-Peering/Modules/single-vpc-to-vpc/07-route-tables.tf b/VPC-Peering/Modules/single-vpc-to-vpc/07-route-tables.tf new file mode 100644 index 0000000..88aaaef --- /dev/null +++ b/VPC-Peering/Modules/single-vpc-to-vpc/07-route-tables.tf @@ -0,0 +1,79 @@ +### Source/Requester VPC Route Tables ### + +resource "aws_route_table" "requestor_rt" { + vpc_id = aws_vpc.requester_vpc.id + provider = aws.us-east + + route { + cidr_block = var.acceptor_cidr + vpc_peering_connection_id = aws_vpc_peering_connection.this_connection.id + } + route { + cidr_block = "0.0.0.0/0" + nat_gateway_id = aws_nat_gateway.requester_nat_gw.id + + } + tags = { + Name = var.requester_rt_name + } + depends_on = [ aws_vpc.requester_vpc ] +} + +### Public route table for source VPC ### +resource "aws_route_table" "public_source_rt" { + vpc_id = aws_vpc.requester_vpc.id + provider = aws.us-east + + route { + cidr_block = "0.0.0.0/0" + gateway_id = aws_internet_gateway.this_igw.id + } + + route { + cidr_block = var.acceptor_cidr + vpc_peering_connection_id = aws_vpc_peering_connection.this_connection.id + } + tags = { + Name = "${var.requester_vpc_name}-public-route-table" + } + depends_on = [ aws_vpc.requester_vpc ] +} + +### Destination/ Accepter VPC Route Tables ### + +### Private route table for destination VPC ### +resource "aws_route_table" "this_rt" { + vpc_id = aws_vpc.acceptor_vpc.id + provider = aws.us-west + + route { + cidr_block = var.requester_vpc_cidr + vpc_peering_connection_id = aws_vpc_peering_connection.this_connection.id + } + route { + cidr_block = "0.0.0.0/0" + nat_gateway_id = aws_nat_gateway.acceptor_nat_gw.id + } + + tags = { + Name = var.acceptor_rt_name + } + depends_on = [ aws_vpc.acceptor_vpc ] +} + +### Route Table for Public Subnet ### +resource "aws_route_table" "this_pub_rt" { + vpc_id = aws_vpc.acceptor_vpc.id + provider = aws.us-west + + route { + cidr_block = "0.0.0.0/0" + gateway_id = aws_internet_gateway.acceptor_igw.id + + } + + tags = { + Name = "${var.acceptor_vpc_name}-public-route-table" + } + depends_on = [ aws_vpc.acceptor_vpc ] +} \ No newline at end of file diff --git a/VPC-Peering/Modules/single-vpc-to-vpc/08-route-table-associations.tf b/VPC-Peering/Modules/single-vpc-to-vpc/08-route-table-associations.tf new file mode 100644 index 0000000..300237d --- /dev/null +++ b/VPC-Peering/Modules/single-vpc-to-vpc/08-route-table-associations.tf @@ -0,0 +1,51 @@ +### Route Table Association for Source ### + +resource "aws_route_table_association" "a" { + provider = aws.us-east + subnet_id = aws_subnet.requester_subnet1.id + route_table_id = aws_route_table.requestor_rt.id + + depends_on = [ aws_route_table.requestor_rt ] +} + +resource "aws_route_table_association" "b" { + provider = aws.us-east + subnet_id = aws_subnet.requester_subnet2.id + route_table_id = aws_route_table.requestor_rt.id + + depends_on = [ aws_route_table.requestor_rt ] +} + +resource "aws_route_table_association" "pub_a" { + provider = aws.us-east + subnet_id = aws_subnet.requester_public_subnet.id + route_table_id = aws_route_table.public_source_rt.id + + depends_on = [ aws_route_table.public_source_rt ] +} + +### Route Table Association for Destination VPC Public Subnet + +resource "aws_route_table_association" "c" { + provider = aws.us-west + subnet_id = aws_subnet.acceptor_subnet1.id + route_table_id = aws_route_table.this_rt.id + + depends_on = [ aws_route_table.this_rt ] +} + +resource "aws_route_table_association" "d" { + provider = aws.us-west + subnet_id = aws_subnet.acceptor_subnet2.id + route_table_id = aws_route_table.this_rt.id + + depends_on = [ aws_route_table.this_rt ] +} + +resource "aws_route_table_association" "dest_d" { + provider = aws.us-west + subnet_id = aws_subnet.acceptor_public_subnet.id + route_table_id = aws_route_table.this_pub_rt.id + + depends_on = [ aws_route_table.this_pub_rt ] +} \ No newline at end of file diff --git a/VPC-Peering/Modules/single-vpc-to-vpc/09-iam.tf b/VPC-Peering/Modules/single-vpc-to-vpc/09-iam.tf new file mode 100644 index 0000000..cccb1d3 --- /dev/null +++ b/VPC-Peering/Modules/single-vpc-to-vpc/09-iam.tf @@ -0,0 +1,86 @@ +### use the IAM policy created for SSM ### + +resource "aws_iam_policy" "ssm_policy" { + name = "AmazonSSMManagedInstanceCore" + path = "/" + description = "SSM policy" + + # Terraform's "jsonencode" function converts a + # Terraform expression result to valid JSON syntax. + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + "Effect": "Allow", + "Action": [ + "ssm:DescribeAssociation", + "ssm:GetDeployablePatchSnapshotForInstance", + "ssm:GetDocument", + "ssm:DescribeDocument", + "ssm:GetManifest", + "ssm:GetParameter", + "ssm:GetParameters", + "ssm:ListAssociations", + "ssm:ListInstanceAssociations", + "ssm:PutInventory", + "ssm:PutComplianceItems", + "ssm:PutConfigurePackageResult", + "ssm:UpdateAssociationStatus", + "ssm:UpdateInstanceAssociationStatus", + "ssm:UpdateInstanceInformation" + ], + "Resource": "*" + }, + { + "Effect": "Allow", + "Action": [ + "ssmmessages:CreateControlChannel", + "ssmmessages:CreateDataChannel", + "ssmmessages:OpenControlChannel", + "ssmmessages:OpenDataChannel" + ], + "Resource": "*" + }, + { + "Effect": "Allow", + "Action": [ + "ec2messages:AcknowledgeMessage", + "ec2messages:DeleteMessage", + "ec2messages:FailMessage", + "ec2messages:GetEndpoint", + "ec2messages:GetMessages", + "ec2messages:SendReply" + ], + "Resource": "*" + } + ] + }) +} + +data "aws_iam_policy_document" "ssm_policy_doc" { + statement { + actions = [ + "sts:AssumeRole" + ] + principals { + type = "Service" + identifiers = ["ec2.amazonaws.com"] + } + effect = "Allow" + } +} + +resource "aws_iam_role" "ssm_role" { + name = "AmazonSSMManagedInstanceCore1" + assume_role_policy = data.aws_iam_policy_document.ssm_policy_doc.json +} + +resource "aws_iam_role_policy_attachment" "attach_ssm_policy" { + role = aws_iam_role.ssm_role.name + policy_arn = aws_iam_policy.ssm_policy.arn +} + +resource "aws_iam_instance_profile" "ssm_profile" { + name = "AmazonSSMManagedInstanceCore2" + role = aws_iam_role.ssm_role.name +} \ No newline at end of file diff --git a/VPC-Peering/Modules/single-vpc-to-vpc/04-variables.tf b/VPC-Peering/Modules/single-vpc-to-vpc/10-variables.tf similarity index 59% rename from VPC-Peering/Modules/single-vpc-to-vpc/04-variables.tf rename to VPC-Peering/Modules/single-vpc-to-vpc/10-variables.tf index d977854..933a272 100644 --- a/VPC-Peering/Modules/single-vpc-to-vpc/04-variables.tf +++ b/VPC-Peering/Modules/single-vpc-to-vpc/10-variables.tf @@ -4,12 +4,12 @@ variable "environment" { } -variable "source_region" { +variable "requestor_vpc_region" { description = "The AWS region for the source VPC" type = string } -variable "dest_region" { +variable "acceptor_region" { description = "The AWS region for the destination VPC" type = string @@ -19,122 +19,145 @@ variable "dest_region" { ### Source VPC Variables ### -variable "source_vpc_name" { +variable "requester_vpc_name" { description = "Name for the source VPC" type = string } -variable "source_cidr" { +variable "requester_vpc_cidr" { description = "CIDR block for the destination VPC" type = string } -variable "source_pub_sub_cidr" { +variable "requester_vpc_pub_sub_cidr" { description = "CIDR block for the public subnet" type = string } -variable "source_subnet1_cidr" { +variable "requester_subnet1_cidr" { description = "CIDR block for the first destination subnet" type = string } -variable "source_subnet1_name" { +variable "requester_subnet1_name" { description = "Name for the first destination subnet" type = string } -variable "source_subnet1_az" { +variable "requester_subnet1_az" { description = "Availability Zone for the first destination subnet" type = string } -variable "source_subnet2_name" { +variable "requester_subnet2_name" { description = "Name for the second destination subnet" type = string } -variable "source_subnet2_cidr" { +variable "requester_subnet2_cidr" { description = "CIDR block for the second destination subnet" type = string } -variable "source_subnet2_az" { +variable "requester_subnet2_az" { description = "Availability Zone for the second destination subnet" type = string } -variable "source_rt_name" { +variable "requester_rt_name" { description = "Name for the destination route table" type = string } -### Destination VPC Variables ### +### Acceptor VPC Variables ### -variable "dest_vpc_name" { +variable "acceptor_vpc_name" { description = "Name for the source VPC" type = string } -variable "dest_cidr" { +variable "acceptor_cidr" { description = "CIDR block for the destination VPC" type = string } -variable "dest_subnet1_cidr" { +variable "acceptor_subnet1_cidr" { description = "CIDR block for the first destination subnet" type = string } -variable "dest_subnet1_name" { +variable "acceptor_subnet1_name" { description = "Name for the first destination subnet" type = string } -variable "dest_subnet1_az" { +variable "acceptor_subnet1_az" { description = "Availability Zone for the first destination subnet" type = string } -variable "dest_subnet2_name" { +variable "acceptor_subnet2_name" { description = "Name for the second destination subnet" type = string } -variable "dest_pub_sub_cidr" { +variable "acceptor_pub_sub_cidr" { description = "CIDR block for the public subnet" type = string } -variable "dest_subnet2_cidr" { +variable "acceptor_subnet2_cidr" { description = "CIDR block for the second destination subnet" type = string } -variable "dest_subnet2_az" { +variable "acceptor_subnet2_az" { description = "Availability Zone for the second destination subnet" type = string } -variable "dest_rt_name" { +variable "acceptor_rt_name" { description = "Name for the destination route table" type = string +} +variable "map_public_ip_on_launch" { + description = "Whether to map public IPs on launch for subnets, defaults to false" + type = bool + default = false + +} + +### EC2 Instance Variables ### + +variable "requester_ami_id" { + description = "ami id for the source VPC EC2 instance. MUST BE REGION SPECIFIC" + type = string +} + +variable "acceptor_ami_id" { + description = "ami id for the destination VPC EC2 instance. MUST BE REGION SPECIFIC" + type = string +} +variable "instance_type" { + description = "Instance type for the EC2 instances in both VPCs" + type = string + default = "t2.micro" } \ No newline at end of file diff --git a/VPC-Peering/Modules/single-vpc-to-vpc/11-outputs.tf b/VPC-Peering/Modules/single-vpc-to-vpc/11-outputs.tf new file mode 100644 index 0000000..e69de29 diff --git a/VPC/.gitignore b/VPC/.gitignore new file mode 100644 index 0000000..1e1ac26 --- /dev/null +++ b/VPC/.gitignore @@ -0,0 +1,41 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl + +# Ignore the .DS_Store files created by macOS +.DS_Store \ No newline at end of file diff --git a/VPC/Environment/Dev/.gitignore b/VPC/Environment/Dev/.gitignore new file mode 100644 index 0000000..1e1ac26 --- /dev/null +++ b/VPC/Environment/Dev/.gitignore @@ -0,0 +1,41 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl + +# Ignore the .DS_Store files created by macOS +.DS_Store \ No newline at end of file diff --git a/VPC/Environment/Dev/backend.tf b/VPC/Environment/Dev/backend.tf new file mode 100644 index 0000000..409aaf7 --- /dev/null +++ b/VPC/Environment/Dev/backend.tf @@ -0,0 +1,8 @@ +terraform { + backend "s3" { + bucket = "terraform-state-bucket1237546" + key = "dev-vpc-by-terraform-state.tfstate" + region = "us-east-1" + use_lockfile = true + } +} diff --git a/VPC/Environment/Dev/main.tf b/VPC/Environment/Dev/main.tf new file mode 100644 index 0000000..5bd83ee --- /dev/null +++ b/VPC/Environment/Dev/main.tf @@ -0,0 +1,25 @@ + +locals { + region = "us-east-1" +} + +module "vpc" { + source = "../../Modules/vpc" + create_vpc = "true" + vpc_cidr = "10.0.0.0/16" + enable_dns_hostnames = "true" + enable_dns_support = "true" + public_subnets_cidr_blocks = ["10.0.0.0/24", "10.0.1.0/24", "10.0.2.0/24"] + private_subnets_cidr_blocks = ["10.0.3.0/24", "10.0.4.0/24", "10.0.5.0/24"] + availability_zones = ["us-east-1a", "us-east-1b", "us-east-1c"] + map_public_ip_on_launch = "true" + map_public_ip_on_private_subs = "false" + create_nat = "true" + name = "smooth" + create_igw = "true" + tags = { + Environment = "Dev" + Project = "Smooth" + } + +} \ No newline at end of file diff --git a/VPC/Environment/Dev/outputs.tf b/VPC/Environment/Dev/outputs.tf new file mode 100644 index 0000000..ba419a2 --- /dev/null +++ b/VPC/Environment/Dev/outputs.tf @@ -0,0 +1,40 @@ +output "vpc_id" { + description = "The ID of the VPC" + value = module.vpc.vpc_id +} + +output "vpc_cidr" { + description = "VPC CIDR" + value = module.vpc.vpc_cidr +} +output "igw_id" { + description = "The ID of the Internet Gateway" + value = module.vpc.igw_id +} + +output "igw_arn" { + description = "The ARN of the Internet Gateway" + value = module.vpc.igw_arn +} +output "public_subnets" { + description = "List of IDs of public subnets" + value = module.vpc.public_subnets +} +output "public_subnet_arns" { + description = "List of ARNs of public subnets" + value = module.vpc.public_subnet_arns +} +output "public_subnets_cidr_blocks" { + description = "List of cidr_blocks of public subnets" + value = module.vpc.public_subnets_cidr_blocks +} + +output "private_subnets" { + description = "List of IDs of private subnets" + value = module.vpc.private_subnets +} + +output "private_subnets_cidr_blocks" { + description = "List of cidr_blocks of private subnets" + value = module.vpc.private_subnets_cidr_blocks +} \ No newline at end of file diff --git a/VPC/Environment/Dev/providers.tf b/VPC/Environment/Dev/providers.tf new file mode 100644 index 0000000..bd011dc --- /dev/null +++ b/VPC/Environment/Dev/providers.tf @@ -0,0 +1,13 @@ +terraform { + required_version = ">= 1.0" + required_providers { + aws = { + source = "hashicorp/aws" + version = "6.0.0-beta2" + } + } + +} +provider "aws" { + region = local.region +} diff --git a/VPC/Environment/Dev/variables.tf b/VPC/Environment/Dev/variables.tf new file mode 100644 index 0000000..6fdf93d --- /dev/null +++ b/VPC/Environment/Dev/variables.tf @@ -0,0 +1,83 @@ +variable "create_vpc" { + description = "Create a new VPC" + type = bool + default = true + +} + +variable "vpc_cidr" { + description = "CIDR block for the VPC" + type = string + default = "" +} + +variable "enable_dns_hostnames" { + description = "Enable DNS hostnames in the VPC" + type = bool + default = true +} + +variable "enable_dns_support" { + description = "Enable DNS support in the VPC" + type = bool + default = true +} + +variable "public_subnets_cidr_blocks" { + description = "List of CIDR blocks for public subnets" + type = list(string) + default = [""] + +} + +variable "availability_zones" { + description = "List of availability zones for the VPC" + type = list(string) + default = [""] + +} + +variable "map_public_ip_on_launch" { + description = "Map public IP on launch for public subnets" + type = bool + default = true + +} + +variable "map_public_ip_on_private_subs" { + description = "Map public IP on launch for public subnets" + type = bool + default = false + +} + +######### private subnets ######### +variable "private_subnets_cidr_blocks" { + description = "List of private subnets CIDR blocks" + type = list(string) + default = [""] +} + +######### NAT/ IGW ############# +variable "create_nat" { + description = "Create a NAT Gateway" + type = bool + default = true +} +variable "create_igw" { + description = "Create an Internet Gateway" + type = bool + default = true +} +variable "tags" { + description = "tags for each resource" + type = map(string) + default = {} +} +variable "name" { + description = "universal name" + type = string + default = "" +} + + \ No newline at end of file diff --git a/VPC/Environment/test-v1/.gitignore b/VPC/Environment/test-v1/.gitignore new file mode 100644 index 0000000..7fd6910 --- /dev/null +++ b/VPC/Environment/test-v1/.gitignore @@ -0,0 +1,42 @@ +# Local .terraform directories +**/.terraform/* +.terraform/* +.terraform/ +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl + +# Ignore the .DS_Store files created by macOS +.DS_Store \ No newline at end of file diff --git a/VPC/Environment/test-v1/backend.tf b/VPC/Environment/test-v1/backend.tf new file mode 100644 index 0000000..78ec24f --- /dev/null +++ b/VPC/Environment/test-v1/backend.tf @@ -0,0 +1,9 @@ +terraform { + backend "s3" { + bucket = "terraform-state-bucket1237546" + key = "dev-vpc-module-by-terraform-state.tfstate" + region = "us-east-1" + use_lockfile = true + } +} +## \ No newline at end of file diff --git a/VPC/Environment/test-v1/main.tf b/VPC/Environment/test-v1/main.tf new file mode 100644 index 0000000..75de09d --- /dev/null +++ b/VPC/Environment/test-v1/main.tf @@ -0,0 +1,210 @@ +locals { + region = "us-east-1" + region_2 = "us-east-2" + envrionment = "Test" + Project = "Smooth" + global_name = "${var.name}-${local.Project}-${local.envrionment}" + tags = { + Envrionment = local.envrionment + Project = local.Project + } + +} +##################################################################### +# VPC +#################################################################### +module "vpc" { + source = "../../Modules/vpc" + name = local.global_name + + vpc_attributes = { + vpc = { + cidr_block = "10.0.0.0/16" + enable_dns_support = true + enable_dns_hostnames = true + region = local.region + } + vpc_2 = { + cidr_block = "10.10.0.0/16" + enable_dns_support = false + enable_dns_hostnames = false + region = local.region_2 + } + } + tags = local.tags +} + +#################################################################### +# Subnets +#################################################################### +module "subnets" { + source = "../../Modules/subnets" + name = local.global_name + public_subnets = { + pub_subnet_1 = { + vpc_id = module.vpc.vpc_id["vpc"] + cidr_block = ["10.0.0.0/24"] + availability_zone = ["us-east-1a"] + map_public_ip_on_launch = true + } + + pub_subnet_2 = { + vpc_id = module.vpc.vpc_id["vpc"] + cidr_block = ["10.0.1.0/24"] + availability_zone = ["us-east-1b"] + map_public_ip_on_launch = true + } + } + private_subnets = { + priv_subnet_1 = { + vpc_id = module.vpc.vpc_id["vpc"] + cidr_block = ["10.0.2.0/24"] + availability_zone = ["us-east-1a"] + map_public_ip_on_launch = false + } + priv_subnet_2 = { + vpc_id = module.vpc.vpc_id["vpc"] + cidr_block = ["10.0.3.0/24"] + availability_zone = ["us-east-1b"] + map_public_ip_on_launch = false + } + } +} +#################################################################### +# Route Tables +#################################################################### + +module "route-tables" { + source = "../../Modules/route-tables" + name = local.global_name + tags = local.tags + public_route_tables = { + public_rt1 = { + vpc_id = module.vpc.vpc_id["vpc"] + region = local.region + } + } + + public_routes = { + public_routes = { + type = "public" + route_table_id = module.route-tables.public_route_table_id["public_rt1"] + destination_cidr_block = "0.0.0.0/0" + gateway_id = module.igw-nat.igw_id["igw"] + } + } + public_route_table_associations = { + pub_rt1_subnet1 = { # unique key + route_table_id = module.route-tables.public_route_table_id["public_rt1"] + subnet_id = module.subnets.public_subnets["pub_subnet_1"] + } + pub_rt1_subnet2 = { + route_table_id = module.route-tables.public_route_table_id["public_rt1"] + subnet_id = module.subnets.public_subnets["pub_subnet_2"] + } + + } + # Accessing the first public subnet + + private_route_tables = { + private_rt1 = { + vpc_id = module.vpc.vpc_id["vpc"] + region = local.region + } + } + private_routes = { + private_route = { + type = "private" + route_table_id = module.route-tables.private_route_table_id["private_rt1"] # Syntax = module<[keyname]> + destination_cidr_block = "0.0.0.0/0" + nat_gateway_id = module.igw-nat.nat_id["main_nat"] + } + } + + private_route_table_associations = { + priv_rt1_subnet1 = { # unique key + route_table_id = module.route-tables.private_route_table_id["private_rt1"] + subnet_id = module.subnets.private_subnets["priv_subnet_1"] + } + priv_rt1_subnet2 = { + route_table_id = module.route-tables.private_route_table_id["private_rt1"] + subnet_id = module.subnets.private_subnets["priv_subnet_2"] + } + } +} + + + + +#################################################################### +# Internet Gateway and NAT Gateway +#################################################################### +module "igw-nat" { + source = "../../Modules/igw-nat" + eip = { + main_eip = { + region = local.region + tags = local.tags + } + } + + nat_gateway = { + main_nat = { + allocation_id = module.igw-nat.allocation_id["main_eip"] + subnet_id = module.subnets.public_subnets["pub_subnet_1"] # no need to add .id because it is already a string and established in the outputs + } + } + + internet_gateway = { + igw = { + vpc_id = module.vpc.vpc_id["vpc"] + tags = local.tags + } + } + name = local.global_name +} + + + + +#################################################################### +# Security Groups +#################################################################### +module "security-groups" { + source = "../../Modules/security-groups" + vpc_id = module.vpc.vpc_id["vpc"] + name = local.global_name + tags = local.tags + + security_group_description = "Security group for Smooth project" + + ingress_rules = [ + + { + type = "ingress" + from_port = 22 + to_port = 22 + protocol = "tcp" + description = "Allow SSH access" + cidr_blocks = ["0.0.0.0/0"] + }, + { + type = "ingress" + from_port = 80 + to_port = 80 + protocol = "tcp" + description = "Allow HTTP access" + cidr_blocks = ["0.0.0.0/0"] + }, + { + type = "ingress" + from_port = 443 + to_port = 443 + protocol = "tcp" + description = "Allow HTTPS access" + cidr_blocks = ["0.0.0.0/0"] + } + + ] + +} \ No newline at end of file diff --git a/VPC/Environment/test-v1/outputs.tf b/VPC/Environment/test-v1/outputs.tf new file mode 100644 index 0000000..e69de29 diff --git a/VPC/Environment/test-v1/providers.tf b/VPC/Environment/test-v1/providers.tf new file mode 100644 index 0000000..7eda631 --- /dev/null +++ b/VPC/Environment/test-v1/providers.tf @@ -0,0 +1,14 @@ +terraform { + required_version = ">= 1.0" + required_providers { + aws = { + source = "hashicorp/aws" + version = "6.0.0-beta2" + } + } + +} +provider "aws" { + region = local.region +} +## \ No newline at end of file diff --git a/VPC/Environment/test-v1/variables.tf b/VPC/Environment/test-v1/variables.tf new file mode 100644 index 0000000..99d22f9 --- /dev/null +++ b/VPC/Environment/test-v1/variables.tf @@ -0,0 +1,16 @@ + +########################################################## +# VPC +########################################################### +variable "name" { + description = "Global name for all resources" + type = string + default = "Tim" +} + +# variable "tags" { +# description = "Global tags to apply to all resources" +# type = map(string) +# default = {} +# } + diff --git a/VPC/Modules/.DS_Store b/VPC/Modules/.DS_Store new file mode 100644 index 0000000..3806447 Binary files /dev/null and b/VPC/Modules/.DS_Store differ diff --git a/VPC/Modules/Simple-VPC/.gitignore b/VPC/Modules/Simple-VPC/.gitignore new file mode 100644 index 0000000..11a858c --- /dev/null +++ b/VPC/Modules/Simple-VPC/.gitignore @@ -0,0 +1,45 @@ +# Local .terraform directories +**/.terraform/* +**/.terraform/ + + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl + +# Ignore the .DS_Store files created by macOS +.DS_Store +**/.DS_Store/ +../.DS_Store \ No newline at end of file diff --git a/VPC/Modules/Simple-VPC/igw-nat.tf b/VPC/Modules/Simple-VPC/igw-nat.tf new file mode 100644 index 0000000..b79fede --- /dev/null +++ b/VPC/Modules/Simple-VPC/igw-nat.tf @@ -0,0 +1,49 @@ + +############################################################## +# Module: igw-nat +################################################################ +## Create IGW and NAT Gateway if the VPC is created and the respective subnet CIDR blocks are provided + + +locals { + create_igw = var.create_vpc && length(var.public_subnets_cidr_blocks) > 0 + create_nat_gateway = var.create_vpc && length(var.private_subnets_cidr_blocks) > 0 + create_eip = var.create_vpc && length(var.private_subnets_cidr_blocks) > 0 +} + +resource "aws_eip" "this_eip" { + count = local.create_eip ? 1 : 0 + + tags = merge( + { + Name = "${var.name}-nat-eip" + }, + var.tags + ) +} + +resource "aws_internet_gateway" "this_igw" { + count = local.create_igw ? 1 : 0 + vpc_id = aws_vpc.this_vpc[0].id + + tags = merge( + { + Name = "${var.name}-igw" + }, + var.tags + ) + +} + +resource "aws_nat_gateway" "this_nat" { + count = local.create_nat_gateway ? 1:0 + allocation_id = aws_eip.this_eip[0].id + subnet_id = aws_subnet.public_subnets[0].id + + tags = merge( + { + Name = "${var.name}-nat-gateway" + }, + var.tags + ) +} \ No newline at end of file diff --git a/VPC/Modules/Simple-VPC/ouputs.tf b/VPC/Modules/Simple-VPC/ouputs.tf new file mode 100644 index 0000000..a3b1d91 --- /dev/null +++ b/VPC/Modules/Simple-VPC/ouputs.tf @@ -0,0 +1,40 @@ +output "vpc_id" { + description = "The ID of the VPC" + value = aws_vpc.this_vpc[0].id +} + +output "vpc_cidr" { + description = "VPC CIDR" + value = aws_vpc.this_vpc[0].cidr_block +} +output "igw_id" { + description = "The ID of the Internet Gateway" + value = aws_internet_gateway.this_igw[0].id +} + +output "igw_arn" { + description = "The ARN of the Internet Gateway" + value = aws_internet_gateway.this_igw[0].arn +} +output "public_subnets" { + description = "List of IDs of public subnets" + value = aws_subnet.public_subnets[*].id +} +output "public_subnet_arns" { + description = "List of ARNs of public subnets" + value = aws_subnet.public_subnets[*].arn +} +output "public_subnets_cidr_blocks" { + description = "List of cidr_blocks of public subnets" + value = compact(aws_subnet.public_subnets[*].cidr_block) +} + +output "private_subnets" { + description = "List of IDs of private subnets" + value = aws_subnet.private_subnets[*].id +} + +output "private_subnets_cidr_blocks" { + description = "List of cidr_blocks of private subnets" + value = compact(aws_subnet.private_subnets[*].cidr_block) +} \ No newline at end of file diff --git a/VPC/Modules/Simple-VPC/private-subnets.tf b/VPC/Modules/Simple-VPC/private-subnets.tf new file mode 100644 index 0000000..7a6b5ee --- /dev/null +++ b/VPC/Modules/Simple-VPC/private-subnets.tf @@ -0,0 +1,23 @@ +########################################################################## +# Private Subnets +########################################################################## + +### Create private subnets if the list of CIDR blocks is not empty +locals { + create_private_subnets = length(var.private_subnets_cidr_blocks) > 0 +} + +resource "aws_subnet" "private_subnets" { + count = var.create_vpc ? length(var.private_subnets_cidr_blocks): 0 + map_public_ip_on_launch = var.map_public_ip_on_private_subs + vpc_id = aws_vpc.this_vpc[0].id + cidr_block = var.private_subnets_cidr_blocks[count.index] + availability_zone = var.availability_zones[count.index % length(var.availability_zones)] + + tags = merge( + { + Name = "${var.name}-private-subnet-${count.index + 1}" + }, + var.tags + ) +} \ No newline at end of file diff --git a/VPC/Modules/Simple-VPC/provider..tf b/VPC/Modules/Simple-VPC/provider..tf new file mode 100644 index 0000000..ca3b037 --- /dev/null +++ b/VPC/Modules/Simple-VPC/provider..tf @@ -0,0 +1,13 @@ +terraform { + required_version = ">= 1.0" + required_providers { + aws = { + source = "hashicorp/aws" + version = "6.0.0-beta2" + } + } +} + +provider "aws" { + region = "us-east-1" +} \ No newline at end of file diff --git a/VPC/Modules/Simple-VPC/public-subnets.tf b/VPC/Modules/Simple-VPC/public-subnets.tf new file mode 100644 index 0000000..5709863 --- /dev/null +++ b/VPC/Modules/Simple-VPC/public-subnets.tf @@ -0,0 +1,25 @@ +########################################################################## +# Public Subnets +########################################################################## + +## Create public subnets if the list of CIDR blocks is not empty +locals { + create_public_subnets = length(var.public_subnets_cidr_blocks) > 0 +} + +resource "aws_subnet" "public_subnets" { + count = var.create_vpc ? length(var.public_subnets_cidr_blocks) : 0 + vpc_id = aws_vpc.this_vpc[0].id + cidr_block = var.public_subnets_cidr_blocks[count.index] + availability_zone = var.availability_zones[count.index % length(var.availability_zones)] + + map_public_ip_on_launch = var.map_public_ip_on_launch + + tags = merge( + { + Name = "${var.name}-public-subnet-${count.index + 1}" + }, + var.tags + ) + +} \ No newline at end of file diff --git a/VPC/Modules/Simple-VPC/route-tables.tf b/VPC/Modules/Simple-VPC/route-tables.tf new file mode 100644 index 0000000..547c64c --- /dev/null +++ b/VPC/Modules/Simple-VPC/route-tables.tf @@ -0,0 +1,82 @@ +######################################################################### +# Route Tables for VPC +######################################################################### +locals{ + create_public_route_table = var.create_vpc && length(var.public_subnets_cidr_blocks) > 0 + create_private_route_table = var.create_vpc && length(var.private_subnets_cidr_blocks) > 0 + create_route_to_igw = var.create_vpc && var.create_igw && local.create_public_route_table + create_route_to_nat = var.create_vpc && var.create_nat && local.create_private_route_table + +} +######################################################################### +# Public RT and Rules +######################################################################### +resource "aws_route_table" "public" { + count = local.create_public_route_table ? 1:0 + vpc_id = aws_vpc.this_vpc[0].id + + tags = merge( + { + Name = "${var.name}-public-route-table" + }, + var.tags + ) +} +resource "aws_route" "public_internet_gateway" { + count = local.create_route_to_igw ? 1:0 + + route_table_id = aws_route_table.public[count.index].id + destination_cidr_block = "0.0.0.0/0" + gateway_id = aws_internet_gateway.this_igw[0].id + + +} + +######################################################################### +# Public RT Association +######################################################################### +resource "aws_route_table_association" "public_association" { + count = local.create_public_subnets ? length(aws_subnet.public_subnets) : 0 + + subnet_id = element(aws_subnet.public_subnets[*].id, count.index) + route_table_id = aws_route_table.public[0].id + +} + + +######################################################################### +# Private RT and Rules +######################################################################### + +resource "aws_route_table" "private" { + count = local.create_private_route_table ? 1:0 + vpc_id = aws_vpc.this_vpc[0].id + + tags = merge( + { + Name = "${var.name}-private-route-table" + }, + var.tags + ) +} + + +resource "aws_route" "private_nat_gateway" { + count = local.create_private_route_table ? 1 : 0 + + route_table_id = aws_route_table.private[count.index].id + destination_cidr_block = "0.0.0.0/0" + nat_gateway_id = aws_nat_gateway.this_nat[0].id + +} + +######################################################################### +# Private RT Association +######################################################################### +resource "aws_route_table_association" "private_association" { + count = local.create_private_subnets ? length(aws_subnet.private_subnets) : 0 + + subnet_id = element(aws_subnet.private_subnets[*].id, count.index) + route_table_id = aws_route_table.private[0].id + +} \ No newline at end of file diff --git a/VPC/Modules/Simple-VPC/variables.tf b/VPC/Modules/Simple-VPC/variables.tf new file mode 100644 index 0000000..7d57e66 --- /dev/null +++ b/VPC/Modules/Simple-VPC/variables.tf @@ -0,0 +1,82 @@ +variable "create_vpc" { + description = "Create a new VPC" + type = bool + default = true + +} + +variable "vpc_cidr" { + description = "CIDR block for the VPC" + type = string + default = "" +} + +variable "enable_dns_hostnames" { + description = "Enable DNS hostnames in the VPC" + type = bool + default = true +} + +variable "enable_dns_support" { + description = "Enable DNS support in the VPC" + type = bool + default = true +} + +variable "public_subnets_cidr_blocks" { + description = "List of CIDR blocks for public subnets" + type = list(string) + default = [""] + +} + +variable "availability_zones" { + description = "List of availability zones for the VPC" + type = list(string) + default = [""] + +} + +variable "map_public_ip_on_launch" { + description = "Map public IP on launch for public subnets" + type = bool + default = true + +} + +variable "map_public_ip_on_private_subs" { + description = "Map public IP on launch for public subnets" + type = bool + default = false + +} + +######### private subnets ######### +variable "private_subnets_cidr_blocks" { + description = "List of private subnets CIDR blocks" + type = list(string) + default = [""] +} + +######### NAT/ IGW ############# +variable "create_nat" { + description = "Create a NAT Gateway" + type = bool + default = true +} +variable "create_igw" { + description = "Create an Internet Gateway" + type = bool + default = true +} +variable "tags"{ + description = "tags for each resource" + type = map(string) + default = {} + } + variable "name" { + description = "universal name" + type = string + default = "" + } + diff --git a/VPC/Modules/Simple-VPC/vpc-flowlogs.tf b/VPC/Modules/Simple-VPC/vpc-flowlogs.tf new file mode 100644 index 0000000..e69de29 diff --git a/VPC/Modules/Simple-VPC/vpc.tf b/VPC/Modules/Simple-VPC/vpc.tf new file mode 100644 index 0000000..055d26a --- /dev/null +++ b/VPC/Modules/Simple-VPC/vpc.tf @@ -0,0 +1,18 @@ +########################################################################## +# VPC Configuration +########################################################################## + + +resource "aws_vpc" "this_vpc" { + count = var.create_vpc ? 1: 0 + cidr_block = var.vpc_cidr + enable_dns_support = var.enable_dns_support + enable_dns_hostnames = var.enable_dns_hostnames + + tags = merge( + { + Name = "${var.name}-vpc" + }, + var.tags + ) +} \ No newline at end of file diff --git a/VPC/Modules/VPC/.gitignore b/VPC/Modules/VPC/.gitignore new file mode 100644 index 0000000..11a858c --- /dev/null +++ b/VPC/Modules/VPC/.gitignore @@ -0,0 +1,45 @@ +# Local .terraform directories +**/.terraform/* +**/.terraform/ + + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl + +# Ignore the .DS_Store files created by macOS +.DS_Store +**/.DS_Store/ +../.DS_Store \ No newline at end of file diff --git a/VPC/Modules/VPC/main.tf b/VPC/Modules/VPC/main.tf new file mode 100644 index 0000000..e89115a --- /dev/null +++ b/VPC/Modules/VPC/main.tf @@ -0,0 +1,22 @@ +########################################################################### +# VPC Configuration +########################################################################## + + + +resource "aws_vpc" "this_vpc" { + for_each = var.vpc_attributes + # provider = each.value.region == "us-east-1" ? aws.us-east : aws.us-west + cidr_block = each.value.cidr_block + enable_dns_support = each.value.enable_dns_support + enable_dns_hostnames = each.value.enable_dns_hostnames + region = each.value.region + + tags = merge( + { + Name = lookup(each.value, "name", "-${each.key}") + }, + var.tags + ) +} + diff --git a/VPC/Modules/VPC/outputs.tf b/VPC/Modules/VPC/outputs.tf new file mode 100644 index 0000000..a5a403a --- /dev/null +++ b/VPC/Modules/VPC/outputs.tf @@ -0,0 +1,34 @@ +### +output "vpc_id" { + description = "VPC ID" + value = {for k, v in aws_vpc.this_vpc : k => v.id} + +} + +output "vpc_cidr" { + description = "VPC CIDR" + value = {for k, v in aws_vpc.this_vpc : k => v.cidr_block} + +} + +# output "name" { +# description = "VPC ARN" +# value = var.name +# } + + + +# output "vpc_cidr" { +# description = "VPC CIDR" +# value = aws_vpc.this_vpc.cidr_block +# } + +# output "vpc_id" { +# description = "VPC ID" +# value = aws_vpc.this_vpc.id +# } + +# output "vpc_arn" { +# description = "VPC ARN" +# value = aws_vpc.this_vpc.arn +# } diff --git a/VPC/Modules/VPC/variables.tf b/VPC/Modules/VPC/variables.tf new file mode 100644 index 0000000..185f785 --- /dev/null +++ b/VPC/Modules/VPC/variables.tf @@ -0,0 +1,42 @@ + +# variable "name" { +# type = string +# } + + + +variable "tags" { + description = "Global tags to apply to all resources" + type = map(string) + default = {} +} + +variable "vpc_attributes" { + description = "Additional attributes for the VPC" + type = map(object({ + cidr_block = string + enable_dns_support = bool + enable_dns_hostnames = bool + region = string + name = string + })) + +} + +# variable "vpc_cidr" { +# description = "VPC CIDR" +# type = string +# default = "" +# } + +# variable "enable_dns_support" { +# description = "Enable DNS Support for VPC" +# type = bool +# default = true +# } + +# variable "enable_dns_hostnames" { +# description = "Enable Hostnames for VPC" +# type = bool +# default = true +# } \ No newline at end of file diff --git a/VPC/Modules/igw-nat/.gitignore b/VPC/Modules/igw-nat/.gitignore new file mode 100644 index 0000000..1e1ac26 --- /dev/null +++ b/VPC/Modules/igw-nat/.gitignore @@ -0,0 +1,41 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl + +# Ignore the .DS_Store files created by macOS +.DS_Store \ No newline at end of file diff --git a/VPC/Modules/igw-nat/main.tf b/VPC/Modules/igw-nat/main.tf new file mode 100644 index 0000000..4905e0d --- /dev/null +++ b/VPC/Modules/igw-nat/main.tf @@ -0,0 +1,110 @@ + +############################################################## +# Module: igw-nat +################################################################ +## Create IGW and NAT Gateway if the VPC is created and the respective subnet CIDR blocks are provided + + +################################################################### +# Elastic IP for NAT Gateways +##################################################################### +resource "aws_eip" "this_eip" { + for_each = var.eip + + tags = merge( + { + Name = "${var.name}-nat-eip" + }, + var.tags + ) +} + + +#################################################################### +# Internet Gateway +#################################################################### +resource "aws_internet_gateway" "this_igw" { + for_each = var.internet_gateway + vpc_id = each.value.vpc_id + tags = merge( + { + Name = "${var.name}-igw" + }, + var.tags + + ) +} + ############################################################# + # NAT Gateways + ############################################################# + +resource aws_nat_gateway "this_nat"{ + for_each = var.nat_gateway + allocation_id = each.value.allocation_id + subnet_id = each.value.subnet_id + tags = merge( + { + Name = "${var.name}-nat-gateway" + }, + var.tags + + ) +} + + + + + + + + + + + + + + + + +# locals { +# create_igw = length(var.public_subnets_cidr_blocks) > 0 +# create_nat_gateway = length(var.private_subnets_cidr_blocks) > 0 +# create_eip = length(var.private_subnets_cidr_blocks) > 0 +# } + +# resource "aws_eip" "this_eip" { +# count = local.create_eip ? 1 : 0 + +# tags = merge( +# { +# Name = "${var.name}-nat-eip" +# }, +# var.tags +# ) +# } + +# resource "aws_internet_gateway" "this_igw" { +# count = local.create_igw ? 1 : 0 +# vpc_id = var.vpc_id + +# tags = merge( +# { +# Name = "${var.name}-igw" +# }, +# var.tags +# ) + +# } + +# resource "aws_nat_gateway" "this_nat" { +# count = local.create_nat_gateway ? 1:0 +# allocation_id = aws_eip.this_eip[0].id +# subnet_id = var.public_subnets[0] # Assuming the first public subnet is used for the NAT Gateway + +# tags = merge( +# { +# Name = "${var.name}-nat-gateway" +# }, +# var.tags +# ) +# } \ No newline at end of file diff --git a/VPC/Modules/igw-nat/outputs.tf b/VPC/Modules/igw-nat/outputs.tf new file mode 100644 index 0000000..c975f44 --- /dev/null +++ b/VPC/Modules/igw-nat/outputs.tf @@ -0,0 +1,42 @@ +### + +output "igw_id" { + description = "The ID of the Internet Gateway" + value = {for k, v in aws_internet_gateway.this_igw : k => v.id} + +} + +output "nat_id" { + description = "The ID of the NAT Gateway" + value = {for k, v in aws_nat_gateway.this_nat : k => v.id} + +} + + + +output "allocation_id" { + description = "The ID of the EIP" + value = {for k, v in aws_eip.this_eip : k => v.id} +} + + + + + + + + + + + + + +# output "igw_id" { +# description = "The ID of the Internet Gateway" +# value = aws_internet_gateway.this_igw[0].id +# } + +# output "nat_id" { +# description = "The ID of the NAT Gateway" +# value = aws_nat_gateway.this_nat[0].id +# } \ No newline at end of file diff --git a/VPC/Modules/igw-nat/variables.tf b/VPC/Modules/igw-nat/variables.tf new file mode 100644 index 0000000..3da72d3 --- /dev/null +++ b/VPC/Modules/igw-nat/variables.tf @@ -0,0 +1,55 @@ +## +variable "tags" { + description = "Global tags to apply to all resources" + type = map(string) + default = {} +} + +variable "name" { + description = "Global name for all resources" + type = string + +} +variable "eip" { + description = "EIP for NAT Gateway" + type = map(object({ + region = optional(string) + tags = optional(map(string)) # Optional tags for the EIP + domain = optional(string) # Indicates if this EIP is for use in VPC (vpc) + instance_id = optional(string) # EC2 instance ID for EIP association + network_interface_id = optional(string) # Network interface ID for EIP association + + })) + +} + +variable "nat_gateway" { + description = "Map of NAT Gateway configurations" + type = map(object({ + allocation_id = string + subnet_id = string + tags = optional(map(string)) # Optional tags for the NAT Gateway + })) +} + +variable "internet_gateway" { + description = "Map of Internet Gateway configurations" + type = map(object({ + vpc_id = string + tags = optional(map(string)) # Optional tags for the Internet Gateway + + })) + +} + + + + + + + + + + + + diff --git a/VPC/Modules/route-tables/.gitignore b/VPC/Modules/route-tables/.gitignore new file mode 100644 index 0000000..1e1ac26 --- /dev/null +++ b/VPC/Modules/route-tables/.gitignore @@ -0,0 +1,41 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl + +# Ignore the .DS_Store files created by macOS +.DS_Store \ No newline at end of file diff --git a/VPC/Modules/route-tables/main.tf b/VPC/Modules/route-tables/main.tf new file mode 100644 index 0000000..56fca5d --- /dev/null +++ b/VPC/Modules/route-tables/main.tf @@ -0,0 +1,233 @@ +######################################################################### +# Route Tables for VPC +# ######################################################################### + +######################################################################### +# Public RT and Rules +########################################################################## + + + +resource "aws_route_table" "public" { + for_each = var.public_route_tables + vpc_id = each.value.vpc_id + region = each.value.region + tags = merge( + { + Name = "${var.name}-public-route-table" + }, + var.tags + ) +} + +resource aws_route "public_routes" { + for_each = var.public_routes + + route_table_id = each.value.route_table_id + destination_cidr_block = each.value.destination_cidr_block + gateway_id = lookup(each.value, "gateway_id", null) + nat_gateway_id = lookup(each.value, "nat_gateway_id", null) + vpc_peering_connection_id = lookup(each.value, "vpc_peering_connection_id", null) + transit_gateway_id = lookup(each.value, "transit_gateway_id", null) + + depends_on = [aws_route_table.public ] + +} + + +######################################################################### +# Public RT Association +######################################################################### + +resource "aws_route_table_association" "public_association" { + for_each = var.public_route_table_associations + subnet_id = each.value.subnet_id + route_table_id = each.value.route_table_id +} + +######################################################################### +# Private RT and Rules +######################################################################### + +resource "aws_route_table" "private" { + for_each = var.private_route_tables + vpc_id = each.value.vpc_id + region = each.value.region + tags = merge( + { + Name = "${var.name}-private-route-table" + }, + var.tags + ) +} +resource "aws_route" "private_routes" { + for_each = var.private_routes + route_table_id = each.value.route_table_id + destination_cidr_block = each.value.destination_cidr_block + gateway_id = lookup(each.value, "gateway_id", null) + nat_gateway_id = lookup(each.value, "nat_gateway_id", null) + vpc_peering_connection_id = lookup(each.value, "vpc_peering_connection_id", null) + transit_gateway_id = lookup(each.value, "transit_gateway_id", null) + + + + depends_on = [aws_route_table.private ] +} + +######################################################################### +# Private RT Association +######################################################################### + +resource "aws_route_table_association" "private_association" { + for_each = var.private_route_table_associations + subnet_id = each.value.subnet_id + route_table_id = each.value.route_table_id +} + + + + + + + + + + + + + + + + +########################################################################### +# Old Code for Public and Private Route Tables +########################################################################### + +# resource "aws_route_table_association" "private_association" { +# for_each = toset(var.private_route_table_associations) +# subnet_id = each.value +# route_table_id = aws_route_table.private[each.key] + +# depends_on = [aws_route_table.private ] +# } + + + +# resource "aws_route_table_association" "public_association" { +# for_each = toset(var.public_route_table_associations) +# subnet_id = each.value +# route_table_id = each.value.route_table_id + + +# depends_on = [aws_route_table.public ] +# } + + + + + + + +# locals{ +# create_public_route_table = length(var.public_subnets_cidr_blocks) > 0 +# create_private_route_table = length(var.private_subnets_cidr_blocks) > 0 +# create_route_to_igw = local.create_public_route_table +# create_route_to_nat = local.create_private_route_table + + + +# } + + +######################################################################### +# Old Code for Public and Private Route Tables +######################################################################### + +# resource "aws_route_table" "public" { +# count = local.create_public_route_table ? 1:0 +# vpc_id = var.vpc_id + +# tags = merge( +# { +# Name = "${var.name}-public-route-table" +# }, +# var.tags +# ) +# } + +# resource "aws_route" "public_internet_gateway" { +# count = local.create_route_to_igw ? 1:0 + +# route_table_id = aws_route_table.public[count.index].id +# destination_cidr_block = "0.0.0.0/0" +# gateway_id = var.igw_id + + +# } + + + + + + + + + + + + + + + + + + + + +# resource "aws_route_table" "private" { +# for_each = local.create_private_route_table ? toset(["private"]) : toset([]) + +# vpc_id = var.vpc_id + +# tags = merge( +# { +# Name = "${var.name}-private-route-table" +# }, +# var.tags +# ) +# } + + + +# resource "aws_route_table" "private" { +# count = local.create_private_route_table ? 1:0 +# vpc_id = var.vpc_id + +# tags = merge( +# { +# Name = "${var.name}-private-route-table" +# }, +# var.tags +# ) +# } + + +# resource "aws_route" "private_nat_gateway" { +# count = local.create_private_route_table ? 1 : 0 + +# route_table_id = aws_route_table.private[count.index].id +# destination_cidr_block = "0.0.0.0/0" +# nat_gateway_id = var.nat_id + +# } + +######################################################################### +# Private RT Association +######################################################################### +# resource "aws_route_table_association" "private_association" { +# count = var.create_private_subnets ? length(var.private_subnets) : 0 + +# subnet_id = var.private_subnets[count.index] +# route_table_id = aws_route_table.private[0].id + +# } \ No newline at end of file diff --git a/VPC/Modules/route-tables/outputs.tf b/VPC/Modules/route-tables/outputs.tf new file mode 100644 index 0000000..5fb7898 --- /dev/null +++ b/VPC/Modules/route-tables/outputs.tf @@ -0,0 +1,11 @@ +### + +output "public_route_table_id" { + description = "ID of the route table" + value = {for k, v in aws_route_table.public : k =>v.id} +} + +output "private_route_table_id" { + description = "ID of the route table" + value = {for k, v in aws_route_table.private : k => v.id} +} \ No newline at end of file diff --git a/VPC/Modules/route-tables/variables.tf b/VPC/Modules/route-tables/variables.tf new file mode 100644 index 0000000..793b1a9 --- /dev/null +++ b/VPC/Modules/route-tables/variables.tf @@ -0,0 +1,156 @@ +## +variable "tags" { + description = "Global tags to apply to all resources" + type = map(string) + default = {} +} + + +variable "name" { + description = "Global name for all resources" + type = string + default = "" +} + + +##################################### +# Public Route Tables +##################################### + +variable "public_route_tables" { + description = "Map of public route tables" + type = map(object({ + vpc_id = string + region = optional(string, null) # Optional region for the route table + + })) +} + + +##################################### +# Public Routes +##################################### +variable "public_routes" { + description = "Dynamically create routes for the route table" + type = map(object({ + type = optional(string, "public") # Default to public if not specified + route_table_id = string + destination_cidr_block = string + gateway_id = optional(string, null) + nat_gateway_id = optional(string, null) + vpc_peering_connection_id = optional(string, null) + transit_gateway_id = optional(string, null) + + })) +} + +##################################### +# Public Route Table Associations +##################################### +variable "public_route_table_associations" { + description = "Map of public route table associations" + type = map(object({ + route_table_id = string + subnet_id = string + })) +} + + + +##################################### +# Private Route Tables +##################################### + +variable "private_route_tables" { + description = "Map of private route tables" + type = map(object({ + vpc_id = string + region = optional(string, null) # Optional region for the route table + + })) + +} + +##################################### +# Private Route Table Associations +##################################### + +variable "private_route_table_associations" { + description = "Map of private route table associations" + type =map(object({ + route_table_id = string + subnet_id = string + })) +} + +##################################### +# Private Routes +##################################### +variable "private_routes" { + description = "Dynamically create routes for the route table" + type = map(object({ + type = optional(string, "public") # Default to public if not specified + route_table_id = optional(string, null) + destination_cidr_block = string + gateway_id = optional(string, null) + nat_gateway_id = optional(string, null) + vpc_peering_connection_id = optional(string, null) + transit_gateway_id = optional(string, null) + + })) +} + + +############################################## +# Old Variables for Public and Private Subnets +############################################## + +# variable "public_subnets" { +# description = "List of IDs of public subnets" +# type = list(string) +# } + +# variable "private_subnets" { +# description = "List of IDs of private subnets" +# type = list(string) + +# } +# variable "create_public_subnets" { +# description = "value of create_public_subnets local variable" +# type = string + +# } + +# variable "create_private_subnets" { +# description = "value of create_private_subnets local variable" +# type = string + +# } + + +# variable "vpc_id" { +# description = "VPC ID" +# type = string +# } + +# variable "igw_id" { +# description = "Internet Gateway ID" +# type = string +# } + +# variable "nat_id" { +# description = "NAT Gateway ID" +# type = string +# } +# variable "public_subnets_cidr_blocks" { +# description = "List of CIDR blocks for public subnets" +# type = list(string) +# default = [""] + +# } +# variable "private_subnets_cidr_blocks" { +# description = "List of CIDR blocks for private_ subnets" +# type = list(string) +# default = [""] + +# } \ No newline at end of file diff --git a/VPC/Modules/security-groups/.gitignore b/VPC/Modules/security-groups/.gitignore new file mode 100644 index 0000000..1e1ac26 --- /dev/null +++ b/VPC/Modules/security-groups/.gitignore @@ -0,0 +1,41 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl + +# Ignore the .DS_Store files created by macOS +.DS_Store \ No newline at end of file diff --git a/VPC/Modules/security-groups/README.MD b/VPC/Modules/security-groups/README.MD new file mode 100644 index 0000000..e69de29 diff --git a/VPC/Modules/security-groups/main.tf b/VPC/Modules/security-groups/main.tf new file mode 100644 index 0000000..8beca7c --- /dev/null +++ b/VPC/Modules/security-groups/main.tf @@ -0,0 +1,145 @@ +###################################################################### +### Security Group ### +####################################################################### + + +resource "aws_security_group" "this" { + for_each = var.security_groups + vpc_id = each.value.vpc_id + description = each.value.description +} + + + +resource "aws_security_group_rule" "this" { + for_each = var.ingress_rules + type = each.value.type + from_port = each.value.from_port + to_port = each.value.to_port + protocol = each.value.protocol + security_group_id = each.value.security_group_id + cidr_blocks = each.value.cidr_blocks + + +} + +resource "aws_vpc_security_group_egress_rule" "this" { + for_each = var.egress_rules + security_group_id = each.value.security_group_id + + cidr_ipv4 = "0.0.0.0/0" #tfsec:ignore:aws-vpc-no-public-egress-sgr + ip_protocol = "-1" + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# resource "aws_security_group" "this_sg" { +# vpc_id = var.vpc_id +# # provider = each.value.region == "us-east-1" ? aws.us-east : aws.us-west +# description = var.security_group_description +# tags = merge( +# { +# Name = "${var.name}-sg" +# }, +# var.tags +# ) +# } + + + + +# resource "aws_security_group_rule" "ingress" { + +# for_each = { +# for i, rule in var.ingress_rules : "rule-${i}" => rule +# } + +# type = "ingress" +# from_port = each.value.from_port +# to_port = each.value.to_port +# protocol = each.value.protocol +# description = each.value.description +# cidr_blocks = lookup(each.value, "cidr_blocks", []) +# security_group_id = aws_security_group.this_sg.id +# } + + + + + + + + + + + + + + + + + + + + + + + + +# resource "aws_security_group_rule" "ingress" { +# for_each = var.ingress_rules +# type = "ingress" +# from_port = each.value.from_port +# to_port = each.value.to_port +# protocol = each.value.protocol +# security_group_id = aws_security_group.this_sg.id +# cidr_blocks = [each.value.cidr_blocks] + +# description = each.value.description + +# depends_on = [ aws_security_group.this_sg ] +# } + diff --git a/VPC/Modules/security-groups/outputs.tf b/VPC/Modules/security-groups/outputs.tf new file mode 100644 index 0000000..57d54c1 --- /dev/null +++ b/VPC/Modules/security-groups/outputs.tf @@ -0,0 +1,4 @@ +output "security_group_ids" { + description = "List of all security group IDs" + value = {for k, v in aws_security_group.this : k => v.id} +} diff --git a/VPC/Modules/security-groups/variables.tf b/VPC/Modules/security-groups/variables.tf new file mode 100644 index 0000000..caf35f1 --- /dev/null +++ b/VPC/Modules/security-groups/variables.tf @@ -0,0 +1,112 @@ +variable "name" { + description = "Global name" + type = string + +} + +variable "tags" { + description = "Tags for the resources" + type = map(string) + default = {} + +} + + +variable "security_groups" { + description = "Map of secruity groups to create" + type = map(object({ + vpc_id = string + description = string + })) +} + +variable "ingress_rules" { + description = "Map of ingress rules" + type = map(object({ + description = optional(string) + type = string + from_port = number + protocol = string + to_port = number + cidr_blocks = list(string) + security_group_id = string + + })) +} + +variable "egress_rules" { + description = "Map of ingress rules" + type = map(object({ + security_group_id = string + + })) +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# variable "vpc_id" { +# description = "VPC ID" +# type = string + +# } + +# variable "security_group_description" { +# description = "description for the security group" +# type = string + +# } + + +# variable "ingress_rules" { +# description = "List of ingress rules" +# type = list(object({ + +# from_port = number +# to_port = number +# protocol = string +# description = string +# cidr_blocks = optional(list(string), []) +# })) +# } + + + + diff --git a/VPC/Modules/subnets/.gitignore b/VPC/Modules/subnets/.gitignore new file mode 100644 index 0000000..1e1ac26 --- /dev/null +++ b/VPC/Modules/subnets/.gitignore @@ -0,0 +1,41 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl + +# Ignore the .DS_Store files created by macOS +.DS_Store \ No newline at end of file diff --git a/VPC/Modules/subnets/outputs.tf b/VPC/Modules/subnets/outputs.tf new file mode 100644 index 0000000..0846d28 --- /dev/null +++ b/VPC/Modules/subnets/outputs.tf @@ -0,0 +1,31 @@ + +### +output "public_subnets_cidr_blocks" { + description = "values of public subnets CIDR blocks" + value = {for k, v in aws_subnet.public_subnets : k => v.cidr_block} +} + + +output "private_subnets_cidr_blocks" { + description = "values of private subnets CIDR blocks" + value = {for k, v in aws_subnet.private_subnets : k => v.cidr_block} +} + +output "public_subnets" { + description = "List of IDs of public subnets" + value = {for k, v in aws_subnet.public_subnets : k => v.id} +} + +output "private_subnets" { + description = "List of IDs of private subnets" + value = {for k, v in aws_subnet.private_subnets : k => v.id} +} +output "public_subnet_arns" { + description = "List of ARNs of public subnets" + value = {for k, v in aws_subnet.public_subnets : k => v.arn} +} + +output "private_subnets_arns" { + description = "List of ARNs of private subnets" + value = {for k, v in aws_subnet.private_subnets : k => v.arn} +} diff --git a/VPC/Modules/subnets/private.tf b/VPC/Modules/subnets/private.tf new file mode 100644 index 0000000..0ef82f7 --- /dev/null +++ b/VPC/Modules/subnets/private.tf @@ -0,0 +1,51 @@ +########################################################################## +# Private Subnets +########################################################################### + + + + +resource "aws_subnet" "private_subnets" { + for_each = var.private_subnets + # provider = each.value.region == "us-east-1" ? aws.us-east : aws.us-west + vpc_id = each.value.vpc_id + cidr_block = each.value.cidr_block[0] + availability_zone = each.value.availability_zone[0] + map_public_ip_on_launch = each.value.map_public_ip_on_launch + + tags = merge( + { + Name = "${var.name}-${each.key}" + }, + var.tags + ) + +} + + + + + + + + +### Create private subnets if the list of CIDR blocks is not empty +# locals { +# create_private_subnets = length(var.private_subnets_cidr_blocks) > 0 + +# } + +# resource "aws_subnet" "private_subnets" { +# count = var.create_private_subnets ? length(var.private_subnets_cidr_blocks) : 0 +# map_public_ip_on_launch = var.map_public_ip_on_private_subs +# vpc_id =var.vpc_id +# cidr_block = var.private_subnets_cidr_blocks[count.index] +# availability_zone = var.availability_zones[count.index % length(var.availability_zones)] + +# tags = merge( +# { +# Name = "${var.name}private-subnet-${count.index + 1}" +# }, +# var.tags +# ) +# } \ No newline at end of file diff --git a/VPC/Modules/subnets/public.tf b/VPC/Modules/subnets/public.tf new file mode 100644 index 0000000..c5976bc --- /dev/null +++ b/VPC/Modules/subnets/public.tf @@ -0,0 +1,44 @@ +########################################################################## +# Public Subnets +########################################################################### + +## Create public subnets if the list of CIDR blocks is not empty +# locals { +# create_public_subnets = length(var.public_subnets_cidr_blocks) > 0 +# } + + + +resource "aws_subnet" "public_subnets" { + for_each = var.public_subnets + # provider = each.value.region == "us-east-1" ? aws.us-east : aws.us-west + vpc_id = each.value.vpc_id + cidr_block = each.value.cidr_block[0] + availability_zone = each.value.availability_zone[0] + map_public_ip_on_launch = each.value.map_public_ip_on_launch + + tags = merge( + { + Name = "${var.name}-${each.key}" + }, + var.tags + ) +} + + +# resource "aws_subnet" "public_subnets" { +# count = var.create_pub_subs ? length(var.public_subnets_cidr_blocks) : 0 +# vpc_id = var.vpc_id +# cidr_block = var.public_subnets_cidr_blocks[count.index] +# availability_zone = var.availability_zones[count.index % length(var.availability_zones)] + +# map_public_ip_on_launch = var.map_public_ip_on_launch + +# tags = merge( +# { +# Name = "${var.name}public-subnet-${count.index + 1}" +# }, +# var.tags +# ) + +# } \ No newline at end of file diff --git a/VPC/Modules/subnets/variables.tf b/VPC/Modules/subnets/variables.tf new file mode 100644 index 0000000..28eca71 --- /dev/null +++ b/VPC/Modules/subnets/variables.tf @@ -0,0 +1,82 @@ + +## +variable "name" { + description = "Global name for all resources" + type = string + default = "" +} + + +variable "public_subnets" { + description = "Map of public subnets" + type = map(object({ + cidr_block = list(string) + availability_zone = list(string) + map_public_ip_on_launch = bool + vpc_id = string + })) +} + +variable "private_subnets" { + description = "Map of private subnets" + type = map(object({ + cidr_block = list(string) + availability_zone = list(string) + map_public_ip_on_launch = bool + vpc_id = string + })) +} +variable "tags" { + description = "Global tags to apply to all resources" + type = map(string) + default = {} +} + +# variable "vpc_id" { +# description = "VPC ID" +# type = string +# } +#variable "public_subnets_cidr_blocks" { +# description = "List of CIDR blocks for public subnets" +# type = list(string) +# default = [""] + +# } + +# variable "availability_zones" { +# description = "List of availability zones for the VPC" +# type = list(string) +# default = [""] + +# } + +# variable "map_public_ip_on_launch" { +# description = "Map public IP on launch for public subnets" +# type = bool +# default = true + +# } + +# variable "map_public_ip_on_private_subs" { +# description = "Map public IP on launch for public subnets" +# type = bool +# default = false + +# } + +######## private subnets ######### + + + +# variable "create_private_subnets" { +# description = "Bool to create private subnets" +# type = bool +# default = true +# } + +# variable "private_subnets_cidr_blocks" { +# description = "List of private subnets CIDR blocks" +# type = list(string) +# default = [""] +# } + diff --git a/VPC/Modules/vpc-flowlogs/.gitignore b/VPC/Modules/vpc-flowlogs/.gitignore new file mode 100644 index 0000000..1e1ac26 --- /dev/null +++ b/VPC/Modules/vpc-flowlogs/.gitignore @@ -0,0 +1,41 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl + +# Ignore the .DS_Store files created by macOS +.DS_Store \ No newline at end of file diff --git a/VPC/Modules/vpc-flowlogs/main.tf b/VPC/Modules/vpc-flowlogs/main.tf new file mode 100644 index 0000000..e69de29 diff --git a/VPC/Modules/vpc-flowlogs/outputs.tf b/VPC/Modules/vpc-flowlogs/outputs.tf new file mode 100644 index 0000000..e69de29 diff --git a/VPC/Modules/vpc-flowlogs/variables.tf b/VPC/Modules/vpc-flowlogs/variables.tf new file mode 100644 index 0000000..e69de29 diff --git a/VPC/README.MD b/VPC/README.MD new file mode 100644 index 0000000..48ff1b2 --- /dev/null +++ b/VPC/README.MD @@ -0,0 +1,42 @@ +# 🧱 AWS VPC Terraform Module + +This is a reusable and extensible **Terraform module** for provisioning a secure and scalable **AWS Virtual Private Cloud (VPC)**. It acts as the **foundation** for the AWS side of the [Multi-Cloud-Networking-Module](https://github.com/YOUR_USERNAME/Multi-Cloud-Networking-Module), serving as a core dependency for peering, VPN, and transit gateway modules. + +--- + +## 🎯 Purpose + +This module was designed to: + +- Standardize AWS VPC creation across environments +- Serve as the **base layer** for multi-cloud connectivity +- Incorporate **intermediate to advanced Terraform patterns** to enable flexibility, composability, and modular reuse +- Continuously evolve as new networking patterns emerge + +--- + +## ⚙️ Features + +- VPC creation with configurable CIDR block +- Public, private, and database subnets with NAT gateway support +- Route table management and IGW/NAT configuration +- Optional VPC endpoints and DNS support +- Flexible subnet grouping via dynamic blocks +- Use of **locals**, **count**, **conditional logic**, and **dynamic blocks** + +--- + +## 🧠 Terraform Concepts Used + +This module demonstrates intermediate to advanced usage of: + +- `count` and `for_each` for resource control +- `locals` for centralized logic and derived values +- `dynamic` blocks for on-demand subnet generation +- Conditional logic inside locals for flexible configurations +- Parameterized design for reuse across environments (`dev`, `test`, `prod`) + +--- + + + diff --git a/Vnet-Peering/.DS_Store b/Vnet-Peering/.DS_Store new file mode 100644 index 0000000..2d43a31 Binary files /dev/null and b/Vnet-Peering/.DS_Store differ diff --git a/Vnet-Peering/.gitignore b/Vnet-Peering/.gitignore new file mode 100644 index 0000000..1e1ac26 --- /dev/null +++ b/Vnet-Peering/.gitignore @@ -0,0 +1,41 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl + +# Ignore the .DS_Store files created by macOS +.DS_Store \ No newline at end of file diff --git a/Vnet-Peering/Environments/dev/.gitignore b/Vnet-Peering/Environments/dev/.gitignore new file mode 100644 index 0000000..1e1ac26 --- /dev/null +++ b/Vnet-Peering/Environments/dev/.gitignore @@ -0,0 +1,41 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl + +# Ignore the .DS_Store files created by macOS +.DS_Store \ No newline at end of file diff --git a/Vnet-Peering/Environments/prod/.gitignore b/Vnet-Peering/Environments/prod/.gitignore new file mode 100644 index 0000000..1e1ac26 --- /dev/null +++ b/Vnet-Peering/Environments/prod/.gitignore @@ -0,0 +1,41 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl + +# Ignore the .DS_Store files created by macOS +.DS_Store \ No newline at end of file diff --git a/Vnet-Peering/Environments/test/.gitignore b/Vnet-Peering/Environments/test/.gitignore new file mode 100644 index 0000000..1e1ac26 --- /dev/null +++ b/Vnet-Peering/Environments/test/.gitignore @@ -0,0 +1,41 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl + +# Ignore the .DS_Store files created by macOS +.DS_Store \ No newline at end of file diff --git a/Vnet-Peering/Environments/test/backend.tf b/Vnet-Peering/Environments/test/backend.tf new file mode 100644 index 0000000..b91ceea --- /dev/null +++ b/Vnet-Peering/Environments/test/backend.tf @@ -0,0 +1,9 @@ +terraform { + backend "azurerm" { + resource_group_name = "tf_state" + storage_account_name = "tfstatefile84" + container_name = "testtfstate" + key = "vnet-peering.terraform.tfstate" + # subscription_id = "" + } +} \ No newline at end of file diff --git a/Vnet-Peering/Environments/test/main.tf b/Vnet-Peering/Environments/test/main.tf new file mode 100644 index 0000000..d8e28cb --- /dev/null +++ b/Vnet-Peering/Environments/test/main.tf @@ -0,0 +1,192 @@ + + +locals { + environment = "test-v1" + vnet_name = "vnet-${local.environment}" + location = "eastus" + second_location = "westus" + name = "smooth" + global_name = "${local.name}-${local.environment}" + tags = { + environment = local.environment + name = local.name + } + vnet_address_space = ["10.0.0.0/16"] + vnet2_address_space = ["10.10.0.0/16"] +} + +##################################################################### +# Resource Group Module +####################################################################### +module "resource_group" { + source = "../../../VNET/modules/resource-group" + + resource_groups = { + requester_rg = { + name = "requester_rg" + location = local.location + } + accepter_rg = { + name = "accepter_rg" + location = local.location + } + } + tags = local.tags +} + + +################################################################################ +# Virtul Network Module +################################################################################ + +module "virtual_network" { + source = "../../../VNET/modules/virtual-network" + + virtual_network = { + requester_vnet = { + name = "requester_vnet" + address_space = local.vnet_address_space + location = local.location + resource_group_name = module.resource_group.resource_group_name["requester_rg"] + } + + accepter_vnet = { + name = "accepter_vnet" + address_space = local.vnet2_address_space + location = local.location + resource_group_name = module.resource_group.resource_group_name["accepter_rg"] + } + + } + tags = local.tags +} + +################################################################################ +# Subnet Module +################################################################################ + +module "subnets" { + source = "../../../VNET/modules/subnet" + + subnets = { + requester_pub_sub1 = { + name = "requester_pub_sub1" + address_prefixes = ["10.0.0.0/24"] + virtual_network_name = module.virtual_network.virutal_network_name["requester_vnet"] + resource_group_name = module.resource_group.resource_group_name["requester_rg"] + } + requester_pub_sub2 = { + name = "requester_pub_sub2" + address_prefixes = ["10.0.1.0/24"] + virtual_network_name = module.virtual_network.virutal_network_name["requester_vnet"] + resource_group_name = module.resource_group.resource_group_name["requester_rg"] + } + accepter_pub_sub1 = { + name = "accepter_pub_sub1" + address_prefixes = ["10.10.0.0/24"] + virtual_network_name = module.virtual_network.virutal_network_name["accepter_vnet"] + resource_group_name = module.resource_group.resource_group_name["accepter_rg"] + } + accepter_pub_sub2 = { + name = "accepter_pub_sub2" + address_prefixes = ["10.10.1.0/24"] + virtual_network_name = module.virtual_network.virutal_network_name["accepter_vnet"] + resource_group_name = module.resource_group.resource_group_name["accepter_rg"] + } + } + +} +######################################################################################## +# Linux VM +######################################################################################## + +module "linux_vm" { + source = "../../../virtual-machines/Azure/Linux-VM" + + network_interface = { + nic1 = { + name = "linux-nic1" + location = local.location + resource_group_name = module.resource_group.resource_group_name["requester_rg"] + ip_configuration = { + name = "internal" + subnet_id = module.subnets.subnet_id["requester_pub_sub1"] + private_ip_address_allocation = "Dynamic" + } + } + nic2 = { + name = "linux-nic2" + location = local.location + resource_group_name = module.resource_group.resource_group_name["accepter_rg"] + ip_configuration = { + name = "internal" + subnet_id = module.subnets.subnet_id["accepter_pub_sub1"] + private_ip_address_allocation = "Dynamic" + } + } + } + linux_vm = { + Vm1 = { + name = "Linux-VM1" + resource_group_name = module.resource_group.resource_group_name["requester_rg"] + location = local.location + size = "Standard_F2" + admin_username = "adminuser" + network_interface_ids = [module.linux_vm.network_interface_ids["nic1"]] + + os_disk = { + caching = "ReadWrite" + storage_account_type = "Standard_LRS" + + } + + } + + Vm2 = { + name = "Linux-VM2" + resource_group_name = module.resource_group.resource_group_name["accepter_rg"] + location = local.location + size = "Standard_F2" + admin_username = "adminuser" + network_interface_ids = [module.linux_vm.network_interface_ids["nic2"]] + + os_disk = { + caching = "ReadWrite" + storage_account_type = "Standard_LRS" + + } + + + } + + } +} + +############################################################################################################## +# Virtual Network Peering +############################################################################################################## + +module "peerings" { + source = "../../../Vnet-Peering/modules/peering-connection" + + virtual_network_peering = { + request_accepter = { + name = "requester-accepter" + resource_group_name = module.resource_group.resource_group_name["requester_rg"] + virtual_network_name = module.virtual_network.virutal_network_name["requester_vnet"] + remote_virtual_network_id = module.virtual_network.virutal_network_id["accepter_vnet"] + allow_virtual_network_access = true + allow_forwarded_traffic = true + } + accepter_requester = { + name = "requester-accepter" + resource_group_name = module.resource_group.resource_group_name["accepter_rg"] + virtual_network_name = module.virtual_network.virutal_network_name["accepter_vnet"] + remote_virtual_network_id = module.virtual_network.virutal_network_id["requester_vnet"] + allow_virtual_network_access = true + allow_forwarded_traffic = true + } + } + +} + diff --git a/Vnet-Peering/Environments/test/providers.tf b/Vnet-Peering/Environments/test/providers.tf new file mode 100644 index 0000000..da30c99 --- /dev/null +++ b/Vnet-Peering/Environments/test/providers.tf @@ -0,0 +1,22 @@ +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "4.34.0" + } + } +} +# Configure the Microsoft Azure Provider +provider "azurerm" { + subscription_id = "" + features { + resource_group { + prevent_deletion_if_contains_resources = false + } + key_vault { + purge_soft_delete_on_destroy = true + recover_soft_deleted_key_vaults = true + } + + } +} diff --git a/Vnet-Peering/Environments/test/variables.tf b/Vnet-Peering/Environments/test/variables.tf new file mode 100644 index 0000000..e69de29 diff --git a/Vnet-Peering/modules/.gitignore b/Vnet-Peering/modules/.gitignore new file mode 100644 index 0000000..1e1ac26 --- /dev/null +++ b/Vnet-Peering/modules/.gitignore @@ -0,0 +1,41 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl + +# Ignore the .DS_Store files created by macOS +.DS_Store \ No newline at end of file diff --git a/Vnet-Peering/modules/peering-connection/.gitignore b/Vnet-Peering/modules/peering-connection/.gitignore new file mode 100644 index 0000000..1e1ac26 --- /dev/null +++ b/Vnet-Peering/modules/peering-connection/.gitignore @@ -0,0 +1,41 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc +.terraform.lock.hcl + +# Ignore the .DS_Store files created by macOS +.DS_Store \ No newline at end of file diff --git a/Vnet-Peering/modules/peering-connection/main.tf b/Vnet-Peering/modules/peering-connection/main.tf new file mode 100644 index 0000000..8da6724 --- /dev/null +++ b/Vnet-Peering/modules/peering-connection/main.tf @@ -0,0 +1,13 @@ +############################################################################################################## +# Virtual Network Peering +############################################################################################################## + + + +resource "azurerm_virtual_network_peering" "this" { + for_each = var.virtual_network_peering + name = each.value.name + resource_group_name = each.value.resource_group_name + virtual_network_name = each.value.virtual_network_name + remote_virtual_network_id = each.value.remote_virtual_network_id +} \ No newline at end of file diff --git a/Vnet-Peering/modules/peering-connection/outputs.tf b/Vnet-Peering/modules/peering-connection/outputs.tf new file mode 100644 index 0000000..e69de29 diff --git a/Vnet-Peering/modules/peering-connection/variables.tf b/Vnet-Peering/modules/peering-connection/variables.tf new file mode 100644 index 0000000..544f7c4 --- /dev/null +++ b/Vnet-Peering/modules/peering-connection/variables.tf @@ -0,0 +1,17 @@ +############################################################################################################## +# Virtual Network Peering Variables +############################################################################################################## + + +variable "virtual_network_peering" { + description = "Map of virtual network peerings" + type = map(object({ + name = string + resource_group_name = string + virtual_network_name = string + remote_virtual_network_id = string + allow_virtual_network_access = optional(bool) + allow_forwarded_traffic = optional(bool) + + })) +} \ No newline at end of file diff --git a/virtual-machines/.DS_Store b/virtual-machines/.DS_Store new file mode 100644 index 0000000..5aec9bf Binary files /dev/null and b/virtual-machines/.DS_Store differ diff --git a/virtual-machines/AWS/EC2/main.tf b/virtual-machines/AWS/EC2/main.tf new file mode 100644 index 0000000..40423d8 --- /dev/null +++ b/virtual-machines/AWS/EC2/main.tf @@ -0,0 +1,22 @@ +######################################################################## +# EC2 Instance +######################################################################## + +resource "aws_instance" "this" { + for_each = var.instance_attributes + ami = "ami-000ec6c25978d5999" + instance_type = each.value.instance_type + iam_instance_profile = each.value.iam_instance_profile + subnet_id = each.value.subnet_id ## Ensure this is the private subnet, for SSM access + vpc_security_group_ids = each.value.vpc_security_group_ids + metadata_options { + http_tokens = "required" + } + root_block_device { + encrypted = true + } + tags = { + Name = "${var.name}-instance" + } + +} \ No newline at end of file diff --git a/virtual-machines/AWS/EC2/outputs.tf b/virtual-machines/AWS/EC2/outputs.tf new file mode 100644 index 0000000..e69de29 diff --git a/virtual-machines/AWS/EC2/variables.tf b/virtual-machines/AWS/EC2/variables.tf new file mode 100644 index 0000000..92fdd4c --- /dev/null +++ b/virtual-machines/AWS/EC2/variables.tf @@ -0,0 +1,22 @@ +######################################################################## +# EC2 Variables +######################################################################## + +variable "instance_attributes" { + description = "Map of instances to create" + type = map(object({ + instance_type = string # t2.micro + iam_instance_profile = optional(string) + subnet_id = string + vpc_security_group_ids = optional(list(string)) + + })) +} + +variable "tags" { + description = "tags to apply" + type = map(string) +} +variable "name" { + +} \ No newline at end of file diff --git a/virtual-machines/Azure/Linux-VM/.gitignore b/virtual-machines/Azure/Linux-VM/.gitignore new file mode 100644 index 0000000..1c99dc1 --- /dev/null +++ b/virtual-machines/Azure/Linux-VM/.gitignore @@ -0,0 +1 @@ +.terraform/ diff --git a/virtual-machines/Azure/Linux-VM/main.tf b/virtual-machines/Azure/Linux-VM/main.tf new file mode 100644 index 0000000..81e5b6b --- /dev/null +++ b/virtual-machines/Azure/Linux-VM/main.tf @@ -0,0 +1,40 @@ +######################################################################################## +# Linux VM +######################################################################################## + +resource "azurerm_network_interface" "this"{ + for_each = var. network_interface + name = each.value.name + location = each.value.location + resource_group_name = each.value.resource_group_name + ip_configuration { + name = each.value.ip_configuration.name + subnet_id = each.value.ip_configuration.subnet_id + private_ip_address_allocation = each.value.ip_configuration.private_ip_address_allocation + } +} + +resource "azurerm_linux_virtual_machine" "this" { + for_each = var.linux_vm + name = each.value.name + resource_group_name = each.value.resource_group_name + location = each.value.location + size = each.value.size + admin_username = "adminuser" + network_interface_ids = each.value.network_interface_ids + + os_disk { + caching = each.value.os_disk.caching + storage_account_type = each.value.os_disk.storage_account_type + } + source_image_reference { + publisher = "Canonical" + offer = "0001-com-ubuntu-server-jammy" + sku = "22_04-lts" + version = "latest" + } + admin_ssh_key { + username = "adminuser" + public_key = file("~/.ssh/id_rsa.pub") + } +} \ No newline at end of file diff --git a/virtual-machines/Azure/Linux-VM/outputs.tf b/virtual-machines/Azure/Linux-VM/outputs.tf new file mode 100644 index 0000000..4230412 --- /dev/null +++ b/virtual-machines/Azure/Linux-VM/outputs.tf @@ -0,0 +1,9 @@ +output "network_interface_ids" { + description = "map of network interface IDs" + value = {for k, v in azurerm_network_interface.this : k => v.id } +} + +output "azurerm_linux_virtual_machine" { + description = " Map of linux VM Ids" + value = {for k,v in azurerm_linux_virtual_machine.this : k => v.id} +} \ No newline at end of file diff --git a/virtual-machines/Azure/Linux-VM/variables.tf b/virtual-machines/Azure/Linux-VM/variables.tf new file mode 100644 index 0000000..08108a3 --- /dev/null +++ b/virtual-machines/Azure/Linux-VM/variables.tf @@ -0,0 +1,59 @@ +######################################################################################## +# Linux VM +######################################################################################## + +variable "network_interface" { + description = "Map of azure Network Interfaces" + type = map(object({ + name = string + location = string + resource_group_name = string + ip_configuration = object({ + name = string + subnet_id = string + private_ip_address_allocation = string # "Dynamic", "Static" + }) + })) + + +} + + +variable "linux_vm" { + description = "Map of linux Virtual Machines" + type = map(object({ + name = string + resource_group_name = string + location = string + size = string + admin_username = string + network_interface_ids = list(string) + # admin_ssh_key = object({ + # name = string + # }) + os_disk = object({ + caching = optional(string) + storage_account_type = optional(string) # LRS, ZRS + }) + # source_image_reference = object({ + # publisher = optional(string) + # offer = optional(string) + # sku = optional(string) + # version = optional(string) + # }) + })) +# default = { +# source_image_reference = { +# publisher = "Canonical" +# offer = "0001-com-ubuntu-server-jammy" +# sku = "22_04-lts" +# version = "latest" +# } +# os_disk = { +# caching = "ReadWrite" +# storage_account_type = "Standard_LRS" + +# } + +# } +}