-1

I am trying to create a terraform that will create a windows server, linux machine in an aws vpc and then will save the Windows server and the admin password in a local file,

I Know that I will need the keypair in order to decrypt the password of the windows server, though, I am assuming that the indrastructure won't have a key-pair on their end,

please find my terrform main.tf (as this is the only file for now):

### Creating a Dedicated VPC for the project

module "vpc" {
  source = "terraform-aws-modules/vpc/aws"

  name = "Moc-Winsev"
  cidr = "10.0.0.0/16"

  azs            = ["us-east-1a", "eu-east-1b"]
  public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]

  enable_nat_gateway = false
  enable_vpn_gateway = false

  tags = {
    Terraform   = "Yes"
    Environment = "Dev"
  }
}
### Creting windows server
module "ec2_instance" {
  source = "terraform-aws-modules/ec2-instance/aws"

  name = "windows-server"

  instance_type          = "t3a.xlarge"
  key_name               = "${aws_key_pair.kp.id}"
  monitoring             = false
  vpc_security_group_ids = ["${module.windowserver_sg.security_group_id}"]
  subnet_id              = "${module.vpc.public_subnets[0]}"
  ami                    = "ami-069c45f40acdfe41e"

  tags = {
    Terraform   = "Yes"
    Environment = "Dev"
  }
}

## Creating Linux server
module "ec2_linux" {
  source = "terraform-aws-modules/ec2-instance/aws"

  name = "linux-instance"

  instance_type          = "t2.micro"
  key_name               = "${aws_key_pair.kp.id}"
  monitoring             = false
  vpc_security_group_ids = ["${module.windowserver_sg.security_group_id}"]
  subnet_id              = "${module.vpc.public_subnets[0]}"
  ami                    = "ami-05548f9cecf47b442"

  tags = {
    Terraform   = "Yes"
    Environment = "Dev"
  }
}

#### Creating a Security Group that will allow RDP and SSH, Attaching this to both servers
module "windowserver_sg" {
  source = "terraform-aws-modules/security-group/aws"

  name        = "windowserver"
  description = "Security group made for moccing Windows server with forwarder"
  vpc_id      = "vpc-12345678"

  ingress_cidr_blocks = ["0.0.0.0/0"]
  ingress_rules       = ["rdp-tcp", "ssh-tcp"]

}
##### Creating the Key Pair
resource "tls_private_key" "pk" {
  algorithm = "RSA"
  rsa_bits  = 4096
}

resource "aws_key_pair" "kp" {
  key_name   = "winserver"
  public_key = tls_private_key.pk.public_key_openssh
}

resource "local_file" "ssh_key" {
  filename = "winserver.pem"
  content = tls_private_key.pk.private_key_pem
}

#### Creating the Local file with all the credentials and details

resource "local_file" "needed_details" {
  content  = <<-EOT
            Server IP:
            ${module.ec2_instance.public_ip}
            Admin Password:
            ${rsadecrypt(module.ec2_instance.password_data, file("./${local_file.ssh_key.filename}"))} 
        EOT
  filename = "./Windwos_details.txt"

  depends_on = [ local_file.ssh_key ]
}


though, while trying to run (plan/apply) I get the follwing error:

╷
│ Error: Invalid function argument
│
│   on main.tf line 93, in resource "local_file" "needed_details":
│   93:             ${rsadecrypt(module.ec2_instance.password_data, file("./${local_file.ssh_key.filename}"))}
│     ├────────────────
│     │ while calling file(path)
│     │ local_file.ssh_key.filename is "winserver.pem"
│
│ Invalid value for "path" parameter: no file exists at "./winserver.pem"; this function works only with files that are distributed as part   
│ of the configuration source code, so if this file will be created by a resource in this configuration you must instead obtain this result   
│ from an attribute of that resource.

I was reading the error again and again but I don't understand how to implement the requirement in my code, how should i obtain a result from an attribute of the local file resource,

I was searching online and didn't find anything like that, so a reference will be helpful aswell

Thank you all!

EBox
  • 9
  • 2
  • Is the `winserver.pem` file in the same directory as the terraform code? – Marko E Jul 24 '23 at 17:55
  • It doesn't exist, it's created in line 81-84: resource "local_file" "ssh_key" { filename = "winserver.pem" content = tls_private_key.pk.private_key_pem } – EBox Jul 24 '23 at 20:41

2 Answers2

1

You can't do that. Your requirements have little sense. First you need to have a key, before you can create an instance using the key. You can't do this the other way around.

Marcin
  • 215,873
  • 14
  • 235
  • 294
  • hmm, seem like i didn't exaplin myself correctly, I am creating the key first, then I am creating the instances, now I want to take the key I have created and then to decrypt the password for the windows server admin user and this is why I am getting my error, if I will remove: ${rsadecrypt(module.ec2_instance.password_data, file("./${local_file.ssh_key.filename}"))} it will work perfectly fine, so basically it's like the dependency won't really make a difference – EBox Jul 25 '23 at 13:37
0

So, after quite a while of thinking, the solution for my issue was basically to refer to the content of the file and not to the file itself and it seem to bypass the issue, and it should look like this

#### Creating the Local file with all the credentials and details

resource "local_file" "needed_details" {
  content  = <<-EOT
            Server IP:
            ${module.ec2_instance.public_ip}
            Admin Password:
            ${rsadecrypt(module.ec2_instance.password_data, local_file.ssh_key.content))} 
        EOT
  filename = "./Windwos_details.txt"

  depends_on = [ local_file.ssh_key ]
}

Now the problem is different which is that the password_data is not generated as it takes a while but this solution is easy by using a null resource or time_sleep

Gautam Savaliya
  • 1,403
  • 2
  • 20
  • 31
EBox
  • 9
  • 2