Reputation: 43
I'm attempting to add a domain controller to an existing domain using terraform (in Azure). I declared some local values in the main terraform file for my servers, like so:
locals {
username_command = "$username = ${var.domainAdminUsername}"
password_command = "$password = ConvertTo-SecureString ${var.domainAdminPassword} -AsPlainText -Force"
credentials_command = "$credentials = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList ($username,$password)"
install_ad_command = "Add-WindowsFeature -name ad-domain-services -IncludeManagementTools"
configure_ad_command = "Install-ADDSDomainController -DomainName ${var.domainName} -InstallDns -Credential $credentials -SafeModeAdministratorPassword $password -Force:$true"
shutdown_command = "shutdown -r -t 10"
exit_code_hack = "exit 0"
powershell_command = "${local.username_command}; ${local.password_command}; ${local.credentials_command}; ${local.install_ad_command}; ${local.configure_ad_command}; ${local.shutdown_command}; ${local.exit_code_hack}"
}
I'm then applying a custom script extension resource on the VM, that run the powershell cmdlets built by the local values:
resource "azurerm_virtual_machine_extension" "promote-to-domain-controller" {
count = 2
depends_on = [
azurerm_windows_virtual_machine.vm
]
name = "promote-to-domain-controller"
virtual_machine_id = azurerm_windows_virtual_machine.vm[count.index].id
publisher = "Microsoft.Compute"
type = "CustomScriptExtension"
type_handler_version = "1.9"
settings = <<SETTINGS
{
"commandToExecute": "powershell.exe -Command \"${local.powershell_command}\""
}
SETTINGS
}
Everything seems to work, but the VM extension. [ { "code": "ComponentStatus/StdOut/succeeded", "level": "Info", "displayStatus": "Provisioning succeeded", "message": "" }, { "code": "ComponentStatus/StdErr/succeeded", "level": "Info", "displayStatus": "Provisioning succeeded", "message": "azadmin : The term 'azadmin' is not recognized as the name of a cmdlet, function, script file, or operable program. \r\nCheck the spelling of the name, or if a path was included, verify that the path is correct and try again.\r\nAt line:1 char:13\r\n+ $username = azadmin; $password = ConvertTo-SecureString <redacted>...\r\n+ ~~~~~~~\r\n + CategoryInfo : ObjectNotFound: (azadmin:String) [], CommandNotFoundException\r\n + FullyQualifiedErrorId : CommandNotFoundException\r\n \r\nNew-Object : Exception calling \".ctor\" with \"2\" argument(s): \"Cannot process argument because the value of argument \r\n\"userName\" is not valid. Change the value of the \"userName\" argument and run the operation again.\"\r\nAt line:1 char:118\r\n+ ... edentials = New-Object -TypeName System.Management.Automation.PSCrede ...\r\n+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n + CategoryInfo : InvalidOperation: (:) [New-Object], MethodInvocationException\r\n + FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand\r\n \r\n" } ]
var.domainAdminUsername is set to 'azadmin'. In the first screenshot, on line 11, you can see that I'm passing this value ($username) to the PSCredential constructor. This constructor takes two overloads: a string and a securestring. It's like the value that's getting passed to the constructor isn't a string, though it should be.
Upvotes: 1
Views: 2392
Reputation: 11431
You can use the below to promote your VM as a domain controller for a exisitng forest .
Main.tf file:
provider "azurerm" {
features {}
}
locals {
password_command = "$password = ConvertTo-SecureString ${var.admin_password} -AsPlainText -Force"
credentials_command = "$credentials = Get-Credential ${var.domainAdminUsername}"
install_ad_command = "Add-WindowsFeature -name ad-domain-services -IncludeManagementTools"
configure_ad_command = "Install-ADDSDomainController -DomainName ${var.active_directory_domain} -InstallDns -Credential $credentials -SafeModeAdministratorPassword $password -Force:$true"
shutdown_command = "shutdown -r -t 10"
exit_code_hack = "exit 0"
powershell_command = " ${local.password_command};${local.credentials_command}; ${local.install_ad_command}; ${local.configure_ad_command}; ${local.shutdown_command}; ${local.exit_code_hack}"
}
data "azurerm_virtual_machine" "example" {
name = "${var.vmname}"
resource_group_name = "${var.resource_group_name}"
}
resource "azurerm_virtual_machine_extension" "promote-to-domain-controller" {
name = "promote-to-domain-controller"
virtual_machine_id = data.azurerm_virtual_machine.example.id
publisher = "Microsoft.Compute"
type = "CustomScriptExtension"
type_handler_version = "1.9"
settings = <<SETTINGS
{
"commandToExecute": "powershell.exe -Command \"${local.powershell_command}\""
}
SETTINGS
}
variable.tf file:
variable resource_group_name {
description = "The name of the Resource Group where the VM is"
default = "resourcegroup"
}
variable location {
description = "The Azure Region in which the Resource Group exists"
default = "resourcegrouplocation"
}
# Active Directory & Domain Controller
variable vmname {
description = "The Virtual Machine name that you wish to join to the domain"
default = "vmname"
}
variable "active_directory_domain" {
description = "The name of the Active Directory domain, for example `consoto.local`"
default = "domainname"
}
variable "domainAdminUsername" {
description = "The local administrator account on the Domain"
default = "Domain\admin or [email protected]"
}
variable "admin_password" {
description = "The password associated with the local administrator account on the virtual machine"
default = "password"
}
Output: (Terraform Plan)
Adding VM to existing domain:
Main.tf
resource "azurerm_virtual_machine_extension" "join-domain" {
name = "join-domain"
location = "${var.location}"
resource_group_name = "${var.resource_group_name}"
virtual_machine_name = "${var.vmname}"
publisher = "Microsoft.Compute"
type = "JsonADDomainExtension"
type_handler_version = "1.3"
settings = <<SETTINGS
{
"Name": "${var.active_directory_domain}",
"OUPath": "",
"User": "${var.active_directory_domain}\\${var.active_directory_username}",
"Restart": "true",
"Options": "3"
}
SETTINGS
protected_settings = <<SETTINGS
{
"Password": "${var.active_directory_password}"
}
SETTINGS
}
Variable.tf
variable resource_group_name {
description = "The name of the Resource Group where the VM is"
}
variable location {
description = "The Azure Region in which the Resource Group exists"
}
# Active Directory & Domain Controller
variable vmname {
description = "The Virtual Machine name that you wish to join to the domain"
}
variable "active_directory_domain" {
description = "The name of the Active Directory domain, for example `consoto.local`"
}
variable "active_directory_username" {
description = "The username of an account with permissions to bind machines to the Active Directory Domain"
}
variable "active_directory_password" {
description = "The password of the account with permissions to bind machines to the Active Directory Domain"
}
Note: Please ensure to use username as domain\adminusername for the code to run as its expecting username to be domain's username.
Upvotes: 0