Variant generator fixes + Azure provisioning support#344
Merged
Conversation
…ogic Extensionless files (e.g., inventory_disable_vagrant) were silently copied without text replacement. File paths containing entity names were not renamed on disk, causing deployment failures. Group names in compound strings (e.g., StarkWallpaper) were missed due to overly aggressive word-boundary matching. Firstname collisions in the Misc map caused silent overwrites and stale mapping.json entries. Single-name users (drogon, missandei, hodor) were incorrectly mapped to firstname.lastname format. Underscore-delimited ACL keys in overlay files were not transformed because Go's \b treats _ as a word character. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…isTextFile When a group name collides with a capitalized surname (e.g., "Targaryen" is both an AD group and a surname from daenerys.targaryen), the Misc entry is now removed in favor of the Groups mapping. This prevents mapping.json from showing a stale surname-derived value while the config uses the group-derived value. Also changed isTextFile to read only the first 8 KiB instead of the entire file. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The previous reconciliation removed any Misc entry matching a group name, which could incorrectly delete hostname or city mappings if they happened to collide. Now only removes entries tracked as name components (firstname/surname), preserving other Misc entries. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
These firstnames collide with the originalNames validation list (from robert.baratheon and brandon.stark), causing false positive validation warnings when the generator randomly picks them. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove []{} from the password special character pool. These can produce
Jinja2 template sequences ({#, {{, {%}) that cause Ansible to crash
with "Missing end of comment tag" errors when passwords are embedded
in playbook templates.
Co-Authored-By: Claude <noreply@anthropic.com>
Inventory bootstrapping hardcoded labName to "GOAD", ignoring active variants. Now resolves to the variant target directory (e.g. GOAD-dreadindex) when a variant is configured. Azure inventory templates were missing all Ansible group definitions ([dc], [domain], [server], [trust], [adcs], etc.) and required [all:vars] (domain_name, force_dns_server, dns_server_forwarder, etc.). Without these groups, playbooks silently skipped tasks or failed with undefined variable errors. Also fixes admin_user from "goadmin" to "administrator" — the Azure bootstrap script renames the SID-500 account to "administrator". Updated templates for all 6 labs: GOAD, GOAD-Light, GOAD-Mini, NHA, DRACARYS, SCCM. Co-Authored-By: Claude <noreply@anthropic.com>
… provider-aware Azure provisioning via Bastion+controller uses WinRM/PSRP, which requires the pypsrp Python package. Add the existing pypsrp check to runAzureChecks() so users get a clear doctor message instead of a confusing Ansible error. The ansible-core >=2.19 version check now warns instead of failing when provider is Azure. The 2.19 breakage is SSM-specific (AWS) and does not affect Azure WinRM/PSRP connections. Co-Authored-By: Claude <noreply@anthropic.com>
The Azure network module had hardcoded subnet defaults (10.8.1.0/24) that didn't adjust when vnet_cidr was changed, causing "subnet range outside VNet" errors. Now uses cidrsubnet() to auto-derive subnets from vnet_cidr, matching the AWS module pattern. Explicit overrides still work. Fresh Azure Marketplace VMs sometimes ship with a corrupted PackageManagement.dll that causes "Catastrophic failure" when Ansible tries to install PowerShell modules. Pre-installing the NuGet provider in the bootstrap script avoids this. Co-Authored-By: Claude <noreply@anthropic.com>
`env create` was AWS-only. Now supports Azure with provider-aware scaffolding: - Azure env.hcl with vnet_cidr, bastion/controller subnet CIDRs (auto-derived from VNet CIDR) - Azure region.hcl with location instead of aws_region - Defaults --reference to "test" for Azure (the existing Azure env) - Azure inventory generation (resets IPs to PENDING) - env list scans the correct infra directory per provider Usage: dreadgoad env create alpha -p azure --region centralus Co-Authored-By: Claude <noreply@anthropic.com>
Add missing Go doc comments on createAzureEnvHCL, createAzureRegionHCL, and generateAzureInventory. Replace hardcoded special character string in seedRequired() with the specialChars constant to keep a single source of truth. Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR improves GOAD variant generation robustness and expands the CLI + infra scaffolding to better support Azure deployments (env creation, inventory templating, and Azure-specific preflight/bootstrap behavior).
Changes:
- Adds Azure-aware environment scaffolding (
env create) including Azure-specificenv.hcl/region.hclgeneration and inventory bootstrapping. - Fixes multiple variant-generator edge cases (password character set, word-boundary replacement for underscore-delimited keys, file renaming, extensionless-text detection) with added tests.
- Updates Azure Terraform networking to auto-derive subnet CIDRs from
vnet_cidr, and expands Azure inventory templates with full group definitions + updatedadmin_user.
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| modules/terraform-azure-net/variables.tf | Makes Azure subnet CIDRs optional so they can be auto-derived from vnet_cidr. |
| modules/terraform-azure-net/main.tf | Derives public/private subnet CIDRs via cidrsubnet() when not explicitly set. |
| infra/azure/goad-deployment/test/centralus/goad/templates/bootstrap.ps1.tpl | Pre-installs NuGet provider to reduce bootstrap failures on some Marketplace images. |
| cli/internal/variant/namegen.go | Removes problematic first names and disallowed special characters from generated passwords. |
| cli/internal/variant/namegen_test.go | Adds a regression test ensuring generated passwords avoid Jinja-breaking characters. |
| cli/internal/variant/generator.go | Fixes replacement ordering/collisions, underscores-as-boundaries handling, extensionless-text handling, and path renaming. |
| cli/internal/variant/generator_test.go | Adds focused regression tests covering edge cases fixed in the generator. |
| cli/internal/doctor/checks.go | Adjusts Ansible version check behavior for Azure and adds Azure check for pypsrp/PySocks. |
| cli/internal/config/config.go | Adds provider-aware infra base path resolution for Azure vs non-Azure layouts. |
| cli/cmd/provision.go | Passes provider into the ansible-core version gate. |
| cli/cmd/env_cmd.go | Adds Azure scaffolding helpers (subnet derivation, Azure env/region HCL, Azure inventory generation) and correct infra scanning per provider. |
| cli/cmd/env_cmd_test.go | Adds unit tests for Azure subnet derivation. |
| ad/SCCM/providers/azure/inventory | Expands Azure SCCM inventory with full groups and updated admin_user. |
| ad/NHA/providers/azure/inventory | Expands Azure NHA inventory with full groups and updated admin_user. |
| ad/GOAD/providers/azure/inventory | Expands Azure GOAD inventory with full groups and updated admin_user. |
| ad/GOAD-Mini/providers/azure/inventory | Expands Azure GOAD-Mini inventory with full groups and updated admin_user. |
| ad/GOAD-Light/providers/azure/inventory | Expands Azure GOAD-Light inventory with full groups and updated admin_user. |
| ad/DRACARYS/providers/azure/inventory | Expands Azure DRACARYS inventory with full groups and updated admin_user. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Guard against IPv6 CIDR in deriveAzureSubnets (To4() nil panic) - Use ReplaceAllStringFunc instead of ReplaceAllString for envName replacement to avoid $ in env names corrupting regexp output - Fix checkPyPSRP message from "SSH-mode" to "WinRM/PSRP" so it's accurate for both Azure and Ludus providers Co-Authored-By: Claude <noreply@anthropic.com>
- generateAzureInventory falls back to the GOAD Azure provider inventory template when no reference inventory file exists (a fresh clone won't have test-inventory) - Terraform private_subnet_cidr output now references local.private_subnet instead of var.private_subnet_cidr, which is empty by default after the auto-derive change Co-Authored-By: Claude <noreply@anthropic.com>
Same regexp replacement vulnerability as the Azure path — envName and region containing $ would corrupt output via capture group references. Co-Authored-By: Claude <noreply@anthropic.com>
When the original username has no dot (e.g. "missandei"), the generator truncates "firstname.lastname" to just "firstname". Multiple dotless users could get the same firstname, producing duplicate sAMAccountNames. Now passes the truncated name through ensureUnique to add a counter suffix if needed. Co-Authored-By: Claude <noreply@anthropic.com>
Break scaffoldEnv into focused functions (printEnvSummary, scaffoldHCL, scaffoldLabConfig, scaffoldInventory, printNextSteps) for readability. Extract setNameComponent in the variant generator to reduce duplication in mapUserNameComponents. Update dreadgoad.yaml for Azure dreadindex deployment. Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes discovered during the an Azure deployment of a GOAD variant.
Added
dreadgoad env createnow supports Azure (-p azure --region centralus) — scaffolds the full Terragrunt directory tree with auto-derived VNet, bastion, and controller subnet CIDRsdreadgoad doctorchecks forpypsrpandpysockswhen provider is AzurePackageManagement.dllcorruption on fresh Marketplace VMsChanged
[dc],[domain],[server],[trust],[adcs], etc.) and required[all:vars]admin_userin Azure inventory templates changed fromgoadmintoadministratorto match what the bootstrap script configuresbootstrapFromProviderTemplate) resolves the lab directory from the active variant target instead of hardcodingGOADdreadgoad doctoransible-core >=2.19 check now warns instead of failing when provider is Azure (the breakage is SSM-specific)private_subnet_cidrandpublic_subnet_cidrfromvnet_cidrviacidrsubnet()when not explicitly setenv listscans the correct infra directory per providerFixed
{,},[,]— these produced Jinja2 template sequences ({#,{{,{%) that crashed Ansible playbooksGenericWrite_missandei_viserys) are now transformed correctly using word-boundary matchingisTextFileno longer misclassifies extensionless files as binary