Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions cli/cmd/env_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,15 @@ func createAzureEnvHCL(envDir, envName, vnetCIDR string) error {
env = %q
vnet_cidr = %q

# DC02 runs the recurring attack-simulation tasks and needs additional memory.
goad_instance_sizes = {
dc01 = "Standard_D2s_v3"
dc02 = "Standard_D4s_v3"
dc03 = "Standard_D2s_v3"
srv02 = "Standard_D2s_v3"
srv03 = "Standard_D2s_v3"
}

bastion_sku = "Standard"
bastion_subnet_cidr = %q
bastion_tunneling_enabled = true
Expand Down
36 changes: 35 additions & 1 deletion cli/cmd/env_cmd_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package cmd

import "testing"
import (
"os"
"path/filepath"
"strings"
"testing"
)

func TestDeriveAzureSubnets(t *testing.T) {
tests := []struct {
Expand Down Expand Up @@ -36,3 +41,32 @@ func TestDeriveAzureSubnets(t *testing.T) {
})
}
}

func TestCreateAzureEnvHCLSetsGOADInstanceSizes(t *testing.T) {
envDir := t.TempDir()
if err := createAzureEnvHCL(envDir, "memory-test", "10.8.0.0/16"); err != nil {
t.Fatalf("createAzureEnvHCL() error = %v", err)
}

content, err := os.ReadFile(filepath.Join(envDir, "env.hcl"))
if err != nil {
t.Fatalf("read env.hcl: %v", err)
}

for _, want := range []string{
`goad_instance_sizes = {`,
`dc01 = "Standard_D2s_v3"`,
`dc02 = "Standard_D4s_v3"`,
`dc03 = "Standard_D2s_v3"`,
`srv02 = "Standard_D2s_v3"`,
`srv03 = "Standard_D2s_v3"`,
} {
if !strings.Contains(string(content), want) {
t.Errorf("env.hcl missing %q", want)
}
}

if got := strings.Count(string(content), `"Standard_D4s_v3"`); got != 1 {
t.Errorf("D4s_v3 count = %d, want 1", got)
}
}
21 changes: 21 additions & 0 deletions docs/mkdocs/docs/providers/azure.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,27 @@ env: test
!!! warning "Subscription capacity"
The Dreadnode MSFT Startup subscription has tight quota limits in `eastus`. Default to `centralus` unless you know the target region has capacity.

### GOAD VM sizes

Azure environment configuration supports a `goad_instance_sizes` map in `env.hcl`.
DC02 defaults to `Standard_D4s_v3` because it runs the recurring attack-simulation
tasks; the other GOAD hosts default to `Standard_D2s_v3`.

```hcl
goad_instance_sizes = {
dc01 = "Standard_D2s_v3"
dc02 = "Standard_D4s_v3"
dc03 = "Standard_D2s_v3"
srv02 = "Standard_D2s_v3"
srv03 = "Standard_D2s_v3"
}
```

New environments include and consume these defaults automatically. Environments
created before this setting was introduced still have a hard-coded size in each host
configuration. Before the next apply, set `instance_size = "Standard_D4s_v3"` in the
existing environment's `dc02/terragrunt.hcl` so Terraform retains the larger VM size.


## Installation

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ locals {

hostname = include.host.locals.computer_name
goad_id = include.host.locals.goad_id
instance_size = try(
local.env_vars.locals.goad_instance_sizes[local.goad_id],
"Standard_D2s_v3",
)

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
Expand Down Expand Up @@ -45,7 +49,7 @@ inputs = {
env = local.env
instance_name = "${local.deployment_name}-dreadgoad-${local.hostname}"
computer_name = local.hostname
instance_size = "Standard_D2s_v3"
instance_size = local.instance_size
source_image = {
publisher = "MicrosoftWindowsServer"
offer = "WindowsServer"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ locals {

hostname = include.host.locals.computer_name
goad_id = include.host.locals.goad_id
instance_size = try(
local.env_vars.locals.goad_instance_sizes[local.goad_id],
"Standard_D2s_v3",
)

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
Expand Down Expand Up @@ -45,7 +49,7 @@ inputs = {
env = local.env
instance_name = "${local.deployment_name}-dreadgoad-${local.hostname}"
computer_name = local.hostname
instance_size = "Standard_D2s_v3"
instance_size = local.instance_size
source_image = {
publisher = "MicrosoftWindowsServer"
offer = "WindowsServer"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ locals {

hostname = include.host.locals.computer_name
goad_id = include.host.locals.goad_id
instance_size = try(
local.env_vars.locals.goad_instance_sizes[local.goad_id],
"Standard_D2s_v3",
)

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
Expand Down Expand Up @@ -45,7 +49,7 @@ inputs = {
env = local.env
instance_name = "${local.deployment_name}-dreadgoad-${local.hostname}"
computer_name = local.hostname
instance_size = "Standard_D2s_v3"
instance_size = local.instance_size
source_image = {
publisher = "MicrosoftWindowsServer"
offer = "WindowsServer"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ locals {

hostname = include.host.locals.computer_name
goad_id = include.host.locals.goad_id
instance_size = try(
local.env_vars.locals.goad_instance_sizes[local.goad_id],
"Standard_D2s_v3",
)

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
Expand Down Expand Up @@ -45,7 +49,7 @@ inputs = {
env = local.env
instance_name = "${local.deployment_name}-dreadgoad-${local.hostname}"
computer_name = local.hostname
instance_size = "Standard_D2s_v3"
instance_size = local.instance_size
source_image = {
publisher = "MicrosoftWindowsServer"
offer = "WindowsServer"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ locals {

hostname = include.host.locals.computer_name
goad_id = include.host.locals.goad_id
instance_size = try(
local.env_vars.locals.goad_instance_sizes[local.goad_id],
"Standard_D2s_v3",
)

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
Expand Down Expand Up @@ -45,7 +49,7 @@ inputs = {
env = local.env
instance_name = "${local.deployment_name}-dreadgoad-${local.hostname}"
computer_name = local.hostname
instance_size = "Standard_D2s_v3"
instance_size = local.instance_size
source_image = {
publisher = "MicrosoftWindowsServer"
offer = "WindowsServer"
Expand Down
9 changes: 9 additions & 0 deletions infra/azure/goad-deployment/test/env.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@ locals {
env = "test"
vnet_cidr = "10.8.0.0/16"

# DC02 runs the recurring attack-simulation tasks and needs additional memory.
goad_instance_sizes = {
dc01 = "Standard_D2s_v3"
dc02 = "Standard_D4s_v3"
dc03 = "Standard_D2s_v3"
srv02 = "Standard_D2s_v3"
srv03 = "Standard_D2s_v3"
}

bastion_sku = "Standard"
bastion_subnet_cidr = "10.8.2.0/26"
bastion_tunneling_enabled = true
Expand Down
Loading