After making all the Terraform code changes, I executed terraform init and terraform plan successfully. However, when I executed terraform apply, I encountered an AccessDenied error as follows. I have double checked the variables and it does not look like I misconfigured anything that could have caused this error. Please help!
voclabs:~/environment/terraform $ terraform apply
module.bastion_host.random_id.master_password: Refreshing state... [id=Q1A4sh3Su_U]
module.bastion_host.tls_private_key.bastion_host_key_pair: Refreshing state... [id=73eb84fb9df3b70a1a1cffabb8c8403c58a6fbe5]
module.bastion_host.data.aws_subnet.private_subnet_b: Reading...
module.bastion_host.data.aws_subnet.public_subnet_a: Reading...
module.bastion_host.aws_key_pair.bastion_host_key_pair: Refreshing state... [id=de-c2w3lab1-bastion-host-key]
module.bastion_host.data.aws_ami.latest_amazon_linux: Reading...
module.bastion_host.data.aws_vpc.main: Reading...
module.bastion_host.data.aws_subnet.public_subnet_b: Reading...
module.bastion_host.data.aws_subnet.private_subnet_a: Reading...
module.bastion_host.local_file.ssh_key: Refreshing state... [id=dc79a57e48da9dd7617975be3a5759ca3003fe49]
module.bastion_host.data.aws_subnet.public_subnet_b: Read complete after 1s [id=subnet-0b922a4edf087c733]
module.bastion_host.data.aws_subnet.public_subnet_a: Read complete after 1s [id=subnet-01fbfe9699b17e4d8]
module.bastion_host.data.aws_subnet.private_subnet_a: Read complete after 1s [id=subnet-01fbfe9699b17e4d8]
module.bastion_host.data.aws_subnet.private_subnet_b: Read complete after 1s [id=subnet-0b922a4edf087c733]
module.bastion_host.aws_db_subnet_group.database: Refreshing state... [id=de-c2w3lab1-db-subnet-group]
module.bastion_host.data.aws_vpc.main: Read complete after 1s [id=vpc-0302b23301bb1111e]
module.bastion_host.aws_security_group.bastion_host: Refreshing state... [id=sg-04f558ccfdd1c6aff]
module.bastion_host.data.aws_ami.latest_amazon_linux: Read complete after 1s [id=ami-06b21ccaeff8cd686]
module.bastion_host.aws_security_group.database: Refreshing state... [id=sg-063a3da2885fde848]
module.bastion_host.aws_instance.bastion_host: Refreshing state... [id=i-07713b5b3a4045602]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# module.bastion_host.aws_db_instance.database will be created
+ resource "aws_db_instance" "database" {
+ address = (known after apply)
+ allocated_storage = 20
+ apply_immediately = false
+ arn = (known after apply)
+ auto_minor_version_upgrade = true
+ availability_zone = (known after apply)
+ backup_retention_period = (known after apply)
+ backup_target = (known after apply)
+ backup_window = (known after apply)
+ ca_cert_identifier = (known after apply)
+ character_set_name = (known after apply)
+ copy_tags_to_snapshot = false
+ db_name = "postgres"
+ db_subnet_group_name = "de-c2w3lab1-db-subnet-group"
+ delete_automated_backups = true
+ domain_fqdn = (known after apply)
+ endpoint = (known after apply)
+ engine = "postgres"
+ engine_version = "15"
+ engine_version_actual = (known after apply)
+ hosted_zone_id = (known after apply)
+ id = (known after apply)
+ identifier = "de-c2w3lab1-db"
+ identifier_prefix = (known after apply)
+ instance_class = "'db.t3.micro"
+ iops = (known after apply)
+ kms_key_id = (known after apply)
+ latest_restorable_time = (known after apply)
+ license_model = (known after apply)
+ listener_endpoint = (known after apply)
+ maintenance_window = (known after apply)
+ master_user_secret = (known after apply)
+ master_user_secret_kms_key_id = (known after apply)
+ monitoring_interval = 0
+ monitoring_role_arn = (known after apply)
+ multi_az = (known after apply)
+ nchar_character_set_name = (known after apply)
+ network_type = (known after apply)
+ option_group_name = (known after apply)
+ parameter_group_name = (known after apply)
+ password = (sensitive value)
+ performance_insights_enabled = false
+ performance_insights_kms_key_id = (known after apply)
+ performance_insights_retention_period = (known after apply)
+ port = 5432
+ publicly_accessible = false
+ replica_mode = (known after apply)
+ replicas = (known after apply)
+ resource_id = (known after apply)
+ skip_final_snapshot = true
+ snapshot_identifier = (known after apply)
+ status = (known after apply)
+ storage_throughput = (known after apply)
+ storage_type = "gp2"
+ tags_all = {
+ "comments" = "this resource is managed by terraform"
+ "project" = "de-c2w3lab1"
+ "terraform" = "true"
}
+ timezone = (known after apply)
+ username = "postgres_admin"
+ vpc_security_group_ids = [
+ "sg-063a3da2885fde848",
]
}
Plan: 1 to add, 0 to change, 0 to destroy.
Changes to Outputs:
+ db_host = (known after apply)
+ db_master_password = (sensitive value)
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
module.bastion_host.aws_db_instance.database: Creating...
╷
│ Error: creating RDS DB Instance (de-c2w3lab1-db): AccessDenied: User: arn:aws:sts::008207703421:assumed-role/voclabs/user3569082=Sheng-Loong_Su is not authorized to perform: rds:CreateDBInstance on resource: arn:aws:rds:us-east-1:008207703421:db:de-c2w3lab1-db because no identity-based policy allows the rds:CreateDBInstance action
│ status code: 403, request id: 2eea7912-d958-4af0-83a3-a4c7e8a2b970
│
│ with module.bastion_host.aws_db_instance.database,
│ on modules/bastion_host/rds.tf line 14, in resource "aws_db_instance" "database":
│ 14: resource "aws_db_instance" "database" {
│
╵
Hello @codessl
The output you see after running terraform apply is different from what I see. There should be more resources that are supposed to be deployed afterwards:
Here is the complete log:
Terraform will perform the following actions:
# module.bastion_host.aws_db_instance.database will be created
+ resource "aws_db_instance" "database" {
+ address = (known after apply)
+ allocated_storage = 20
+ apply_immediately = false
+ arn = (known after apply)
+ auto_minor_version_upgrade = true
+ availability_zone = (known after apply)
+ backup_retention_period = (known after apply)
+ backup_target = (known after apply)
+ backup_window = (known after apply)
+ ca_cert_identifier = (known after apply)
+ character_set_name = (known after apply)
+ copy_tags_to_snapshot = false
+ db_name = "postgres"
+ db_subnet_group_name = "de-c2w3lab1-db-subnet-group"
+ delete_automated_backups = true
+ domain_fqdn = (known after apply)
+ endpoint = (known after apply)
+ engine = "postgres"
+ engine_version = "15"
+ engine_version_actual = (known after apply)
+ hosted_zone_id = (known after apply)
+ id = (known after apply)
+ identifier = "de-c2w3lab1-db"
+ identifier_prefix = (known after apply)
+ instance_class = "db.t3.micro"
+ iops = (known after apply)
+ kms_key_id = (known after apply)
+ latest_restorable_time = (known after apply)
+ license_model = (known after apply)
+ listener_endpoint = (known after apply)
+ maintenance_window = (known after apply)
+ master_user_secret = (known after apply)
+ master_user_secret_kms_key_id = (known after apply)
+ monitoring_interval = 0
+ monitoring_role_arn = (known after apply)
+ multi_az = (known after apply)
+ nchar_character_set_name = (known after apply)
+ network_type = (known after apply)
+ option_group_name = (known after apply)
+ parameter_group_name = (known after apply)
+ password = (sensitive value)
+ performance_insights_enabled = false
+ performance_insights_kms_key_id = (known after apply)
+ performance_insights_retention_period = (known after apply)
+ port = 5432
+ publicly_accessible = false
+ replica_mode = (known after apply)
+ replicas = (known after apply)
+ resource_id = (known after apply)
+ skip_final_snapshot = true
+ snapshot_identifier = (known after apply)
+ status = (known after apply)
+ storage_throughput = (known after apply)
+ storage_type = "gp2"
+ tags_all = {
+ "comments" = "this resource is managed by terraform"
+ "project" = "de-c2w3lab1"
+ "terraform" = "true"
}
+ timezone = (known after apply)
+ username = "postgres_admin"
+ vpc_security_group_ids = (known after apply)
}
# module.bastion_host.aws_db_subnet_group.database will be created
+ resource "aws_db_subnet_group" "database" {
+ arn = (known after apply)
+ description = "Managed by Terraform"
+ id = (known after apply)
+ name = "de-c2w3lab1-db-subnet-group"
+ name_prefix = (known after apply)
+ subnet_ids = [
+ "subnet-0b0666f2b33b695b6",
+ "subnet-0c73a1b5abaed001d",
]
+ supported_network_types = (known after apply)
+ tags_all = {
+ "comments" = "this resource is managed by terraform"
+ "project" = "de-c2w3lab1"
+ "terraform" = "true"
}
+ vpc_id = (known after apply)
}
# module.bastion_host.aws_instance.bastion_host will be created
+ resource "aws_instance" "bastion_host" {
+ ami = "ami-06b21ccaeff8cd686"
+ arn = (known after apply)
+ associate_public_ip_address = true
+ availability_zone = (known after apply)
+ cpu_core_count = (known after apply)
+ cpu_threads_per_core = (known after apply)
+ disable_api_stop = (known after apply)
+ disable_api_termination = (known after apply)
+ ebs_optimized = (known after apply)
+ get_password_data = false
+ host_id = (known after apply)
+ host_resource_group_arn = (known after apply)
+ iam_instance_profile = (known after apply)
+ id = (known after apply)
+ instance_initiated_shutdown_behavior = (known after apply)
+ instance_lifecycle = (known after apply)
+ instance_state = (known after apply)
+ instance_type = "t3.nano"
+ ipv6_address_count = (known after apply)
+ ipv6_addresses = (known after apply)
+ key_name = "de-c2w3lab1-bastion-host-key"
+ monitoring = (known after apply)
+ outpost_arn = (known after apply)
+ password_data = (known after apply)
+ placement_group = (known after apply)
+ placement_partition_number = (known after apply)
+ primary_network_interface_id = (known after apply)
+ private_dns = (known after apply)
+ private_ip = (known after apply)
+ public_dns = (known after apply)
+ public_ip = (known after apply)
+ secondary_private_ips = (known after apply)
+ security_groups = (known after apply)
+ source_dest_check = true
+ spot_instance_request_id = (known after apply)
+ subnet_id = "subnet-0b0666f2b33b695b6"
+ tags = {
+ "Name" = "de-c2w3lab1-bastion-host"
}
+ tags_all = {
+ "Name" = "de-c2w3lab1-bastion-host"
+ "comments" = "this resource is managed by terraform"
+ "project" = "de-c2w3lab1"
+ "terraform" = "true"
}
+ tenancy = (known after apply)
+ user_data = "6fdbebd37f6e25f0b0d058a4f038cf0d947ee16a"
+ user_data_base64 = (known after apply)
+ user_data_replace_on_change = true
+ vpc_security_group_ids = (known after apply)
+ capacity_reservation_specification (known after apply)
+ cpu_options (known after apply)
+ ebs_block_device (known after apply)
+ enclave_options (known after apply)
+ ephemeral_block_device (known after apply)
+ instance_market_options (known after apply)
+ maintenance_options (known after apply)
+ metadata_options (known after apply)
+ network_interface (known after apply)
+ private_dns_name_options (known after apply)
+ root_block_device (known after apply)
}
# module.bastion_host.aws_key_pair.bastion_host_key_pair will be created
+ resource "aws_key_pair" "bastion_host_key_pair" {
+ arn = (known after apply)
+ fingerprint = (known after apply)
+ id = (known after apply)
+ key_name = "de-c2w3lab1-bastion-host-key"
+ key_name_prefix = (known after apply)
+ key_pair_id = (known after apply)
+ key_type = (known after apply)
+ public_key = (known after apply)
+ tags_all = {
+ "comments" = "this resource is managed by terraform"
+ "project" = "de-c2w3lab1"
+ "terraform" = "true"
}
}
# module.bastion_host.aws_security_group.bastion_host will be created
+ resource "aws_security_group" "bastion_host" {
+ arn = (known after apply)
+ description = "Managed by Terraform"
+ egress = [
+ {
+ cidr_blocks = [
+ "0.0.0.0/0",
]
+ description = "Allow all outgoing traffic"
+ from_port = 0
+ ipv6_cidr_blocks = []
+ prefix_list_ids = []
+ protocol = "-1"
+ security_groups = []
+ self = false
+ to_port = 0
},
]
+ id = (known after apply)
+ ingress = [
+ {
+ cidr_blocks = [
+ "0.0.0.0/0",
]
+ description = "Allow incoming SSH connections (Linux)"
+ from_port = 22
+ ipv6_cidr_blocks = []
+ prefix_list_ids = []
+ protocol = "tcp"
+ security_groups = []
+ self = false
+ to_port = 22
},
]
+ name = "de-c2w3lab1-bastion-host-sg"
+ name_prefix = (known after apply)
+ owner_id = (known after apply)
+ revoke_rules_on_delete = false
+ tags = {
+ "Name" = "de-c2w3lab1-bastion-host-sg"
}
+ tags_all = {
+ "Name" = "de-c2w3lab1-bastion-host-sg"
+ "comments" = "this resource is managed by terraform"
+ "project" = "de-c2w3lab1"
+ "terraform" = "true"
}
+ vpc_id = "vpc-0bbe594143fcea7ee"
}
# module.bastion_host.aws_security_group.database will be created
+ resource "aws_security_group" "database" {
+ arn = (known after apply)
+ description = "Managed by Terraform"
+ egress = [
+ {
+ cidr_blocks = [
+ "0.0.0.0/0",
]
+ description = "Allow all outgoing traffic"
+ from_port = 0
+ ipv6_cidr_blocks = []
+ prefix_list_ids = []
+ protocol = "-1"
+ security_groups = []
+ self = false
+ to_port = 0
},
]
+ id = (known after apply)
+ ingress = [
+ {
+ cidr_blocks = []
+ description = "Allow incoming connections from the bastion host sg"
+ from_port = 5432
+ ipv6_cidr_blocks = []
+ prefix_list_ids = []
+ protocol = "tcp"
+ security_groups = (known after apply)
+ self = false
+ to_port = 5432
},
]
+ name = "de-c2w3lab1-database-sg"
+ name_prefix = (known after apply)
+ owner_id = (known after apply)
+ revoke_rules_on_delete = false
+ tags = {
+ "Name" = "de-c2w3lab1-database-sg"
}
+ tags_all = {
+ "Name" = "de-c2w3lab1-database-sg"
+ "comments" = "this resource is managed by terraform"
+ "project" = "de-c2w3lab1"
+ "terraform" = "true"
}
+ vpc_id = "vpc-0bbe594143fcea7ee"
}
# module.bastion_host.local_file.ssh_key will be created
+ resource "local_file" "ssh_key" {
+ content = (sensitive value)
+ content_base64sha256 = (known after apply)
+ content_base64sha512 = (known after apply)
+ content_md5 = (known after apply)
+ content_sha1 = (known after apply)
+ content_sha256 = (known after apply)
+ content_sha512 = (known after apply)
+ directory_permission = "0777"
+ file_permission = "0400"
+ filename = "de-c2w3lab1-bastion-host-key.pem"
+ id = (known after apply)
}
# module.bastion_host.random_id.master_password will be created
+ resource "random_id" "master_password" {
+ b64_std = (known after apply)
+ b64_url = (known after apply)
+ byte_length = 8
+ dec = (known after apply)
+ hex = (known after apply)
+ id = (known after apply)
}
# module.bastion_host.tls_private_key.bastion_host_key_pair will be created
+ resource "tls_private_key" "bastion_host_key_pair" {
+ algorithm = "RSA"
+ ecdsa_curve = "P224"
+ id = (known after apply)
+ private_key_openssh = (sensitive value)
+ private_key_pem = (sensitive value)
+ private_key_pem_pkcs8 = (sensitive value)
+ public_key_fingerprint_md5 = (known after apply)
+ public_key_fingerprint_sha256 = (known after apply)
+ public_key_openssh = (known after apply)
+ public_key_pem = (known after apply)
+ rsa_bits = 4096
}
Plan: 9 to add, 0 to change, 0 to destroy.
Changes to Outputs:
+ bastion_host_dns = (known after apply)
+ db_host = (known after apply)
+ db_master_password = (sensitive value)
+ db_master_username = "postgres_admin"
+ db_port = 5432
+ project = "de-c2w3lab1"
I guess there is something wrong with the files in your terraform/modules/bastion_host folder. The solution files for this lab are provided to you, and I suggest you double check your files with the ones in the solution folder.
Also, please make sure to fill in the gaps in the terraform.tfvars file from the CloudFormation outputs correctly.
If you run the apply from a clean state, the terraform plan will say that it will be adding 9 resources. But after the first initial run/apply, all expect the database is created. Hence, running the apply again say in plan that only the database was not created.
Also, if you look into the error message it clearly says, that there is an issue with the role assumed by cloud9 and that the role does not have permission for action rds:CreateDBInstance. But this is hard to debug, as access to the role definitions are not granted for the users created for the execrises.
@Amir_Zare where you able to create all the resources after the plan stage in terraform apply? I mean after this prompt
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value:
Hello @L41
Yeah, I was able to run terraform apply without any issues, and all the resources were created successfully. There might be an issue in your Terraform config files that is causing this problem. This is a practice lab, and you can always compare your answers with the provided solution files. Most probably, the issue is within the terraform/modules/bastion_host/rds.tf file.