diff --git a/.gitignore b/.gitignore
index eb0fdd16..fa9c561a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,9 +31,10 @@ ad/*/providers/*/ssh_keys/*id_rsa*
ad/*/providers/*/ssh_keys/*.pub
ad/*/providers/*/extensions/*.rb
-# Terraform
+# Terraform / Terragrunt
.terraform/
.terraform.lock.hcl
+.terragrunt-cache/
*.tfstate
*.tfstate.backup
*.tfplan
diff --git a/ad/DRACARYS/providers/aws/linux.tf b/ad/DRACARYS/providers/aws/linux.tf
index 45739841..322e59c6 100644
--- a/ad/DRACARYS/providers/aws/linux.tf
+++ b/ad/DRACARYS/providers/aws/linux.tf
@@ -1,3 +1,7 @@
+# NOTE: AMI IDs below are region-specific (originally eu-west-1).
+# Replace with AMI IDs for your target AWS region.
+# See: https://aws.amazon.com/marketplace for Windows Server base AMIs
+
"lx01" = {
name = "lx01"
linux_sku = "24_04-lts-gen2"
diff --git a/ad/DRACARYS/providers/aws/windows.tf b/ad/DRACARYS/providers/aws/windows.tf
index e1da7885..1af8eb3e 100644
--- a/ad/DRACARYS/providers/aws/windows.tf
+++ b/ad/DRACARYS/providers/aws/windows.tf
@@ -1,6 +1,11 @@
# Standard_B2s : 2 CPU / 4GB
# Standard_B2ms : 2CPU / 8GB
# Standard_B4ms : 4 cpu / 16 GB
+
+# NOTE: AMI IDs below are region-specific (originally eu-west-1).
+# Replace with AMI IDs for your target AWS region.
+# See: https://aws.amazon.com/marketplace for Windows Server base AMIs
+
"dc01" = {
name = "dc01"
domain = "dracarys.lab"
diff --git a/ad/GOAD-Light/providers/aws/windows.tf b/ad/GOAD-Light/providers/aws/windows.tf
index 5e5b3906..8a80f75b 100644
--- a/ad/GOAD-Light/providers/aws/windows.tf
+++ b/ad/GOAD-Light/providers/aws/windows.tf
@@ -1,3 +1,7 @@
+# NOTE: AMI IDs below are region-specific (originally eu-west-1).
+# Replace with AMI IDs for your target AWS region.
+# See: https://aws.amazon.com/marketplace for Windows Server base AMIs
+
"dc01" = {
name = "dc01"
domain = "sevenkingdoms.local"
diff --git a/ad/GOAD-Mini/providers/aws/linux.tf b/ad/GOAD-Mini/providers/aws/linux.tf
index c40117d8..0054364c 100644
--- a/ad/GOAD-Mini/providers/aws/linux.tf
+++ b/ad/GOAD-Mini/providers/aws/linux.tf
@@ -1,3 +1,7 @@
+# NOTE: AMI IDs below are region-specific (originally eu-west-1).
+# Replace with AMI IDs for your target AWS region.
+# See: https://aws.amazon.com/marketplace for Windows Server base AMIs
+
# "lx01" = {
# name = "lx01"
# linux_sku = "22_04-lts-gen2"
diff --git a/ad/GOAD-Mini/providers/aws/windows.tf b/ad/GOAD-Mini/providers/aws/windows.tf
index e406ec80..55d2618b 100644
--- a/ad/GOAD-Mini/providers/aws/windows.tf
+++ b/ad/GOAD-Mini/providers/aws/windows.tf
@@ -1,3 +1,7 @@
+# NOTE: AMI IDs below are region-specific (originally eu-west-1).
+# Replace with AMI IDs for your target AWS region.
+# See: https://aws.amazon.com/marketplace for Windows Server base AMIs
+
"dc01" = {
name = "dc01"
domain = "sevenkingdoms.local"
diff --git a/ad/GOAD-variant-1/providers/aws/linux.tf b/ad/GOAD-variant-1/providers/aws/linux.tf
index c40117d8..0054364c 100644
--- a/ad/GOAD-variant-1/providers/aws/linux.tf
+++ b/ad/GOAD-variant-1/providers/aws/linux.tf
@@ -1,3 +1,7 @@
+# NOTE: AMI IDs below are region-specific (originally eu-west-1).
+# Replace with AMI IDs for your target AWS region.
+# See: https://aws.amazon.com/marketplace for Windows Server base AMIs
+
# "lx01" = {
# name = "lx01"
# linux_sku = "22_04-lts-gen2"
diff --git a/ad/GOAD-variant-1/providers/aws/windows.tf b/ad/GOAD-variant-1/providers/aws/windows.tf
index 40b3c2c3..c9e714d5 100644
--- a/ad/GOAD-variant-1/providers/aws/windows.tf
+++ b/ad/GOAD-variant-1/providers/aws/windows.tf
@@ -1,6 +1,11 @@
# t2.medium = 2cpu / 4GB
# t2.large = 2cpu / 8GB
# t2.xlarge = 4cpu / 16GB
+
+# NOTE: AMI IDs below are region-specific (originally eu-west-1).
+# Replace with AMI IDs for your target AWS region.
+# See: https://aws.amazon.com/marketplace for Windows Server base AMIs
+
"dc01" = {
name = "dc01"
domain = "deltasystems.local"
diff --git a/ad/GOAD/data/test-config.json b/ad/GOAD/data/test-config.json
new file mode 100644
index 00000000..773aba24
--- /dev/null
+++ b/ad/GOAD/data/test-config.json
@@ -0,0 +1,681 @@
+{
+"lab" : {
+ "hosts" : {
+ "dc01" : {
+ "hostname" : "kingslanding",
+ "type" : "dc",
+ "local_admin_password": "qjQ!bcwXKU!3yBrDM2VU",
+ "domain" : "sevenkingdoms.local",
+ "path" : "DC=sevenkingdoms,DC=local",
+ "local_groups" : {
+ "Administrators" : [
+ "sevenkingdoms\\robert.baratheon",
+ "sevenkingdoms\\cersei.lannister",
+ "sevenkingdoms\\DragonRider"
+ ],
+ "Remote Desktop Users" : [
+ "sevenkingdoms\\Small Council",
+ "sevenkingdoms\\Baratheon"
+ ]
+ },
+ "scripts" : ["sidhistory.ps1"],
+ "vulns" : ["disable_firewall"],
+ "security": ["account_is_sensitive", "audit_policy"],
+ "security_vars": {
+ "account_is_sensitive" : { "renly": {"account" : "renly.baratheon"} }
+ }
+ },
+ "dc02" : {
+ "hostname" : "winterfell",
+ "type" : "dc",
+ "local_admin_password": "VExkHyfsKTW_HMNA7fQy",
+ "domain" : "north.sevenkingdoms.local",
+ "path" : "DC=north,DC=sevenkingdoms,DC=local",
+ "local_groups" : {
+ "Administrators" : [
+ "north\\eddard.stark",
+ "north\\catelyn.stark",
+ "north\\robb.stark"
+ ],
+ "Remote Desktop Users" : [
+ "north\\Stark"
+ ]
+ },
+ "scripts" : [
+ "asrep_roasting.ps1",
+ "constrained_delegation_use_any.ps1",
+ "constrained_delegation_kerb_only.ps1",
+ "ntlm_relay.ps1",
+ "responder.ps1",
+ "gpo_abuse.ps1",
+ "rdp_scheduler.ps1",
+ "unconstrained_delegation_user.ps1"
+ ],
+ "vulns" : ["disable_firewall","directory", "credentials", "autologon", "files", "enable_llmnr", "enable_nbt_ns", "shares", "anonymous_enum"],
+ "vulns_vars" : {
+ "directory": {
+ "setup": "C:\\setup"
+ },
+ "credentials" : {
+ "TERMSRV/castelblack": {
+ "username" : "north\\robb.stark",
+ "secret" : "sexywolfy",
+ "runas" : "north\\robb.stark",
+ "runas_password" : "sexywolfy"
+ }
+ },
+ "autologon" : {
+ "robb.stark" : {
+ "username" : "north\\robb.stark",
+ "password" : "sexywolfy"
+ }
+ },
+ "files" : {
+ "rdp" : {
+ "src" : "dc02/bot_rdp.ps1",
+ "dest" : "C:\\setup\\bot_rdp.ps1"
+ },
+ "sysvol_fake_script": {
+ "src" : "dc02/sysvol_scripts/script.ps1",
+ "dest": "C:\\Windows\\SYSVOL\\domain\\scripts\\script.ps1"
+ },
+ "sysvol_secret": {
+ "src" : "dc02/sysvol_scripts/secret.ps1",
+ "dest": "C:\\Windows\\SYSVOL\\domain\\scripts\\secret.ps1"
+ }
+ }
+ },
+ "security": ["audit_policy"]
+ },
+ "srv02" : {
+ "hostname" : "castelblack",
+ "type" : "server",
+ "local_admin_password": "VExkHyfsKTW_HMNA7fQy",
+ "domain" : "north.sevenkingdoms.local",
+ "path" : "DC=north,DC=sevenkingdoms,DC=local",
+ "use_laps": false,
+ "local_groups" : {
+ "Administrators" : [
+ "north\\jeor.mormont"
+ ],
+ "Remote Desktop Users" : [
+ "north\\Night Watch",
+ "north\\Mormont",
+ "north\\Stark"
+ ]
+ },
+ "scripts" : [],
+ "vulns" : ["directory", "disable_firewall", "openshares", "files", "permissions"],
+ "vulns_vars" : {
+ "directory": {
+ "shares": "C:\\shares",
+ "all": "C:\\shares\\all"
+ },
+ "files" : {
+ "website" : {
+ "src" : "srv02/wwwroot",
+ "dest" : "C:\\inetpub\\"
+ },
+ "letter_in_shares": {
+ "src" : "srv02/all/arya.txt",
+ "dest": "C:\\shares\\all\\arya.txt"
+ }
+ },
+ "permissions" : {
+ "IIS_IUSRS_upload": {
+ "path" : "C:\\inetpub\\wwwroot\\upload",
+ "user" : "IIS_IUSRS",
+ "rights" : "FullControl"
+ }
+ }
+ },
+ "mssql":{
+ "sa_password": "Sup1_sa_P@ssw0rd!",
+ "svcaccount" : "sql_svc",
+ "sysadmins" : [
+ "NORTH\\jon.snow"
+ ],
+ "executeaslogin" : {
+ "NORTH\\samwell.tarly" : "sa",
+ "NORTH\\brandon.stark" : "NORTH\\jon.snow"
+ },
+ "executeasuser" : {
+ "arya_master_dbo": {
+ "user": "NORTH\\arya.stark",
+ "db" : "master",
+ "impersonate" : "dbo"
+ },
+ "arya_dbms_dbo": {
+ "user": "NORTH\\arya.stark",
+ "db" : "msdb",
+ "impersonate" : "dbo"
+ }
+ },
+ "linked_servers": {
+ "BRAAVOS" : {
+ "data_src": "braavos.essos.local",
+ "users_mapping": [
+ {"local_login": "NORTH\\jon.snow","remote_login": "sa", "remote_password": "sa_P@ssw0rd!Ess0s"}
+ ]
+ }
+ }
+ }
+ },
+ "dc03" : {
+ "hostname" : "meereen",
+ "type" : "dc",
+ "local_admin_password": "M!BbXzL48D9mH9dQzp*e",
+ "domain" : "essos.local",
+ "path" : "DC=essos,DC=local",
+ "local_groups" : {
+ "Administrators" : [
+ "essos\\daenerys.targaryen"
+ ],
+ "Remote Desktop Users" : [
+ "essos\\Targaryen"
+ ]
+ },
+ "scripts" : ["asrep_roasting2.ps1"],
+ "vulns" : ["ntlmdowngrade", "disable_firewall"],
+ "security": ["audit_policy"]
+ },
+ "srv03" : {
+ "hostname" : "braavos",
+ "type" : "server",
+ "local_admin_password": "M!BbXzL48D9mH9dQzp*e",
+ "domain" : "essos.local",
+ "path" : "DC=essos,DC=local",
+ "use_laps": true,
+ "local_groups" : {
+ "Administrators" : [
+ "essos\\khal.drogo"
+ ]
+ },
+ "Remote Desktop Users" : [
+ "essos\\Dothraki"
+ ],
+ "scripts" : [],
+ "vulns" : ["openshares","disable_firewall"],
+ "security": ["enable_run_as_ppl"],
+ "mssql":{
+ "sa_password": "sa_P@ssw0rd!Ess0s",
+ "svcaccount" : "sql_svc",
+ "sysadmins" : [
+ "ESSOS\\khal.drogo"
+ ],
+ "executeaslogin" : {
+ "ESSOS\\jorah.mormont" : "sa"
+ },
+ "executeasuser" : {},
+ "linked_servers": {
+ "CASTELBLACK" : {
+ "data_src": "castelblack.north.sevenkingdoms.local",
+ "users_mapping": [
+ {"local_login": "ESSOS\\khal.drogo","remote_login": "sa", "remote_password": "Sup1_sa_P@ssw0rd!"}
+ ]
+ }
+ }
+ }
+ }
+ },
+ "domains" : {
+ "essos.local" : {
+ "dc": "dc03",
+ "domain_password" : "M!BbXzL48D9mH9dQzp*e",
+ "netbios_name": "ESSOS",
+ "ca_server": "Braavos",
+ "trust" : "sevenkingdoms.local",
+ "laps_path": "OU=Laps,DC=essos,DC=local",
+ "organisation_units" : {
+ },
+ "laps_readers": [
+ "jorah.mormont",
+ "Spys"
+ ],
+ "groups" : {
+ "universal" : {},
+ "global" : {
+ "Targaryen" : {
+ "managed_by" : "viserys.targaryen",
+ "path" : "CN=Users,DC=essos,DC=local"
+ },
+ "Dothraki" : {
+ "managed_by" : "khal.drogo",
+ "path" : "CN=Users,DC=essos,DC=local"
+ },
+ "Dragons":{
+ "managed_by" : "Administrator",
+ "path" : "CN=Users,DC=essos,DC=local"
+ },
+ "QueenProtector":{
+ "managed_by" : "Administrator",
+ "path" : "CN=Users,DC=essos,DC=local",
+ "members" : ["ESSOS\\Dragons"]
+ },
+ "Domain Admins":{
+ "managed_by" : "Administrator",
+ "path" : "CN=Users,DC=essos,DC=local",
+ "members" : ["ESSOS\\QueenProtector"]
+ }
+ },
+ "domainlocal" : {
+ "DragonsFriends" : {
+ "managed_by" : "daenerys.targaryen",
+ "path" : "CN=Users,DC=essos,DC=local"
+ },
+ "Spys" : {
+ "path" : "CN=Users,DC=essos,DC=local"
+ }
+ }
+ },
+ "multi_domain_groups_member" : {
+ "DragonsFriends" : [
+ "sevenkingdoms.local\\tyron.lannister",
+ "essos.local\\daenerys.targaryen"
+ ],
+ "Spys" : [
+ "sevenkingdoms.local\\Small Council"
+ ]
+ },
+ "gmsa" : {
+ "gmsa_account": {
+ "gMSA_Name" : "gmsaDragon",
+ "gMSA_FQDN" : "gmsaDragon.essos.local",
+ "gMSA_SPNs" : ["HTTP/braavos", "HTTP/braavos.essos.local"],
+ "gMSA_HostNames" : ["braavos"]
+ }
+ },
+ "acls" : {
+ "GenericAll_khal_viserys" : {"for": "khal.drogo", "to": "viserys.targaryen", "right": "GenericAll", "inheritance": "None"},
+ "GenericAll_spy_jorah" : {"for": "Spys", "to": "jorah.mormont", "right": "GenericAll", "inheritance": "None"},
+ "GenericAll_khal_esc4" : {"for": "khal.drogo", "to": "CN=ESC4,CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=essos,DC=local", "right": "GenericAll", "inheritance": "None"},
+ "WriteProperty_petyer_domadmin" : {"for": "viserys.targaryen", "to": "jorah.mormont", "right": "WriteProperty", "inheritance": "All"},
+ "GenericWrite_DragonsFriends_braavos" : {"for": "DragonsFriends", "to": "braavos$", "right": "GenericWrite", "inheritance": "None"},
+ "GenericAll_missandei_khal" : {"for": "missandei", "to": "khal.drogo", "right": "GenericAll", "inheritance": "None"},
+ "GenericAll_gmsaDragon_drogo" : {"for": "gmsaDragon$", "to": "drogon", "right": "GenericAll", "inheritance": "None"}
+ },
+ "users" : {
+ "daenerys.targaryen" : {
+ "firstname" : "daenerys",
+ "surname" : "targaryen",
+ "password" : "BurnThemAll!",
+ "city" : "-",
+ "description" : "Darnerys Targaryen",
+ "groups" : ["Targaryen", "Domain Admins"],
+ "path" : "CN=Users,DC=essos,DC=local"
+ },
+ "viserys.targaryen" : {
+ "firstname" : "viserys",
+ "surname" : "targaryen",
+ "password" : "GoldCrown",
+ "city" : "-",
+ "description" : "Viserys Targaryen",
+ "groups" : ["Targaryen"],
+ "path" : "CN=Users,DC=essos,DC=local"
+ },
+ "khal.drogo" : {
+ "firstname" : "khal",
+ "surname" : "drogo",
+ "password" : "horse",
+ "city" : "-",
+ "description" : "Khal Drogo",
+ "groups" : ["Dothraki"],
+ "path" : "CN=Users,DC=essos,DC=local"
+ },
+ "jorah.mormont" : {
+ "firstname" : "jorah",
+ "surname" : "mormont",
+ "password" : "H0nnor!",
+ "city" : "-",
+ "description" : "Jorah Mormont",
+ "groups" : ["Targaryen"],
+ "path" : "CN=Users,DC=essos,DC=local"
+ },
+ "missandei" : {
+ "firstname" : "missandei",
+ "surname" : "-",
+ "password" : "fr3edom",
+ "city" : "-",
+ "description" : "missandei",
+ "groups" : [],
+ "path" : "CN=Users,DC=essos,DC=local"
+ },
+ "drogon" : {
+ "firstname" : "drogon",
+ "surname" : "-",
+ "password" : "Dracarys",
+ "city" : "-",
+ "description" : "drogon",
+ "groups" : ["Dragons"],
+ "path" : "CN=Users,DC=essos,DC=local"
+ },
+ "sql_svc" : {
+ "firstname" : "sql",
+ "surname" : "service",
+ "password" : "YouWillNotKerboroast1ngMeeeeee",
+ "city" : "-",
+ "description" : "sql service",
+ "groups" : [],
+ "path" : "CN=Users,DC=essos,DC=local",
+ "spns" : ["MSSQLSvc/braavos.essos.local:1433","MSSQLSvc/braavos.essos.local"]
+ }
+ }
+ },
+ "north.sevenkingdoms.local" : {
+ "dc": "dc02",
+ "domain_password" : "VExkHyfsKTW_HMNA7fQy",
+ "netbios_name": "NORTH",
+ "trust" : "",
+ "laps_path": "OU=Laps,DC=north,DC=sevenkingdoms,DC=local",
+ "organisation_units" : {
+ },
+ "groups" : {
+ "universal" : {},
+ "global" : {
+ "Stark" : {
+ "managed_by" : "eddard.stark",
+ "path" : "CN=Users,DC=North,DC=sevenkingdoms,DC=local"
+ },
+ "Night Watch" : {
+ "managed_by" : "jeor.mormont",
+ "path" : "CN=Users,DC=North,DC=sevenkingdoms,DC=local"
+ },
+ "Mormont" : {
+ "managed_by" : "jeor.mormont",
+ "path" : "CN=Users,DC=North,DC=sevenkingdoms,DC=local"
+ }
+ },
+ "domainlocal" : {
+ "AcrossTheSea" : {
+ "path" : "CN=Users,DC=North,DC=sevenkingdoms,DC=local"
+ }
+ }
+ },
+ "multi_domain_groups_member" : {},
+ "acls" : {
+ "anonymous_rpc" : {"for": "NT AUTHORITY\\ANONYMOUS LOGON", "to": "DC=North,DC=sevenkingdoms,DC=local", "right": "ReadProperty", "inheritance": "All"},
+ "anonymous_rpc2" : {"for": "NT AUTHORITY\\ANONYMOUS LOGON", "to": "DC=North,DC=sevenkingdoms,DC=local", "right": "GenericExecute", "inheritance": "All"}
+ },
+ "users" : {
+ "arya.stark" : {
+ "firstname" : "Arya",
+ "surname" : "Stark",
+ "password" : "Needle",
+ "city" : "Winterfell",
+ "description" : "Arya Stark",
+ "groups" : ["Stark"],
+ "path" : "CN=Users,DC=North,DC=sevenkingdoms,DC=local"
+ },
+ "eddard.stark" : {
+ "firstname" : "Eddard",
+ "surname" : "Stark",
+ "password" : "FightP3aceAndHonor!",
+ "city" : "King's Landing",
+ "description" : "Eddard Stark",
+ "groups" : ["Stark", "Domain Admins"],
+ "path" : "CN=Users,DC=North,DC=sevenkingdoms,DC=local"
+ },
+ "catelyn.stark" : {
+ "firstname" : "Catelyn",
+ "surname" : "Stark",
+ "password" : "robbsansabradonaryarickon",
+ "city" : "King's Landing",
+ "description" : "Catelyn Stark",
+ "groups" : ["Stark"],
+ "path" : "CN=Users,DC=North,DC=sevenkingdoms,DC=local"
+ },
+ "robb.stark" : {
+ "firstname" : "Robb",
+ "surname" : "Stark",
+ "password" : "sexywolfy",
+ "city" : "Winterfell",
+ "description" : "Robb Stark",
+ "groups" : ["Stark"],
+ "path" : "CN=Users,DC=North,DC=sevenkingdoms,DC=local"
+ },
+ "sansa.stark" : {
+ "firstname" : "Sansa",
+ "surname" : "Stark",
+ "password" : "345ertdfg",
+ "city" : "Winterfell",
+ "description" : "Sansa Stark",
+ "groups" : ["Stark"],
+ "path" : "CN=Users,DC=North,DC=sevenkingdoms,DC=local",
+ "spns" : ["HTTP/eyrie.north.sevenkingdoms.local"]
+ },
+ "brandon.stark" : {
+ "firstname" : "Brandon",
+ "surname" : "Stark",
+ "password" : "iseedeadpeople",
+ "city" : "Winterfell",
+ "description" : "Brandon Stark",
+ "groups" : ["Stark"],
+ "path" : "CN=Users,DC=North,DC=sevenkingdoms,DC=local"
+ },
+ "rickon.stark" : {
+ "firstname" : "Rickon",
+ "surname" : "Stark",
+ "password" : "Winter2022",
+ "city" : "Winterfell",
+ "description" : "Rickon Stark",
+ "groups" : ["Stark"],
+ "path" : "CN=Users,DC=North,DC=sevenkingdoms,DC=local"
+ },
+ "hodor" : {
+ "firstname" : "hodor",
+ "surname" : "hodor",
+ "password" : "hodor",
+ "city" : "Winterfell",
+ "description" : "Brainless Giant",
+ "groups" : ["Stark"],
+ "path" : "CN=Users,DC=North,DC=sevenkingdoms,DC=local"
+ },
+ "jon.snow" : {
+ "firstname" : "Jon",
+ "surname" : "Snow",
+ "password" : "iknownothing",
+ "city" : "Castel Black",
+ "description" : "Jon Snow",
+ "groups" : ["Stark", "Night Watch"],
+ "path" : "CN=Users,DC=North,DC=sevenkingdoms,DC=local",
+ "spns" : ["HTTP/thewall.north.sevenkingdoms.local"]
+ },
+ "samwell.tarly" : {
+ "firstname" : "Samwell",
+ "surname" : "Tarly",
+ "password" : "Heartsbane",
+ "city" : "Castel Black",
+ "description" : "Samwell Tarly (Password : Heartsbane)",
+ "groups" : ["Night Watch"],
+ "path" : "CN=Users,DC=North,DC=sevenkingdoms,DC=local"
+ },
+ "jeor.mormont" : {
+ "firstname" : "Jeor",
+ "surname" : "Mormont",
+ "password" : "_L0ngCl@w_",
+ "city" : "Castel Black",
+ "description" : "Jeor Mormont",
+ "groups" : ["Night Watch", "Mormont"],
+ "path" : "CN=Users,DC=North,DC=sevenkingdoms,DC=local"
+ },
+ "sql_svc" : {
+ "firstname" : "sql",
+ "surname" : "service",
+ "password" : "YouWillNotKerboroast1ngMeeeeee",
+ "city" : "-",
+ "description" : "sql service",
+ "groups" : [],
+ "path" : "CN=Users,DC=North,DC=sevenkingdoms,DC=local",
+ "spns" : ["MSSQLSvc/castelblack.north.sevenkingdoms.local:1433","MSSQLSvc/castelblack.north.sevenkingdoms.local"]
+ }
+ }
+ },
+ "sevenkingdoms.local" : {
+ "dc": "dc01",
+ "domain_password" : "qjQ!bcwXKU!3yBrDM2VU",
+ "netbios_name": "SEVENKINGDOMS",
+ "trust" : "essos.local",
+ "laps_path": "OU=Laps,DC=sevenkingdoms,DC=local",
+ "organisation_units" : {
+ "Vale" : { "path" : "DC=sevenkingdoms,DC=local"},
+ "IronIslands" : { "path" : "DC=sevenkingdoms,DC=local"},
+ "Riverlands" : { "path" : "DC=sevenkingdoms,DC=local"},
+ "Crownlands" : { "path" : "DC=sevenkingdoms,DC=local"},
+ "Stormlands" : { "path" : "DC=sevenkingdoms,DC=local"},
+ "Westerlands" : { "path" : "DC=sevenkingdoms,DC=local"},
+ "Reach" : { "path" : "DC=sevenkingdoms,DC=local"},
+ "Dorne" : { "path" : "DC=sevenkingdoms,DC=local"}
+ },
+ "groups" : {
+ "universal" : {},
+ "global" : {
+ "Lannister" : {
+ "managed_by" : "tywin.lannister",
+ "path" : "OU=Westerlands,DC=sevenkingdoms,DC=local"
+ },
+ "Baratheon" : {
+ "managed_by" : "robert.baratheon",
+ "path" : "OU=Stormlands,DC=sevenkingdoms,DC=local"
+ },
+ "Small Council" : {
+ "path" : "OU=Crownlands,DC=sevenkingdoms,DC=local"
+ },
+ "DragonStone" : {
+ "path" : "OU=Crownlands,DC=sevenkingdoms,DC=local"
+ },
+ "KingsGuard" : {
+ "path" : "OU=Crownlands,DC=sevenkingdoms,DC=local"
+ },
+ "DragonRider" : {
+ "path" : "OU=Crownlands,DC=sevenkingdoms,DC=local"
+ }
+ },
+ "domainlocal" : {
+ "AcrossTheNarrowSea" : {
+ "path" : "CN=Users,DC=sevenkingdoms,DC=local"
+ }
+ }
+ },
+ "multi_domain_groups_member" : {
+ "AcrossTheNarrowSea" : [
+ "essos.local\\daenerys.targaryen"
+ ]
+ },
+ "acls" : {
+ "forcechangepassword_tywin_jaime" : {"for": "tywin.lannister", "to": "jaime.lannister", "right": "Ext-User-Force-Change-Password", "inheritance": "None"},
+ "GenericWrite_on_user_jaimie_joffrey" : {"for": "jaime.lannister", "to": "joffrey.baratheon", "right": "GenericWrite", "inheritance": "None"},
+ "Writedacl_joffrey_tyron" : {"for": "joffrey.baratheon", "to": "tyron.lannister", "right": "WriteDacl", "inheritance": "None"},
+ "self-self-membership-on-group_tyron_small_council" : {"for": "tyron.lannister", "to": "Small Council", "right": "Ext-Self-Self-Membership", "inheritance": "None"},
+ "addmember_smallcouncil_DragonStone" : {"for": "Small Council", "to": "DragonStone", "right": "Ext-Write-Self-Membership", "inheritance": "All"},
+ "write_owner_dragonstone_kingsguard" : {"for": "DragonStone", "to": "KingsGuard", "right": "WriteOwner", "inheritance": "None"},
+ "GenericAll_kingsguard_stanis" : {"for": "KingsGuard", "to": "stannis.baratheon", "right": "GenericAll", "inheritance": "None"},
+ "GenericAll_stanis_dc" : {"for": "stannis.baratheon", "to": "kingslanding$", "right": "GenericAll", "inheritance": "None"},
+ "GenericAll_group_acrrosdom_dc" : {"for": "AcrossTheNarrowSea", "to": "kingslanding$", "right": "GenericAll", "inheritance": "None"},
+ "GenericAll_varys_domadmin" : {"for": "lord.varys", "to": "Domain Admins", "right": "GenericAll", "inheritance": "None"},
+ "GenericAll_varys_domadmin_holder" : {"for": "lord.varys", "to": "CN=AdminSDHolder,CN=System,DC=sevenkingdoms,DC=local", "right": "GenericAll", "inheritance": "None"},
+ "WriteDACL_renly_Crownlands" : {"for": "renly.baratheon", "to": "OU=Crownlands,DC=sevenkingdoms,DC=local", "right": "WriteDacl", "inheritance": "None"}
+ },
+ "users" : {
+ "tywin.lannister" : {
+ "firstname" : "Tywin",
+ "surname" : "Lanister",
+ "password" : "powerkingftw135",
+ "city" : "Casterly Rock",
+ "description" : "Tywin Lanister",
+ "groups" : ["Lannister"],
+ "path" : "OU=Crownlands,DC=sevenkingdoms,DC=local"
+ },
+ "jaime.lannister" : {
+ "firstname" : "Jaime",
+ "surname" : "Lanister",
+ "password" : "cersei",
+ "city" : "King's Landing",
+ "description" : "Jaime Lanister",
+ "groups" : ["Lannister"],
+ "path" : "OU=Crownlands,DC=sevenkingdoms,DC=local"
+ },
+ "cersei.lannister" : {
+ "firstname" : "Cersei",
+ "surname" : "Lanister",
+ "password" : "il0vejaime",
+ "city" : "King's Landing",
+ "description" : "Cersei Lanister",
+ "groups" : ["Lannister","Baratheon","Domain Admins","Small Council"],
+ "path" : "OU=Crownlands,DC=sevenkingdoms,DC=local"
+ },
+ "tyron.lannister" : {
+ "firstname" : "Tyron",
+ "surname" : "Lanister",
+ "password" : "Alc00L&S3x",
+ "city" : "King's Landing",
+ "description" : "Tyron Lanister",
+ "groups" : ["Lannister"],
+ "path" : "OU=Westerlands,DC=sevenkingdoms,DC=local"
+ },
+ "robert.baratheon" : {
+ "firstname" : "Robert",
+ "surname" : "Baratheon",
+ "password" : "iamthekingoftheworld",
+ "city" : "King's Landing",
+ "description" : "Robert Lanister",
+ "groups" : ["Baratheon","Domain Admins","Small Council","Protected Users"],
+ "path" : "OU=Crownlands,DC=sevenkingdoms,DC=local"
+ },
+ "joffrey.baratheon" : {
+ "firstname" : "Joffrey",
+ "surname" : "Baratheon",
+ "password" : "1killerlion",
+ "city" : "King's Landing",
+ "description" : "Joffrey Baratheon",
+ "groups" : ["Baratheon","Lannister"],
+ "path" : "OU=Crownlands,DC=sevenkingdoms,DC=local"
+ },
+ "renly.baratheon" : {
+ "firstname" : "Renly",
+ "surname" : "Baratheon",
+ "password" : "lorastyrell",
+ "city" : "King's Landing",
+ "description" : "Renly Baratheon",
+ "groups" : ["Baratheon","Small Council"],
+ "path" : "OU=Crownlands,DC=sevenkingdoms,DC=local"
+ },
+ "stannis.baratheon" : {
+ "firstname" : "Stannis",
+ "surname" : "Baratheon",
+ "password" : "Drag0nst0ne",
+ "city" : "King's Landing",
+ "description" : "Stannis Baratheon",
+ "groups" : ["Baratheon","Small Council"],
+ "path" : "OU=Crownlands,DC=sevenkingdoms,DC=local"
+ },
+ "petyer.baelish" : {
+ "firstname" : "Petyer",
+ "surname" : "Baelish",
+ "password" : "@littlefinger@",
+ "city" : "King's Landing",
+ "description" : "Petyer Baelish",
+ "groups" : ["Small Council"],
+ "path" : "OU=Crownlands,DC=sevenkingdoms,DC=local"
+ },
+ "lord.varys" : {
+ "firstname" : "Lord",
+ "surname" : "Varys",
+ "password" : "_W1sper_$",
+ "city" : "King's Landing",
+ "description" : "Lord Varys",
+ "groups" : ["Small Council"],
+ "path" : "OU=Crownlands,DC=sevenkingdoms,DC=local"
+ },
+ "maester.pycelle" : {
+ "firstname" : "Maester",
+ "surname" : "Pycelle",
+ "password" : "MaesterOfMaesters",
+ "city" : "King's Landing",
+ "description" : "Maester Pycelle",
+ "groups" : ["Small Council"],
+ "path" : "OU=Crownlands,DC=sevenkingdoms,DC=local"
+ }
+ }
+ }
+ }
+}}
diff --git a/ad/GOAD/providers/aws/windows.tf b/ad/GOAD/providers/aws/windows.tf
index de4f9904..5f5e79a3 100644
--- a/ad/GOAD/providers/aws/windows.tf
+++ b/ad/GOAD/providers/aws/windows.tf
@@ -1,6 +1,11 @@
# t2.medium = 2cpu / 4GB
# t2.large = 2cpu / 8GB
# t2.xlarge = 4cpu / 16GB
+
+# NOTE: AMI IDs below are region-specific (originally eu-west-1).
+# Replace with AMI IDs for your target AWS region.
+# See: https://aws.amazon.com/marketplace for Windows Server base AMIs
+
"dc01" = {
name = "dc01"
domain = "sevenkingdoms.local"
diff --git a/ad/NHA/providers/aws/windows.tf b/ad/NHA/providers/aws/windows.tf
index 3ced7649..f4143d2d 100644
--- a/ad/NHA/providers/aws/windows.tf
+++ b/ad/NHA/providers/aws/windows.tf
@@ -1,6 +1,11 @@
# t2.medium = 2cpu / 4GB
# t2.large = 2cpu / 8GB
# t2.xlarge = 4cpu / 16GB
+
+# NOTE: AMI IDs below are region-specific (originally eu-west-1).
+# Replace with AMI IDs for your target AWS region.
+# See: https://aws.amazon.com/marketplace for Windows Server base AMIs
+
"dc01" = {
name = "dc01"
domain = "ninja.hack"
diff --git a/ad/SCCM/providers/aws/windows.tf b/ad/SCCM/providers/aws/windows.tf
index bf698f01..6055336f 100644
--- a/ad/SCCM/providers/aws/windows.tf
+++ b/ad/SCCM/providers/aws/windows.tf
@@ -1,6 +1,11 @@
# t2.medium = 2cpu / 4GB
# t2.large = 2cpu / 8GB
# t2.xlarge = 4cpu / 16GB
+
+# NOTE: AMI IDs below are region-specific (originally eu-west-1).
+# Replace with AMI IDs for your target AWS region.
+# See: https://aws.amazon.com/marketplace for Windows Server base AMIs
+
"dc01" = {
name = "dc01"
domain = "sccm.lab"
diff --git a/infra/goad-deployment/host.hcl b/infra/goad-deployment/host.hcl
index ebe22cbe..570dbbce 100644
--- a/infra/goad-deployment/host.hcl
+++ b/infra/goad-deployment/host.hcl
@@ -1,5 +1,5 @@
locals {
- registry_path = "${get_terragrunt_dir()}/../host-registry.yaml"
+ registry_path = find_in_parent_folders("host-registry.yaml")
host_registry = yamldecode(file(local.registry_path))
terragrunt_dir = get_terragrunt_dir()
diff --git a/infra/goad-deployment/staging/env.hcl b/infra/goad-deployment/staging/env.hcl
index a3909311..f89262e7 100644
--- a/infra/goad-deployment/staging/env.hcl
+++ b/infra/goad-deployment/staging/env.hcl
@@ -2,7 +2,7 @@
# This is automatically pulled in by the root terragrunt.hcl configuration.
locals {
deployment_name = "goad" # Change to your deployment name
- aws_account_id = "CHANGE_ME" # Your AWS account ID
+ aws_account_id = get_aws_account_id()
env = "staging" # Environment name (dev, staging, prod)
vpc_cidr = "10.1.0.0/16" # VPC CIDR block for this environment
}
diff --git a/infra/goad-deployment/staging/us-west-1/goad/dc01/terragrunt.hcl b/infra/goad-deployment/staging/us-west-1/goad/dc01/terragrunt.hcl
index f820cd8f..0441a2d8 100644
--- a/infra/goad-deployment/staging/us-west-1/goad/dc01/terragrunt.hcl
+++ b/infra/goad-deployment/staging/us-west-1/goad/dc01/terragrunt.hcl
@@ -24,8 +24,9 @@ locals {
role = include.host.locals.role
goad_id = include.host.locals.goad_id
- # Set admin password via terraform.tfvars or TF_VAR_admin_password env var
- admin_password = get_env("TF_VAR_goad_dc01_password", "CHANGE_ME")
+ # Read admin password from GOAD lab config (single source of truth)
+ lab_config = jsondecode(file("${get_repo_root()}/ad/GOAD/data/${local.env}-config.json"))
+ admin_password = local.lab_config.lab.hosts[local.goad_id].local_admin_password
}
terraform {
@@ -34,6 +35,12 @@ terraform {
dependency "network" {
config_path = "../../network"
+ mock_outputs = {
+ vpc_id = "vpc-mock"
+ vpc_cidr = "10.0.0.0/16"
+ private_subnet_ids = ["subnet-mock"]
+ }
+ mock_outputs_allowed_terraform_commands = ["init", "validate", "plan"]
}
include {
@@ -56,15 +63,15 @@ inputs = {
s3_full_access = "arn:aws:iam::aws:policy/AmazonS3FullAccess"
}
- # Windows AMI - replace with your AMI built from warpgate-templates/goad-dc-base
+ # Windows AMI - uses latest warpgate-built AMI (most_recent = true, owners = ["self"])
windows_os = "Windows_Server"
windows_os_version = "2019-English-Full-Base"
windows_ami_owners = ["self"]
additional_windows_ami_filters = [
{
- name = "image-id"
- values = ["CHANGE_ME"] # Your goad-dc-base AMI ID
+ name = "name"
+ values = ["goad-dc-base-*"] # warpgate-templates/goad-dc-base
}
]
diff --git a/infra/goad-deployment/staging/us-west-1/goad/dc02/terragrunt.hcl b/infra/goad-deployment/staging/us-west-1/goad/dc02/terragrunt.hcl
index e686b854..5c073bbe 100644
--- a/infra/goad-deployment/staging/us-west-1/goad/dc02/terragrunt.hcl
+++ b/infra/goad-deployment/staging/us-west-1/goad/dc02/terragrunt.hcl
@@ -23,7 +23,9 @@ locals {
role = include.host.locals.role
goad_id = include.host.locals.goad_id
- admin_password = get_env("TF_VAR_goad_dc02_password", "CHANGE_ME")
+ # Read admin password from GOAD lab config (single source of truth)
+ lab_config = jsondecode(file("${get_repo_root()}/ad/GOAD/data/${local.env}-config.json"))
+ admin_password = local.lab_config.lab.hosts[local.goad_id].local_admin_password
}
terraform {
@@ -32,6 +34,12 @@ terraform {
dependency "network" {
config_path = "../../network"
+ mock_outputs = {
+ vpc_id = "vpc-mock"
+ vpc_cidr = "10.0.0.0/16"
+ private_subnet_ids = ["subnet-mock"]
+ }
+ mock_outputs_allowed_terraform_commands = ["init", "validate", "plan"]
}
include {
@@ -54,15 +62,15 @@ inputs = {
s3_full_access = "arn:aws:iam::aws:policy/AmazonS3FullAccess"
}
- # Windows AMI - replace with your AMI built from warpgate-templates/goad-dc-base
+ # Windows AMI - uses latest warpgate-built AMI (most_recent = true, owners = ["self"])
windows_os = "Windows_Server"
windows_os_version = "2019-English-Full-Base"
windows_ami_owners = ["self"]
additional_windows_ami_filters = [
{
- name = "image-id"
- values = ["CHANGE_ME"] # Your goad-dc-base AMI ID
+ name = "name"
+ values = ["goad-dc-base-*"] # warpgate-templates/goad-dc-base
}
]
diff --git a/infra/goad-deployment/staging/us-west-1/goad/dc03/terragrunt.hcl b/infra/goad-deployment/staging/us-west-1/goad/dc03/terragrunt.hcl
index 3df4ec51..668f058a 100644
--- a/infra/goad-deployment/staging/us-west-1/goad/dc03/terragrunt.hcl
+++ b/infra/goad-deployment/staging/us-west-1/goad/dc03/terragrunt.hcl
@@ -23,7 +23,9 @@ locals {
role = include.host.locals.role
goad_id = include.host.locals.goad_id
- admin_password = get_env("TF_VAR_goad_dc03_password", "CHANGE_ME")
+ # Read admin password from GOAD lab config (single source of truth)
+ lab_config = jsondecode(file("${get_repo_root()}/ad/GOAD/data/${local.env}-config.json"))
+ admin_password = local.lab_config.lab.hosts[local.goad_id].local_admin_password
}
terraform {
@@ -32,6 +34,12 @@ terraform {
dependency "network" {
config_path = "../../network"
+ mock_outputs = {
+ vpc_id = "vpc-mock"
+ vpc_cidr = "10.0.0.0/16"
+ private_subnet_ids = ["subnet-mock"]
+ }
+ mock_outputs_allowed_terraform_commands = ["init", "validate", "plan"]
}
include {
@@ -54,15 +62,15 @@ inputs = {
s3_full_access = "arn:aws:iam::aws:policy/AmazonS3FullAccess"
}
- # Windows AMI - replace with your AMI built from warpgate-templates/goad-dc-base-2016
+ # Windows AMI - uses latest warpgate-built AMI (most_recent = true, owners = ["self"])
windows_os = "Windows_Server"
windows_os_version = "2016-English-Full-Base"
windows_ami_owners = ["self"]
additional_windows_ami_filters = [
{
- name = "image-id"
- values = ["CHANGE_ME"] # Your goad-dc-base-2016 AMI ID
+ name = "name"
+ values = ["goad-dc-base-2016-*"] # warpgate-templates/goad-dc-base-2016
}
]
diff --git a/infra/goad-deployment/staging/us-west-1/goad/srv02/terragrunt.hcl b/infra/goad-deployment/staging/us-west-1/goad/srv02/terragrunt.hcl
index 46005572..11385662 100644
--- a/infra/goad-deployment/staging/us-west-1/goad/srv02/terragrunt.hcl
+++ b/infra/goad-deployment/staging/us-west-1/goad/srv02/terragrunt.hcl
@@ -23,8 +23,9 @@ locals {
role = include.host.locals.role
goad_id = include.host.locals.goad_id
- # SRV02 uses DC02's password (it joins the north subdomain)
- admin_password = get_env("TF_VAR_goad_dc02_password", "CHANGE_ME")
+ # Read admin password from GOAD lab config (single source of truth)
+ lab_config = jsondecode(file("${get_repo_root()}/ad/GOAD/data/${local.env}-config.json"))
+ admin_password = local.lab_config.lab.hosts[local.goad_id].local_admin_password
}
terraform {
@@ -33,6 +34,12 @@ terraform {
dependency "network" {
config_path = "../../network"
+ mock_outputs = {
+ vpc_id = "vpc-mock"
+ vpc_cidr = "10.0.0.0/16"
+ private_subnet_ids = ["subnet-mock"]
+ }
+ mock_outputs_allowed_terraform_commands = ["init", "validate", "plan"]
}
include {
@@ -55,15 +62,15 @@ inputs = {
s3_full_access = "arn:aws:iam::aws:policy/AmazonS3FullAccess"
}
- # Windows AMI - replace with your AMI built from warpgate-templates/goad-mssql-base
+ # Windows AMI - uses latest warpgate-built AMI (most_recent = true, owners = ["self"])
windows_os = "Windows_Server"
windows_os_version = "2019-English-Full-Base"
windows_ami_owners = ["self"]
additional_windows_ami_filters = [
{
- name = "image-id"
- values = ["CHANGE_ME"] # Your goad-mssql-base AMI ID
+ name = "name"
+ values = ["goad-mssql-base-*"] # warpgate-templates/goad-mssql-base
}
]
diff --git a/infra/goad-deployment/staging/us-west-1/goad/srv03/terragrunt.hcl b/infra/goad-deployment/staging/us-west-1/goad/srv03/terragrunt.hcl
index 339dac88..18a6421a 100644
--- a/infra/goad-deployment/staging/us-west-1/goad/srv03/terragrunt.hcl
+++ b/infra/goad-deployment/staging/us-west-1/goad/srv03/terragrunt.hcl
@@ -23,8 +23,9 @@ locals {
role = include.host.locals.role
goad_id = include.host.locals.goad_id
- # SRV03 uses DC03's password (it joins the essos domain)
- admin_password = get_env("TF_VAR_goad_dc03_password", "CHANGE_ME")
+ # Read admin password from GOAD lab config (single source of truth)
+ lab_config = jsondecode(file("${get_repo_root()}/ad/GOAD/data/${local.env}-config.json"))
+ admin_password = local.lab_config.lab.hosts[local.goad_id].local_admin_password
}
terraform {
@@ -33,6 +34,12 @@ terraform {
dependency "network" {
config_path = "../../network"
+ mock_outputs = {
+ vpc_id = "vpc-mock"
+ vpc_cidr = "10.0.0.0/16"
+ private_subnet_ids = ["subnet-mock"]
+ }
+ mock_outputs_allowed_terraform_commands = ["init", "validate", "plan"]
}
include {
@@ -55,15 +62,15 @@ inputs = {
s3_full_access = "arn:aws:iam::aws:policy/AmazonS3FullAccess"
}
- # Windows AMI - replace with your AMI built from warpgate-templates/goad-member-base-2016
+ # Windows AMI - uses latest warpgate-built AMI (most_recent = true, owners = ["self"])
windows_os = "Windows_Server"
windows_os_version = "2016-English-Full-Base"
windows_ami_owners = ["self"]
additional_windows_ami_filters = [
{
- name = "image-id"
- values = ["CHANGE_ME"] # Your goad-member-base-2016 AMI ID
+ name = "name"
+ values = ["goad-member-base-2016-*"] # warpgate-templates/goad-member-base-2016
}
]
diff --git a/infra/goad-deployment/test/env.hcl b/infra/goad-deployment/test/env.hcl
new file mode 100644
index 00000000..2712a77d
--- /dev/null
+++ b/infra/goad-deployment/test/env.hcl
@@ -0,0 +1,8 @@
+# Set common variables for the test environment.
+# This is automatically pulled in by the root terragrunt.hcl configuration.
+locals {
+ deployment_name = "goad"
+ aws_account_id = get_aws_account_id()
+ env = "test"
+ vpc_cidr = "10.8.0.0/16"
+}
diff --git a/infra/goad-deployment/test/us-east-2/goad/dc01/templates/user_data.ps1.tpl b/infra/goad-deployment/test/us-east-2/goad/dc01/templates/user_data.ps1.tpl
new file mode 100644
index 00000000..bbc0ec7c
--- /dev/null
+++ b/infra/goad-deployment/test/us-east-2/goad/dc01/templates/user_data.ps1.tpl
@@ -0,0 +1,44 @@
+# Add registry keys to enable TLS 1.2 at the OS level
+New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server' -Force | Out-Null
+New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client' -Force | Out-Null
+New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server' -name 'Enabled' -value '1' -PropertyType 'DWord' -Force | Out-Null
+New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server' -name 'DisabledByDefault' -value 0 -PropertyType 'DWord' -Force | Out-Null
+New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client' -name 'Enabled' -value 1 -PropertyType 'DWord' -Force | Out-Null
+New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client' -name 'DisabledByDefault' -value 0 -PropertyType 'DWord' -Force | Out-Null
+
+# Enable strong cryptography on .NET Framework
+Set-ItemProperty -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value 1 -Type DWord -Force
+Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value 1 -Type DWord -Force
+
+# Force TLS 1.2 in current PowerShell session and create system-wide PowerShell profile
+[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
+
+# Create AllSigned profile for all users
+$allUsersAllHosts = "$env:windir\System32\WindowsPowerShell\v1.0\profile.ps1"
+New-Item -Path $allUsersAllHosts -ItemType File -Force | Out-Null
+Set-Content -Path $allUsersAllHosts -Value "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12" -Force
+
+# Set the local Administrator password
+net user Administrator ${admin_password} /expires:never /y
+
+# Create ansible user, add to administrators group, and set password
+net user ansible ${admin_password} /add /expires:never /y
+net localgroup administrators ansible /add
+
+# Setup SSM Agent
+$progressPreference = 'silentlyContinue'
+
+# Use WebClient instead of Invoke-WebRequest for SSM agent download too
+$ssmUrl = "https://amazon-ssm-${aws_region}.s3.amazonaws.com/latest/windows_amd64/AmazonSSMAgentSetup.exe"
+$ssmOutput = "$env:TEMP\SSMAgent_latest.exe"
+$webClient = New-Object System.Net.WebClient
+$webClient.DownloadFile($ssmUrl, $ssmOutput)
+
+# Install SSM agent
+Start-Process -FilePath $env:TEMP\SSMAgent_latest.exe -ArgumentList "/S" -Wait
+Remove-Item -Force $env:TEMP\SSMAgent_latest.exe
+Restart-Service AmazonSSMAgent
+
+# Rename computer and restart
+Rename-Computer -NewName "${hostname}" -Force
+Restart-Computer -Force
diff --git a/infra/goad-deployment/test/us-east-2/goad/dc01/templates/user_data_wrapper.ps1.tpl b/infra/goad-deployment/test/us-east-2/goad/dc01/templates/user_data_wrapper.ps1.tpl
new file mode 100644
index 00000000..4f83016f
--- /dev/null
+++ b/infra/goad-deployment/test/us-east-2/goad/dc01/templates/user_data_wrapper.ps1.tpl
@@ -0,0 +1,5 @@
+
+$EncodedUserData = "${compressed_user_data}"
+$DecodedUserData = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($EncodedUserData))
+Invoke-Expression $DecodedUserData
+
diff --git a/infra/goad-deployment/test/us-east-2/goad/dc01/terragrunt.hcl b/infra/goad-deployment/test/us-east-2/goad/dc01/terragrunt.hcl
new file mode 100644
index 00000000..0441a2d8
--- /dev/null
+++ b/infra/goad-deployment/test/us-east-2/goad/dc01/terragrunt.hcl
@@ -0,0 +1,121 @@
+# =============================================================================
+# DC01 - Primary Domain Controller for Seven Kingdoms
+# AMI: Built from warpgate-templates/goad-dc-base (Windows Server 2019)
+# =============================================================================
+
+include "host" {
+ path = find_in_parent_folders("host.hcl")
+ expose = true
+}
+
+locals {
+ env_vars = read_terragrunt_config(find_in_parent_folders("env.hcl"))
+ region_vars = read_terragrunt_config(find_in_parent_folders("region.hcl"))
+
+ env = local.env_vars.locals.env
+ aws_region = local.region_vars.locals.aws_region
+ deployment_name = local.env_vars.locals.deployment_name
+
+ # Host metadata from host-registry.yaml via host.hcl
+ hostname = include.host.locals.computer_name
+ friendly_name = include.host.locals.hostname
+ domain = include.host.locals.domain
+ os_type = include.host.locals.os_type
+ role = include.host.locals.role
+ goad_id = include.host.locals.goad_id
+
+ # Read admin password from GOAD lab config (single source of truth)
+ lab_config = jsondecode(file("${get_repo_root()}/ad/GOAD/data/${local.env}-config.json"))
+ admin_password = local.lab_config.lab.hosts[local.goad_id].local_admin_password
+}
+
+terraform {
+ source = "${get_repo_root()}/modules//terraform-aws-instance-factory"
+}
+
+dependency "network" {
+ config_path = "../../network"
+ mock_outputs = {
+ vpc_id = "vpc-mock"
+ vpc_cidr = "10.0.0.0/16"
+ private_subnet_ids = ["subnet-mock"]
+ }
+ mock_outputs_allowed_terraform_commands = ["init", "validate", "plan"]
+}
+
+include {
+ path = find_in_parent_folders("root.hcl")
+}
+
+inputs = {
+ env = local.env
+ instance_name = "${local.deployment_name}-dreadgoad-${local.hostname}"
+ instance_type = "t3.medium"
+ os_type = local.os_type
+ enable_asg = false
+ subnet_id = dependency.network.outputs.private_subnet_ids[0]
+ vpc_id = dependency.network.outputs.vpc_id
+
+ enable_ssm = true
+
+ additional_iam_policies = {
+ cloudwatch_agent = "arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy"
+ s3_full_access = "arn:aws:iam::aws:policy/AmazonS3FullAccess"
+ }
+
+ # Windows AMI - uses latest warpgate-built AMI (most_recent = true, owners = ["self"])
+ windows_os = "Windows_Server"
+ windows_os_version = "2019-English-Full-Base"
+ windows_ami_owners = ["self"]
+
+ additional_windows_ami_filters = [
+ {
+ name = "name"
+ values = ["goad-dc-base-*"] # warpgate-templates/goad-dc-base
+ }
+ ]
+
+ ingress_rules = [
+ {
+ description = "Allow all traffic from VPC CIDR"
+ from_port = 0
+ to_port = 0
+ protocol = "-1"
+ cidr_blocks = [dependency.network.outputs.vpc_cidr]
+ },
+ ]
+
+ egress_rules = [
+ {
+ from_port = 0
+ to_port = 0
+ protocol = "-1"
+ cidr_blocks = ["0.0.0.0/0"]
+ }
+ ]
+
+ enable_monitoring = true
+ enable_metadata = true
+ require_imdsv2 = true
+ encrypt_volumes = true
+ root_volume_size = 100
+ volume_type = "gp3"
+
+ user_data = templatefile("${get_terragrunt_dir()}/templates/user_data_wrapper.ps1.tpl", {
+ compressed_user_data = base64encode(templatefile("${get_terragrunt_dir()}/templates/user_data.ps1.tpl", {
+ aws_region = local.aws_region,
+ hostname = local.hostname,
+ admin_password = local.admin_password
+ }))
+ })
+
+ tags = {
+ Environment = local.env
+ Project = "DreadGOAD"
+ Role = "DomainController"
+ Lab = "${local.deployment_name}-goad"
+ Name = "${local.deployment_name}-dreadgoad-${local.hostname}"
+ Domain = local.domain
+ ComputerName = local.hostname
+ }
+}
diff --git a/infra/goad-deployment/test/us-east-2/goad/dc02/templates/user_data.ps1.tpl b/infra/goad-deployment/test/us-east-2/goad/dc02/templates/user_data.ps1.tpl
new file mode 100644
index 00000000..bbc0ec7c
--- /dev/null
+++ b/infra/goad-deployment/test/us-east-2/goad/dc02/templates/user_data.ps1.tpl
@@ -0,0 +1,44 @@
+# Add registry keys to enable TLS 1.2 at the OS level
+New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server' -Force | Out-Null
+New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client' -Force | Out-Null
+New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server' -name 'Enabled' -value '1' -PropertyType 'DWord' -Force | Out-Null
+New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server' -name 'DisabledByDefault' -value 0 -PropertyType 'DWord' -Force | Out-Null
+New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client' -name 'Enabled' -value 1 -PropertyType 'DWord' -Force | Out-Null
+New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client' -name 'DisabledByDefault' -value 0 -PropertyType 'DWord' -Force | Out-Null
+
+# Enable strong cryptography on .NET Framework
+Set-ItemProperty -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value 1 -Type DWord -Force
+Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value 1 -Type DWord -Force
+
+# Force TLS 1.2 in current PowerShell session and create system-wide PowerShell profile
+[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
+
+# Create AllSigned profile for all users
+$allUsersAllHosts = "$env:windir\System32\WindowsPowerShell\v1.0\profile.ps1"
+New-Item -Path $allUsersAllHosts -ItemType File -Force | Out-Null
+Set-Content -Path $allUsersAllHosts -Value "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12" -Force
+
+# Set the local Administrator password
+net user Administrator ${admin_password} /expires:never /y
+
+# Create ansible user, add to administrators group, and set password
+net user ansible ${admin_password} /add /expires:never /y
+net localgroup administrators ansible /add
+
+# Setup SSM Agent
+$progressPreference = 'silentlyContinue'
+
+# Use WebClient instead of Invoke-WebRequest for SSM agent download too
+$ssmUrl = "https://amazon-ssm-${aws_region}.s3.amazonaws.com/latest/windows_amd64/AmazonSSMAgentSetup.exe"
+$ssmOutput = "$env:TEMP\SSMAgent_latest.exe"
+$webClient = New-Object System.Net.WebClient
+$webClient.DownloadFile($ssmUrl, $ssmOutput)
+
+# Install SSM agent
+Start-Process -FilePath $env:TEMP\SSMAgent_latest.exe -ArgumentList "/S" -Wait
+Remove-Item -Force $env:TEMP\SSMAgent_latest.exe
+Restart-Service AmazonSSMAgent
+
+# Rename computer and restart
+Rename-Computer -NewName "${hostname}" -Force
+Restart-Computer -Force
diff --git a/infra/goad-deployment/test/us-east-2/goad/dc02/templates/user_data_wrapper.ps1.tpl b/infra/goad-deployment/test/us-east-2/goad/dc02/templates/user_data_wrapper.ps1.tpl
new file mode 100644
index 00000000..4f83016f
--- /dev/null
+++ b/infra/goad-deployment/test/us-east-2/goad/dc02/templates/user_data_wrapper.ps1.tpl
@@ -0,0 +1,5 @@
+
+$EncodedUserData = "${compressed_user_data}"
+$DecodedUserData = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($EncodedUserData))
+Invoke-Expression $DecodedUserData
+
diff --git a/infra/goad-deployment/test/us-east-2/goad/dc02/terragrunt.hcl b/infra/goad-deployment/test/us-east-2/goad/dc02/terragrunt.hcl
new file mode 100644
index 00000000..5c073bbe
--- /dev/null
+++ b/infra/goad-deployment/test/us-east-2/goad/dc02/terragrunt.hcl
@@ -0,0 +1,120 @@
+# =============================================================================
+# DC02 - Domain Controller for North Subdomain
+# AMI: Built from warpgate-templates/goad-dc-base (Windows Server 2019)
+# =============================================================================
+
+include "host" {
+ path = find_in_parent_folders("host.hcl")
+ expose = true
+}
+
+locals {
+ env_vars = read_terragrunt_config(find_in_parent_folders("env.hcl"))
+ region_vars = read_terragrunt_config(find_in_parent_folders("region.hcl"))
+
+ env = local.env_vars.locals.env
+ aws_region = local.region_vars.locals.aws_region
+ deployment_name = local.env_vars.locals.deployment_name
+
+ hostname = include.host.locals.computer_name
+ friendly_name = include.host.locals.hostname
+ domain = include.host.locals.domain
+ os_type = include.host.locals.os_type
+ role = include.host.locals.role
+ goad_id = include.host.locals.goad_id
+
+ # Read admin password from GOAD lab config (single source of truth)
+ lab_config = jsondecode(file("${get_repo_root()}/ad/GOAD/data/${local.env}-config.json"))
+ admin_password = local.lab_config.lab.hosts[local.goad_id].local_admin_password
+}
+
+terraform {
+ source = "${get_repo_root()}/modules//terraform-aws-instance-factory"
+}
+
+dependency "network" {
+ config_path = "../../network"
+ mock_outputs = {
+ vpc_id = "vpc-mock"
+ vpc_cidr = "10.0.0.0/16"
+ private_subnet_ids = ["subnet-mock"]
+ }
+ mock_outputs_allowed_terraform_commands = ["init", "validate", "plan"]
+}
+
+include {
+ path = find_in_parent_folders("root.hcl")
+}
+
+inputs = {
+ env = local.env
+ instance_name = "${local.deployment_name}-dreadgoad-${local.hostname}"
+ instance_type = "t3.medium"
+ os_type = local.os_type
+ enable_asg = false
+ subnet_id = dependency.network.outputs.private_subnet_ids[0]
+ vpc_id = dependency.network.outputs.vpc_id
+
+ enable_ssm = true
+
+ additional_iam_policies = {
+ cloudwatch_agent = "arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy"
+ s3_full_access = "arn:aws:iam::aws:policy/AmazonS3FullAccess"
+ }
+
+ # Windows AMI - uses latest warpgate-built AMI (most_recent = true, owners = ["self"])
+ windows_os = "Windows_Server"
+ windows_os_version = "2019-English-Full-Base"
+ windows_ami_owners = ["self"]
+
+ additional_windows_ami_filters = [
+ {
+ name = "name"
+ values = ["goad-dc-base-*"] # warpgate-templates/goad-dc-base
+ }
+ ]
+
+ ingress_rules = [
+ {
+ description = "Allow all traffic from VPC CIDR"
+ from_port = 0
+ to_port = 0
+ protocol = "-1"
+ cidr_blocks = [dependency.network.outputs.vpc_cidr]
+ },
+ ]
+
+ egress_rules = [
+ {
+ from_port = 0
+ to_port = 0
+ protocol = "-1"
+ cidr_blocks = ["0.0.0.0/0"]
+ }
+ ]
+
+ enable_monitoring = true
+ enable_metadata = true
+ require_imdsv2 = true
+ encrypt_volumes = true
+ root_volume_size = 100
+ volume_type = "gp3"
+
+ user_data = templatefile("${get_terragrunt_dir()}/templates/user_data_wrapper.ps1.tpl", {
+ compressed_user_data = base64encode(templatefile("${get_terragrunt_dir()}/templates/user_data.ps1.tpl", {
+ aws_region = local.aws_region,
+ hostname = local.hostname,
+ admin_password = local.admin_password
+ }))
+ })
+
+ tags = {
+ Environment = local.env
+ Project = "DreadGOAD"
+ Role = "DomainController"
+ Lab = "${local.deployment_name}-goad"
+ Name = "${local.deployment_name}-dreadgoad-${local.hostname}"
+ Domain = local.domain
+ ComputerName = local.hostname
+ }
+}
diff --git a/infra/goad-deployment/test/us-east-2/goad/dc03/templates/user_data.ps1.tpl b/infra/goad-deployment/test/us-east-2/goad/dc03/templates/user_data.ps1.tpl
new file mode 100644
index 00000000..bbc0ec7c
--- /dev/null
+++ b/infra/goad-deployment/test/us-east-2/goad/dc03/templates/user_data.ps1.tpl
@@ -0,0 +1,44 @@
+# Add registry keys to enable TLS 1.2 at the OS level
+New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server' -Force | Out-Null
+New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client' -Force | Out-Null
+New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server' -name 'Enabled' -value '1' -PropertyType 'DWord' -Force | Out-Null
+New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server' -name 'DisabledByDefault' -value 0 -PropertyType 'DWord' -Force | Out-Null
+New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client' -name 'Enabled' -value 1 -PropertyType 'DWord' -Force | Out-Null
+New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client' -name 'DisabledByDefault' -value 0 -PropertyType 'DWord' -Force | Out-Null
+
+# Enable strong cryptography on .NET Framework
+Set-ItemProperty -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value 1 -Type DWord -Force
+Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value 1 -Type DWord -Force
+
+# Force TLS 1.2 in current PowerShell session and create system-wide PowerShell profile
+[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
+
+# Create AllSigned profile for all users
+$allUsersAllHosts = "$env:windir\System32\WindowsPowerShell\v1.0\profile.ps1"
+New-Item -Path $allUsersAllHosts -ItemType File -Force | Out-Null
+Set-Content -Path $allUsersAllHosts -Value "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12" -Force
+
+# Set the local Administrator password
+net user Administrator ${admin_password} /expires:never /y
+
+# Create ansible user, add to administrators group, and set password
+net user ansible ${admin_password} /add /expires:never /y
+net localgroup administrators ansible /add
+
+# Setup SSM Agent
+$progressPreference = 'silentlyContinue'
+
+# Use WebClient instead of Invoke-WebRequest for SSM agent download too
+$ssmUrl = "https://amazon-ssm-${aws_region}.s3.amazonaws.com/latest/windows_amd64/AmazonSSMAgentSetup.exe"
+$ssmOutput = "$env:TEMP\SSMAgent_latest.exe"
+$webClient = New-Object System.Net.WebClient
+$webClient.DownloadFile($ssmUrl, $ssmOutput)
+
+# Install SSM agent
+Start-Process -FilePath $env:TEMP\SSMAgent_latest.exe -ArgumentList "/S" -Wait
+Remove-Item -Force $env:TEMP\SSMAgent_latest.exe
+Restart-Service AmazonSSMAgent
+
+# Rename computer and restart
+Rename-Computer -NewName "${hostname}" -Force
+Restart-Computer -Force
diff --git a/infra/goad-deployment/test/us-east-2/goad/dc03/templates/user_data_wrapper.ps1.tpl b/infra/goad-deployment/test/us-east-2/goad/dc03/templates/user_data_wrapper.ps1.tpl
new file mode 100644
index 00000000..4f83016f
--- /dev/null
+++ b/infra/goad-deployment/test/us-east-2/goad/dc03/templates/user_data_wrapper.ps1.tpl
@@ -0,0 +1,5 @@
+
+$EncodedUserData = "${compressed_user_data}"
+$DecodedUserData = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($EncodedUserData))
+Invoke-Expression $DecodedUserData
+
diff --git a/infra/goad-deployment/test/us-east-2/goad/dc03/terragrunt.hcl b/infra/goad-deployment/test/us-east-2/goad/dc03/terragrunt.hcl
new file mode 100644
index 00000000..668f058a
--- /dev/null
+++ b/infra/goad-deployment/test/us-east-2/goad/dc03/terragrunt.hcl
@@ -0,0 +1,120 @@
+# =============================================================================
+# DC03 - Domain Controller for Essos
+# AMI: Built from warpgate-templates/goad-dc-base-2016 (Windows Server 2016)
+# =============================================================================
+
+include "host" {
+ path = find_in_parent_folders("host.hcl")
+ expose = true
+}
+
+locals {
+ env_vars = read_terragrunt_config(find_in_parent_folders("env.hcl"))
+ region_vars = read_terragrunt_config(find_in_parent_folders("region.hcl"))
+
+ env = local.env_vars.locals.env
+ aws_region = local.region_vars.locals.aws_region
+ deployment_name = local.env_vars.locals.deployment_name
+
+ hostname = include.host.locals.computer_name
+ friendly_name = include.host.locals.hostname
+ domain = include.host.locals.domain
+ os_type = include.host.locals.os_type
+ role = include.host.locals.role
+ goad_id = include.host.locals.goad_id
+
+ # Read admin password from GOAD lab config (single source of truth)
+ lab_config = jsondecode(file("${get_repo_root()}/ad/GOAD/data/${local.env}-config.json"))
+ admin_password = local.lab_config.lab.hosts[local.goad_id].local_admin_password
+}
+
+terraform {
+ source = "${get_repo_root()}/modules//terraform-aws-instance-factory"
+}
+
+dependency "network" {
+ config_path = "../../network"
+ mock_outputs = {
+ vpc_id = "vpc-mock"
+ vpc_cidr = "10.0.0.0/16"
+ private_subnet_ids = ["subnet-mock"]
+ }
+ mock_outputs_allowed_terraform_commands = ["init", "validate", "plan"]
+}
+
+include {
+ path = find_in_parent_folders("root.hcl")
+}
+
+inputs = {
+ env = local.env
+ instance_name = "${local.deployment_name}-dreadgoad-${local.hostname}"
+ instance_type = "t3.medium"
+ os_type = local.os_type
+ enable_asg = false
+ subnet_id = dependency.network.outputs.private_subnet_ids[0]
+ vpc_id = dependency.network.outputs.vpc_id
+
+ enable_ssm = true
+
+ additional_iam_policies = {
+ cloudwatch_agent = "arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy"
+ s3_full_access = "arn:aws:iam::aws:policy/AmazonS3FullAccess"
+ }
+
+ # Windows AMI - uses latest warpgate-built AMI (most_recent = true, owners = ["self"])
+ windows_os = "Windows_Server"
+ windows_os_version = "2016-English-Full-Base"
+ windows_ami_owners = ["self"]
+
+ additional_windows_ami_filters = [
+ {
+ name = "name"
+ values = ["goad-dc-base-2016-*"] # warpgate-templates/goad-dc-base-2016
+ }
+ ]
+
+ ingress_rules = [
+ {
+ description = "Allow all traffic from VPC CIDR"
+ from_port = 0
+ to_port = 0
+ protocol = "-1"
+ cidr_blocks = [dependency.network.outputs.vpc_cidr]
+ },
+ ]
+
+ egress_rules = [
+ {
+ from_port = 0
+ to_port = 0
+ protocol = "-1"
+ cidr_blocks = ["0.0.0.0/0"]
+ }
+ ]
+
+ enable_monitoring = true
+ enable_metadata = true
+ require_imdsv2 = true
+ encrypt_volumes = true
+ root_volume_size = 100
+ volume_type = "gp3"
+
+ user_data = templatefile("${get_terragrunt_dir()}/templates/user_data_wrapper.ps1.tpl", {
+ compressed_user_data = base64encode(templatefile("${get_terragrunt_dir()}/templates/user_data.ps1.tpl", {
+ aws_region = local.aws_region,
+ hostname = local.hostname,
+ admin_password = local.admin_password
+ }))
+ })
+
+ tags = {
+ Environment = local.env
+ Project = "DreadGOAD"
+ Role = "DomainController"
+ Lab = "${local.deployment_name}-goad"
+ Name = "${local.deployment_name}-dreadgoad-${local.hostname}"
+ Domain = local.domain
+ ComputerName = local.hostname
+ }
+}
diff --git a/infra/goad-deployment/test/us-east-2/goad/srv02/templates/user_data.ps1.tpl b/infra/goad-deployment/test/us-east-2/goad/srv02/templates/user_data.ps1.tpl
new file mode 100644
index 00000000..bbc0ec7c
--- /dev/null
+++ b/infra/goad-deployment/test/us-east-2/goad/srv02/templates/user_data.ps1.tpl
@@ -0,0 +1,44 @@
+# Add registry keys to enable TLS 1.2 at the OS level
+New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server' -Force | Out-Null
+New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client' -Force | Out-Null
+New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server' -name 'Enabled' -value '1' -PropertyType 'DWord' -Force | Out-Null
+New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server' -name 'DisabledByDefault' -value 0 -PropertyType 'DWord' -Force | Out-Null
+New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client' -name 'Enabled' -value 1 -PropertyType 'DWord' -Force | Out-Null
+New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client' -name 'DisabledByDefault' -value 0 -PropertyType 'DWord' -Force | Out-Null
+
+# Enable strong cryptography on .NET Framework
+Set-ItemProperty -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value 1 -Type DWord -Force
+Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value 1 -Type DWord -Force
+
+# Force TLS 1.2 in current PowerShell session and create system-wide PowerShell profile
+[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
+
+# Create AllSigned profile for all users
+$allUsersAllHosts = "$env:windir\System32\WindowsPowerShell\v1.0\profile.ps1"
+New-Item -Path $allUsersAllHosts -ItemType File -Force | Out-Null
+Set-Content -Path $allUsersAllHosts -Value "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12" -Force
+
+# Set the local Administrator password
+net user Administrator ${admin_password} /expires:never /y
+
+# Create ansible user, add to administrators group, and set password
+net user ansible ${admin_password} /add /expires:never /y
+net localgroup administrators ansible /add
+
+# Setup SSM Agent
+$progressPreference = 'silentlyContinue'
+
+# Use WebClient instead of Invoke-WebRequest for SSM agent download too
+$ssmUrl = "https://amazon-ssm-${aws_region}.s3.amazonaws.com/latest/windows_amd64/AmazonSSMAgentSetup.exe"
+$ssmOutput = "$env:TEMP\SSMAgent_latest.exe"
+$webClient = New-Object System.Net.WebClient
+$webClient.DownloadFile($ssmUrl, $ssmOutput)
+
+# Install SSM agent
+Start-Process -FilePath $env:TEMP\SSMAgent_latest.exe -ArgumentList "/S" -Wait
+Remove-Item -Force $env:TEMP\SSMAgent_latest.exe
+Restart-Service AmazonSSMAgent
+
+# Rename computer and restart
+Rename-Computer -NewName "${hostname}" -Force
+Restart-Computer -Force
diff --git a/infra/goad-deployment/test/us-east-2/goad/srv02/templates/user_data_wrapper.ps1.tpl b/infra/goad-deployment/test/us-east-2/goad/srv02/templates/user_data_wrapper.ps1.tpl
new file mode 100644
index 00000000..4f83016f
--- /dev/null
+++ b/infra/goad-deployment/test/us-east-2/goad/srv02/templates/user_data_wrapper.ps1.tpl
@@ -0,0 +1,5 @@
+
+$EncodedUserData = "${compressed_user_data}"
+$DecodedUserData = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($EncodedUserData))
+Invoke-Expression $DecodedUserData
+
diff --git a/infra/goad-deployment/test/us-east-2/goad/srv02/terragrunt.hcl b/infra/goad-deployment/test/us-east-2/goad/srv02/terragrunt.hcl
new file mode 100644
index 00000000..11385662
--- /dev/null
+++ b/infra/goad-deployment/test/us-east-2/goad/srv02/terragrunt.hcl
@@ -0,0 +1,120 @@
+# =============================================================================
+# SRV02 - Member Server in North Subdomain (MSSQL)
+# AMI: Built from warpgate-templates/goad-mssql-base (Windows Server 2019)
+# =============================================================================
+
+include "host" {
+ path = find_in_parent_folders("host.hcl")
+ expose = true
+}
+
+locals {
+ env_vars = read_terragrunt_config(find_in_parent_folders("env.hcl"))
+ region_vars = read_terragrunt_config(find_in_parent_folders("region.hcl"))
+
+ env = local.env_vars.locals.env
+ aws_region = local.region_vars.locals.aws_region
+ deployment_name = local.env_vars.locals.deployment_name
+
+ hostname = include.host.locals.computer_name
+ friendly_name = include.host.locals.hostname
+ domain = include.host.locals.domain
+ os_type = include.host.locals.os_type
+ role = include.host.locals.role
+ goad_id = include.host.locals.goad_id
+
+ # Read admin password from GOAD lab config (single source of truth)
+ lab_config = jsondecode(file("${get_repo_root()}/ad/GOAD/data/${local.env}-config.json"))
+ admin_password = local.lab_config.lab.hosts[local.goad_id].local_admin_password
+}
+
+terraform {
+ source = "${get_repo_root()}/modules//terraform-aws-instance-factory"
+}
+
+dependency "network" {
+ config_path = "../../network"
+ mock_outputs = {
+ vpc_id = "vpc-mock"
+ vpc_cidr = "10.0.0.0/16"
+ private_subnet_ids = ["subnet-mock"]
+ }
+ mock_outputs_allowed_terraform_commands = ["init", "validate", "plan"]
+}
+
+include {
+ path = find_in_parent_folders("root.hcl")
+}
+
+inputs = {
+ env = local.env
+ instance_name = "${local.deployment_name}-dreadgoad-${local.hostname}"
+ instance_type = "t3.medium"
+ os_type = local.os_type
+ enable_asg = false
+ subnet_id = dependency.network.outputs.private_subnet_ids[0]
+ vpc_id = dependency.network.outputs.vpc_id
+
+ enable_ssm = true
+
+ additional_iam_policies = {
+ cloudwatch_agent = "arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy"
+ s3_full_access = "arn:aws:iam::aws:policy/AmazonS3FullAccess"
+ }
+
+ # Windows AMI - uses latest warpgate-built AMI (most_recent = true, owners = ["self"])
+ windows_os = "Windows_Server"
+ windows_os_version = "2019-English-Full-Base"
+ windows_ami_owners = ["self"]
+
+ additional_windows_ami_filters = [
+ {
+ name = "name"
+ values = ["goad-mssql-base-*"] # warpgate-templates/goad-mssql-base
+ }
+ ]
+
+ ingress_rules = [
+ {
+ description = "Allow all traffic from VPC CIDR"
+ from_port = 0
+ to_port = 0
+ protocol = "-1"
+ cidr_blocks = [dependency.network.outputs.vpc_cidr]
+ },
+ ]
+
+ egress_rules = [
+ {
+ from_port = 0
+ to_port = 0
+ protocol = "-1"
+ cidr_blocks = ["0.0.0.0/0"]
+ }
+ ]
+
+ enable_monitoring = true
+ enable_metadata = true
+ require_imdsv2 = true
+ encrypt_volumes = true
+ root_volume_size = 100
+ volume_type = "gp3"
+
+ user_data = templatefile("${get_terragrunt_dir()}/templates/user_data_wrapper.ps1.tpl", {
+ compressed_user_data = base64encode(templatefile("${get_terragrunt_dir()}/templates/user_data.ps1.tpl", {
+ aws_region = local.aws_region,
+ hostname = local.hostname,
+ admin_password = local.admin_password
+ }))
+ })
+
+ tags = {
+ Environment = local.env
+ Project = "DreadGOAD"
+ Role = "MemberServer"
+ Lab = "${local.deployment_name}-goad"
+ Name = "${local.deployment_name}-dreadgoad-${local.hostname}"
+ Domain = local.domain
+ ComputerName = local.hostname
+ }
+}
diff --git a/infra/goad-deployment/test/us-east-2/goad/srv03/templates/user_data.ps1.tpl b/infra/goad-deployment/test/us-east-2/goad/srv03/templates/user_data.ps1.tpl
new file mode 100644
index 00000000..bbc0ec7c
--- /dev/null
+++ b/infra/goad-deployment/test/us-east-2/goad/srv03/templates/user_data.ps1.tpl
@@ -0,0 +1,44 @@
+# Add registry keys to enable TLS 1.2 at the OS level
+New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server' -Force | Out-Null
+New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client' -Force | Out-Null
+New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server' -name 'Enabled' -value '1' -PropertyType 'DWord' -Force | Out-Null
+New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server' -name 'DisabledByDefault' -value 0 -PropertyType 'DWord' -Force | Out-Null
+New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client' -name 'Enabled' -value 1 -PropertyType 'DWord' -Force | Out-Null
+New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client' -name 'DisabledByDefault' -value 0 -PropertyType 'DWord' -Force | Out-Null
+
+# Enable strong cryptography on .NET Framework
+Set-ItemProperty -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value 1 -Type DWord -Force
+Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value 1 -Type DWord -Force
+
+# Force TLS 1.2 in current PowerShell session and create system-wide PowerShell profile
+[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
+
+# Create AllSigned profile for all users
+$allUsersAllHosts = "$env:windir\System32\WindowsPowerShell\v1.0\profile.ps1"
+New-Item -Path $allUsersAllHosts -ItemType File -Force | Out-Null
+Set-Content -Path $allUsersAllHosts -Value "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12" -Force
+
+# Set the local Administrator password
+net user Administrator ${admin_password} /expires:never /y
+
+# Create ansible user, add to administrators group, and set password
+net user ansible ${admin_password} /add /expires:never /y
+net localgroup administrators ansible /add
+
+# Setup SSM Agent
+$progressPreference = 'silentlyContinue'
+
+# Use WebClient instead of Invoke-WebRequest for SSM agent download too
+$ssmUrl = "https://amazon-ssm-${aws_region}.s3.amazonaws.com/latest/windows_amd64/AmazonSSMAgentSetup.exe"
+$ssmOutput = "$env:TEMP\SSMAgent_latest.exe"
+$webClient = New-Object System.Net.WebClient
+$webClient.DownloadFile($ssmUrl, $ssmOutput)
+
+# Install SSM agent
+Start-Process -FilePath $env:TEMP\SSMAgent_latest.exe -ArgumentList "/S" -Wait
+Remove-Item -Force $env:TEMP\SSMAgent_latest.exe
+Restart-Service AmazonSSMAgent
+
+# Rename computer and restart
+Rename-Computer -NewName "${hostname}" -Force
+Restart-Computer -Force
diff --git a/infra/goad-deployment/test/us-east-2/goad/srv03/templates/user_data_wrapper.ps1.tpl b/infra/goad-deployment/test/us-east-2/goad/srv03/templates/user_data_wrapper.ps1.tpl
new file mode 100644
index 00000000..4f83016f
--- /dev/null
+++ b/infra/goad-deployment/test/us-east-2/goad/srv03/templates/user_data_wrapper.ps1.tpl
@@ -0,0 +1,5 @@
+
+$EncodedUserData = "${compressed_user_data}"
+$DecodedUserData = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($EncodedUserData))
+Invoke-Expression $DecodedUserData
+
diff --git a/infra/goad-deployment/test/us-east-2/goad/srv03/terragrunt.hcl b/infra/goad-deployment/test/us-east-2/goad/srv03/terragrunt.hcl
new file mode 100644
index 00000000..18a6421a
--- /dev/null
+++ b/infra/goad-deployment/test/us-east-2/goad/srv03/terragrunt.hcl
@@ -0,0 +1,120 @@
+# =============================================================================
+# SRV03 - Member Server in Essos Domain
+# AMI: Built from warpgate-templates/goad-member-base-2016 (Windows Server 2016)
+# =============================================================================
+
+include "host" {
+ path = find_in_parent_folders("host.hcl")
+ expose = true
+}
+
+locals {
+ env_vars = read_terragrunt_config(find_in_parent_folders("env.hcl"))
+ region_vars = read_terragrunt_config(find_in_parent_folders("region.hcl"))
+
+ env = local.env_vars.locals.env
+ aws_region = local.region_vars.locals.aws_region
+ deployment_name = local.env_vars.locals.deployment_name
+
+ hostname = include.host.locals.computer_name
+ friendly_name = include.host.locals.hostname
+ domain = include.host.locals.domain
+ os_type = include.host.locals.os_type
+ role = include.host.locals.role
+ goad_id = include.host.locals.goad_id
+
+ # Read admin password from GOAD lab config (single source of truth)
+ lab_config = jsondecode(file("${get_repo_root()}/ad/GOAD/data/${local.env}-config.json"))
+ admin_password = local.lab_config.lab.hosts[local.goad_id].local_admin_password
+}
+
+terraform {
+ source = "${get_repo_root()}/modules//terraform-aws-instance-factory"
+}
+
+dependency "network" {
+ config_path = "../../network"
+ mock_outputs = {
+ vpc_id = "vpc-mock"
+ vpc_cidr = "10.0.0.0/16"
+ private_subnet_ids = ["subnet-mock"]
+ }
+ mock_outputs_allowed_terraform_commands = ["init", "validate", "plan"]
+}
+
+include {
+ path = find_in_parent_folders("root.hcl")
+}
+
+inputs = {
+ env = local.env
+ instance_name = "${local.deployment_name}-dreadgoad-${local.hostname}"
+ instance_type = "t3.medium"
+ os_type = local.os_type
+ enable_asg = false
+ subnet_id = dependency.network.outputs.private_subnet_ids[0]
+ vpc_id = dependency.network.outputs.vpc_id
+
+ enable_ssm = true
+
+ additional_iam_policies = {
+ cloudwatch_agent = "arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy"
+ s3_full_access = "arn:aws:iam::aws:policy/AmazonS3FullAccess"
+ }
+
+ # Windows AMI - uses latest warpgate-built AMI (most_recent = true, owners = ["self"])
+ windows_os = "Windows_Server"
+ windows_os_version = "2016-English-Full-Base"
+ windows_ami_owners = ["self"]
+
+ additional_windows_ami_filters = [
+ {
+ name = "name"
+ values = ["goad-member-base-2016-*"] # warpgate-templates/goad-member-base-2016
+ }
+ ]
+
+ ingress_rules = [
+ {
+ description = "Allow all traffic from VPC CIDR"
+ from_port = 0
+ to_port = 0
+ protocol = "-1"
+ cidr_blocks = [dependency.network.outputs.vpc_cidr]
+ },
+ ]
+
+ egress_rules = [
+ {
+ from_port = 0
+ to_port = 0
+ protocol = "-1"
+ cidr_blocks = ["0.0.0.0/0"]
+ }
+ ]
+
+ enable_monitoring = true
+ enable_metadata = true
+ require_imdsv2 = true
+ encrypt_volumes = true
+ root_volume_size = 100
+ volume_type = "gp3"
+
+ user_data = templatefile("${get_terragrunt_dir()}/templates/user_data_wrapper.ps1.tpl", {
+ compressed_user_data = base64encode(templatefile("${get_terragrunt_dir()}/templates/user_data.ps1.tpl", {
+ aws_region = local.aws_region,
+ hostname = local.hostname,
+ admin_password = local.admin_password
+ }))
+ })
+
+ tags = {
+ Environment = local.env
+ Project = "DreadGOAD"
+ Role = "MemberServer"
+ Lab = "${local.deployment_name}-goad"
+ Name = "${local.deployment_name}-dreadgoad-${local.hostname}"
+ Domain = local.domain
+ ComputerName = local.hostname
+ }
+}
diff --git a/infra/goad-deployment/test/us-east-2/network/terragrunt.hcl b/infra/goad-deployment/test/us-east-2/network/terragrunt.hcl
new file mode 100644
index 00000000..43a8c989
--- /dev/null
+++ b/infra/goad-deployment/test/us-east-2/network/terragrunt.hcl
@@ -0,0 +1,57 @@
+locals {
+ env_vars = read_terragrunt_config(find_in_parent_folders("env.hcl"))
+ region_vars = read_terragrunt_config(find_in_parent_folders("region.hcl"))
+
+ env = local.env_vars.locals.env
+ aws_region = local.region_vars.locals.aws_region
+ deployment_name = local.env_vars.locals.deployment_name
+ vpc_cidr = local.env_vars.locals.vpc_cidr
+}
+
+terraform {
+ source = "${get_repo_root()}/modules//terraform-aws-net"
+}
+
+include {
+ path = find_in_parent_folders("root.hcl")
+}
+
+inputs = {
+ additional_tags = {
+ Project = "DreadGOAD"
+ Environment = local.env
+ }
+ deployment_name = local.deployment_name
+ env = local.env
+ map_public_ip = true
+ vpc_cidr_block = local.vpc_cidr
+
+ # Security group rules for VPC endpoints
+ vpce_security_group_rules = {
+ ingress_cidr_blocks = [local.vpc_cidr]
+ egress_cidr_blocks = ["0.0.0.0/0"]
+ }
+
+ # VPC endpoints required for SSM-based instance management
+ vpc_endpoints = {
+ ssm = {
+ service = "ssm"
+ type = "Interface"
+ private_dns = true
+ }
+ ssmmessages = {
+ service = "ssmmessages"
+ type = "Interface"
+ private_dns = true
+ }
+ ec2messages = {
+ service = "ec2messages"
+ type = "Interface"
+ private_dns = true
+ }
+ s3 = {
+ service = "s3"
+ type = "Gateway"
+ }
+ }
+}
diff --git a/infra/goad-deployment/test/us-east-2/region.hcl b/infra/goad-deployment/test/us-east-2/region.hcl
new file mode 100644
index 00000000..d788ddf7
--- /dev/null
+++ b/infra/goad-deployment/test/us-east-2/region.hcl
@@ -0,0 +1,3 @@
+locals {
+ aws_region = "us-east-2"
+}