commit 4f8fdb6112ed786615bf0ad1fd4fefee4ae1acca Author: xpk Date: Thu Oct 24 23:12:35 2024 +0800 HistoryPurge: Clearing 17 old commits diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1f9ab44 --- /dev/null +++ b/.gitignore @@ -0,0 +1,38 @@ +### IntelliJ IDEA ### +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store + +### Terraform ### +.terraform +*.tfstate +*.tfstate.backup +*.tfstate.*.* +.idea +.terraform.lock.hcl +terraform-training.iml diff --git a/Modules/Compute/ec2/main.tf b/Modules/Compute/ec2/main.tf new file mode 100644 index 0000000..5300b32 --- /dev/null +++ b/Modules/Compute/ec2/main.tf @@ -0,0 +1,26 @@ +resource "aws_instance" "example" { + ami = "ami-0157c3cc39a1c5cc0" + instance_type = "t4g.large" + subnet_id = "subnet-0927ba1b06ccfe6c5" + key_name = aws_key_pair.this.key_name + + # IMDSv2 requirement + dynamic "metadata_options" { + for_each = var.disable_secure_idmsv2 == false ? { set_idmsv2 : true } : {} + content { + http_endpoint = "enabled" + http_tokens = "required" + http_put_response_hop_limit = 2 + } + } + tags = { Name : var.name } +} + +resource "tls_private_key" "this" { + algorithm = "ED25519" +} + +resource "aws_key_pair" "this" { + key_name = "${var.name}-sshkey" + public_key = tls_private_key.this.public_key_openssh +} \ No newline at end of file diff --git a/Modules/Compute/ec2/provider.tf b/Modules/Compute/ec2/provider.tf new file mode 100644 index 0000000..fa025da --- /dev/null +++ b/Modules/Compute/ec2/provider.tf @@ -0,0 +1,28 @@ +provider "aws" { + region = "ap-east-1" + + default_tags { + tags = { + ServiceProvider = "RackspaceTechnology" + Environment = "Training" + Project = "Iac" + TerraformMode = "managed" + Owner = "ken2026" + TerraformDir = "${reverse(split("/", path.cwd))[1]}/${reverse(split("/", path.cwd))[0]}" + } + } +} + +output "last-updated" { + value = timestamp() +} + +terraform { + required_version = ">= 1.3.0" + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.0" + } + } +} \ No newline at end of file diff --git a/Modules/Compute/ec2/variables.tf b/Modules/Compute/ec2/variables.tf new file mode 100644 index 0000000..899f93c --- /dev/null +++ b/Modules/Compute/ec2/variables.tf @@ -0,0 +1,10 @@ +variable "name" { + type = string + description = "Name of Ec2 instance" +} + +variable "disable_secure_idmsv2" { + type = bool + default = false + description = "Allow use of insecure idmsv1. Default is false." +} \ No newline at end of file diff --git a/Modules/Compute/security_group/README.md b/Modules/Compute/security_group/README.md new file mode 100644 index 0000000..442140c --- /dev/null +++ b/Modules/Compute/security_group/README.md @@ -0,0 +1,44 @@ +# security-group +This module create security group. + +## Inputs + +| Name | Description | Type | Default | Required | +|---------|-------------------|----------|---------|:--------:| +| vpc-id | VPC id | string | n/a | yes | +| ingress | See example below | map | n/a | yes | +| egress | See example below | map | n/a | yes | + +## Outputs + +| Name | Description | +|------------|--------------------------------| +| sg-id-name | A map of SG id and their names | + +### Example +Below is a sample root module calling this shared module + +```hcl +module "admin-sg" { + + source = "../../modules/compute/security_group" + + description = "Security group for admins" + egress = { + r1 = "tcp,4750,4750,1.2.3.4/32,Patch Management Tool" + r2 = "tcp,22,22,1.2.3.4/32,Patch Management Tool" + r3 = "tcp,52311,52311,${aws_ec2_managed_prefix_list.bigfix.id},Client to BigFix server" + r4 = "-1,-1,-1,0.0.0.0/0,Outbound access" + } + ingress = { + r1 = "tcp,4750,4750,1.2.3.4/32,Patch Management Tool" + r2 = "tcp,22,22,1.2.3.4/32,Patch Management Tool" + r3 = "tcp,52311,52311,${aws_ec2_managed_prefix_list.bigfix.id},BigFix server to client" + } + name = "admin-sg" + vpc-id = "vpc-01a10b033169f89a8" +} +``` + + + diff --git a/Modules/Compute/security_group/main.tf b/Modules/Compute/security_group/main.tf new file mode 100644 index 0000000..6fb358e --- /dev/null +++ b/Modules/Compute/security_group/main.tf @@ -0,0 +1,39 @@ +data "aws_default_tags" "this" { + lifecycle { + postcondition { + condition = length(self.tags) >= 1 + error_message = "Validation failed: Provider default_tags not set." + } + } +} + +resource "aws_security_group" "sg" { + name = var.name + description = var.description + vpc_id = var.vpc-id + tags = { Name = var.name } +} + +resource "aws_vpc_security_group_ingress_rule" "ingress-rules" { + for_each = var.ingress + security_group_id = aws_security_group.sg.id + ip_protocol = split(",", each.value)[0] + from_port = split(",", each.value)[1] + to_port = split(",", each.value)[2] + cidr_ipv4 = substr(split(",", each.value)[3], 2, 1) != "-" ? split(",", each.value)[3] : null + referenced_security_group_id = substr(split(",", each.value)[3], 0, 2) == "sg" ? split(",", each.value)[3] : null + prefix_list_id = substr(split(",", each.value)[3], 0, 2) == "pl" ? split(",", each.value)[3] : null + description = split(",", each.value)[4] +} + +resource "aws_vpc_security_group_egress_rule" "egress-rules" { + for_each = var.egress + security_group_id = aws_security_group.sg.id + ip_protocol = split(",", each.value)[0] + from_port = split(",", each.value)[1] + to_port = split(",", each.value)[2] + cidr_ipv4 = substr(split(",", each.value)[3], 2, 1) != "-" ? split(",", each.value)[3] : null + referenced_security_group_id = substr(split(",", each.value)[3], 0, 2) == "sg" ? split(",", each.value)[3] : null + prefix_list_id = substr(split(",", each.value)[3], 0, 2) == "pl" ? split(",", each.value)[3] : null + description = split(",", each.value)[4] +} diff --git a/Modules/Compute/security_group/outputs.tf b/Modules/Compute/security_group/outputs.tf new file mode 100644 index 0000000..5a963bf --- /dev/null +++ b/Modules/Compute/security_group/outputs.tf @@ -0,0 +1,3 @@ +output id { + value = aws_security_group.sg.id +} \ No newline at end of file diff --git a/Modules/Compute/security_group/variables.tf b/Modules/Compute/security_group/variables.tf new file mode 100644 index 0000000..4fb72d0 --- /dev/null +++ b/Modules/Compute/security_group/variables.tf @@ -0,0 +1,5 @@ +variable name {} +variable description {} +variable vpc-id {} +variable ingress {} +variable egress {} \ No newline at end of file diff --git a/NetworkContentDelivery/Exercise3/README.md b/NetworkContentDelivery/Exercise3/README.md new file mode 100644 index 0000000..3e429ee --- /dev/null +++ b/NetworkContentDelivery/Exercise3/README.md @@ -0,0 +1,54 @@ + +## Requirements + +| Name | Version | +|------|---------| +| terraform | >= 1.3.0 | +| aws | >= 5.0 | +| http | >= 3.4.2 | + +## Providers + +| Name | Version | +|------|---------| +| aws | 5.51.1 | +| http | 3.4.2 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| CloudflareSg | ../../Modules/Compute/security_group | n/a | +| Vpc | terraform-aws-modules/vpc/aws | 5.8.1 | +| VpcEndpoints | terraform-aws-modules/vpc/aws//modules/vpc-endpoints | 5.8.1 | + +## Resources + +| Name | Type | +|------|------| +| [aws_ec2_managed_prefix_list.pl1](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_managed_prefix_list) | resource | +| [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source | +| [aws_iam_policy_document.dynamodb_endpoint_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.s3_endpoint_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [http_http.CloudflareIps](https://registry.terraform.io/providers/hashicorp/http/latest/docs/data-sources/http) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| VpcCidr | VPC CIDR | `string` | n/a | yes | +| VpcName | Name of VPC | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| CloudflareSg | Cloudflare security group id | +| PrivateSubnetCidrs | Private subnet CIDRs | +| VpcCidr | Vpc CIDR | +| VpcId | Vpc ID | +| last-updated | n/a | + +--- +## Authorship +This module was developed by xpk. \ No newline at end of file diff --git a/NetworkContentDelivery/Exercise3/main.tf b/NetworkContentDelivery/Exercise3/main.tf new file mode 100644 index 0000000..4921d48 --- /dev/null +++ b/NetworkContentDelivery/Exercise3/main.tf @@ -0,0 +1,123 @@ +data "aws_availability_zones" "available" {} + +locals { + PrivataSubnets = cidrsubnets(var.VpcCidr, 8, 8) +} + +module "Vpc" { + source = "terraform-aws-modules/vpc/aws" + version = "5.8.1" + + name = var.VpcName + cidr = var.VpcCidr + azs = slice(data.aws_availability_zones.available.names, 0, 2) + + private_subnets = local.PrivataSubnets + private_subnet_names = [for k, v in local.PrivataSubnets : "${var.VpcName}Private${k}"] + enable_dns_hostnames = true + enable_dns_support = true + enable_nat_gateway = false + enable_dhcp_options = true + dhcp_options_domain_name = "${var.VpcName}.aws" +} + +module "VpcEndpoints" { + source = "terraform-aws-modules/vpc/aws//modules/vpc-endpoints" + version = "5.8.1" + + vpc_id = module.Vpc.vpc_id + create_security_group = false + endpoints = { + s3 = { + service = "s3" + service_type = "Gateway" + route_table_ids = flatten([ + module.Vpc.intra_route_table_ids, module.Vpc.private_route_table_ids, module.Vpc.public_route_table_ids + ]) + policy = data.aws_iam_policy_document.s3_endpoint_policy.json + tags = { Name = "S3VpcEp" } + }, + dynamodb = { + service = "dynamodb" + service_type = "Gateway" + route_table_ids = flatten([ + module.Vpc.intra_route_table_ids, module.Vpc.private_route_table_ids, module.Vpc.public_route_table_ids + ]) + policy = data.aws_iam_policy_document.dynamodb_endpoint_policy.json + tags = { Name = "DynamodbVpcEp" } + } + } +} + +data "aws_iam_policy_document" "s3_endpoint_policy" { + statement { + effect = "Deny" + actions = ["s3:*"] + resources = ["*"] + + principals { + type = "*" + identifiers = ["*"] + } + + condition { + test = "StringNotEquals" + variable = "aws:sourceVpc" + + values = [module.Vpc.vpc_id] + } + } +} + +data "aws_iam_policy_document" "dynamodb_endpoint_policy" { + statement { + effect = "Deny" + actions = ["dynamodb:*"] + resources = ["*"] + + principals { + type = "*" + identifiers = ["*"] + } + + condition { + test = "StringNotEquals" + variable = "aws:sourceVpc" + + values = [module.Vpc.vpc_id] + } + } +} + + +data "http" "CloudflareIps" { + url = "https://api.cloudflare.com/client/v4/ips" + request_headers = { + Accept = "application/json" + } +} + +resource "aws_ec2_managed_prefix_list" "pl1" { + name = "CloudflareIpRanges" + address_family = "IPv4" + max_entries = 20 + dynamic "entry" { + for_each = jsondecode(data.http.CloudflareIps.response_body)["result"]["ipv4_cidrs"] + content { + cidr = entry.value + description = "Cloudflare IP" + } + } +} + +module "CloudflareSg" { + source = "../../Modules/Compute/security_group" + description = "Cloudflare Ip Ranges" + egress = { + } + ingress = { + r1 = "tcp,443,443,${aws_ec2_managed_prefix_list.pl1.id},Cloudflare Prefix List" + } + name = "cloudflare-ips" + vpc-id = module.Vpc.vpc_id +} \ No newline at end of file diff --git a/NetworkContentDelivery/Exercise3/outputs.tf b/NetworkContentDelivery/Exercise3/outputs.tf new file mode 100644 index 0000000..be0091e --- /dev/null +++ b/NetworkContentDelivery/Exercise3/outputs.tf @@ -0,0 +1,19 @@ +output "VpcId" { + value = module.Vpc.vpc_id + description = "Vpc ID" +} + +output "VpcCidr" { + value = module.Vpc.vpc_cidr_block + description = "Vpc CIDR" +} + +output "PrivateSubnetCidrs" { + value = module.Vpc.private_subnets_cidr_blocks + description = "Private subnet CIDRs" +} + +output "CloudflareSg" { + value = module.CloudflareSg.id + description = "Cloudflare security group id" +} \ No newline at end of file diff --git a/NetworkContentDelivery/Exercise3/provider.tf b/NetworkContentDelivery/Exercise3/provider.tf new file mode 100644 index 0000000..642f342 --- /dev/null +++ b/NetworkContentDelivery/Exercise3/provider.tf @@ -0,0 +1,31 @@ +provider "aws" { + region = "us-east-1" + + default_tags { + tags = { + ServiceProvider = "RackspaceTechnology" + Environment = "Training" + Project = "Iac" + TerraformMode = "managed" + TerraformDir = "${reverse(split("/", path.cwd))[1]}/${reverse(split("/", path.cwd))[0]}" + } + } +} + +output "last-updated" { + value = timestamp() +} + +terraform { + required_version = ">= 1.3.0" + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.0" + } + http = { + source = "hashicorp/http" + version = ">= 3.4.2" + } + } +} \ No newline at end of file diff --git a/NetworkContentDelivery/Exercise3/terraform.tfvars b/NetworkContentDelivery/Exercise3/terraform.tfvars new file mode 100644 index 0000000..6cdffea --- /dev/null +++ b/NetworkContentDelivery/Exercise3/terraform.tfvars @@ -0,0 +1,2 @@ +VpcName = "TrainingVpc" +VpcCidr = "192.168.0.0/16" \ No newline at end of file diff --git a/NetworkContentDelivery/Exercise3/variables.tf b/NetworkContentDelivery/Exercise3/variables.tf new file mode 100644 index 0000000..a0afeb5 --- /dev/null +++ b/NetworkContentDelivery/Exercise3/variables.tf @@ -0,0 +1,9 @@ +variable "VpcName" { + type = string + description = "Name of VPC" +} + +variable "VpcCidr" { + type = string + description = "VPC CIDR" +} \ No newline at end of file diff --git a/SecurityIdentityCompliance/Exercise1/README.md b/SecurityIdentityCompliance/Exercise1/README.md new file mode 100644 index 0000000..0ad9714 --- /dev/null +++ b/SecurityIdentityCompliance/Exercise1/README.md @@ -0,0 +1,40 @@ + +## Requirements + +| Name | Version | +|------|---------| +| terraform | >= 1.3.0 | +| aws | >= 5.0 | + +## Providers + +| Name | Version | +|------|---------| +| aws | 5.51.1 | +| random | 3.6.2 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [aws_iam_group.Group1](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_group) | resource | +| [random_pet.this](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) | resource | + +## Inputs + +No inputs. + +## Outputs + +| Name | Description | +|------|-------------| +| GroupName | Name of IAM group | +| last-updated | n/a | + +--- +## Authorship +This module was developed by xpk. \ No newline at end of file diff --git a/SecurityIdentityCompliance/Exercise1/main.tf b/SecurityIdentityCompliance/Exercise1/main.tf new file mode 100644 index 0000000..15eaf14 --- /dev/null +++ b/SecurityIdentityCompliance/Exercise1/main.tf @@ -0,0 +1,6 @@ +resource "aws_iam_group" "Group1" { + name = "Team-${random_pet.this.id}" + path = "/users/" +} + +resource "random_pet" "this" {} \ No newline at end of file diff --git a/SecurityIdentityCompliance/Exercise1/outputs.tf b/SecurityIdentityCompliance/Exercise1/outputs.tf new file mode 100644 index 0000000..c2042e9 --- /dev/null +++ b/SecurityIdentityCompliance/Exercise1/outputs.tf @@ -0,0 +1,4 @@ +output "GroupName" { + value = aws_iam_group.Group1.name + description = "Name of IAM group" +} \ No newline at end of file diff --git a/SecurityIdentityCompliance/Exercise1/provider.tf b/SecurityIdentityCompliance/Exercise1/provider.tf new file mode 100644 index 0000000..aa5c309 --- /dev/null +++ b/SecurityIdentityCompliance/Exercise1/provider.tf @@ -0,0 +1,27 @@ +provider "aws" { + region = "us-east-1" + + default_tags { + tags = { + ServiceProvider = "RackspaceTechnology" + Environment = "Training" + Project = "Iac" + TerraformMode = "managed" + TerraformDir = "${reverse(split("/", path.cwd))[1]}/${reverse(split("/", path.cwd))[0]}" + } + } +} + +output "last-updated" { + value = timestamp() +} + +terraform { + required_version = ">= 1.3.0" + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.0" + } + } +} \ No newline at end of file diff --git a/SecurityIdentityCompliance/Exercise1/terraform.tfvars b/SecurityIdentityCompliance/Exercise1/terraform.tfvars new file mode 100644 index 0000000..e69de29 diff --git a/SecurityIdentityCompliance/Exercise1/variables.tf b/SecurityIdentityCompliance/Exercise1/variables.tf new file mode 100644 index 0000000..e69de29 diff --git a/SecurityIdentityCompliance/Exercise2/README.md b/SecurityIdentityCompliance/Exercise2/README.md new file mode 100644 index 0000000..ae79607 --- /dev/null +++ b/SecurityIdentityCompliance/Exercise2/README.md @@ -0,0 +1,40 @@ + +## Requirements + +| Name | Version | +|------|---------| +| terraform | >= 1.3.0 | +| aws | >= 5.0 | + +## Providers + +| Name | Version | +|------|---------| +| random | 3.6.2 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| iam | terraform-aws-modules/iam/aws//modules/iam-group-with-policies | 5.39.1 | + +## Resources + +| Name | Type | +|------|------| +| [random_pet.this](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) | resource | + +## Inputs + +No inputs. + +## Outputs + +| Name | Description | +|------|-------------| +| GroupName | Name of IAM group | +| last-updated | n/a | + +--- +## Authorship +This module was developed by xpk. \ No newline at end of file diff --git a/SecurityIdentityCompliance/Exercise2/main.tf b/SecurityIdentityCompliance/Exercise2/main.tf new file mode 100644 index 0000000..2f4c196 --- /dev/null +++ b/SecurityIdentityCompliance/Exercise2/main.tf @@ -0,0 +1,12 @@ +module "iam" { + source = "terraform-aws-modules/iam/aws//modules/iam-group-with-policies" + version = "5.39.1" + + name = "Team-${random_pet.this.id}" + create_group = true + custom_group_policy_arns = [ + "arn:aws:iam::aws:policy/job-function/ViewOnlyAccess" + ] +} + +resource "random_pet" "this" {} \ No newline at end of file diff --git a/SecurityIdentityCompliance/Exercise2/outputs.tf b/SecurityIdentityCompliance/Exercise2/outputs.tf new file mode 100644 index 0000000..7a28d68 --- /dev/null +++ b/SecurityIdentityCompliance/Exercise2/outputs.tf @@ -0,0 +1,4 @@ +output "GroupName" { + value = module.iam.group_name + description = "Name of IAM group" +} \ No newline at end of file diff --git a/SecurityIdentityCompliance/Exercise2/provider.tf b/SecurityIdentityCompliance/Exercise2/provider.tf new file mode 100644 index 0000000..aa5c309 --- /dev/null +++ b/SecurityIdentityCompliance/Exercise2/provider.tf @@ -0,0 +1,27 @@ +provider "aws" { + region = "us-east-1" + + default_tags { + tags = { + ServiceProvider = "RackspaceTechnology" + Environment = "Training" + Project = "Iac" + TerraformMode = "managed" + TerraformDir = "${reverse(split("/", path.cwd))[1]}/${reverse(split("/", path.cwd))[0]}" + } + } +} + +output "last-updated" { + value = timestamp() +} + +terraform { + required_version = ">= 1.3.0" + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.0" + } + } +} \ No newline at end of file diff --git a/SecurityIdentityCompliance/Exercise2/terraform.tfvars b/SecurityIdentityCompliance/Exercise2/terraform.tfvars new file mode 100644 index 0000000..e69de29 diff --git a/SecurityIdentityCompliance/Exercise2/variables.tf b/SecurityIdentityCompliance/Exercise2/variables.tf new file mode 100644 index 0000000..e69de29