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
153 changes: 54 additions & 99 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,105 +12,60 @@ by Orange Cyberdefense.

```mermaid
graph TD
Collection[Ansible Collection]
Collection --> Roles[⚙️ Roles]
Roles --> R0[vulns_credentials]
Roles --> R1[sccm_install_wsus]
Roles --> R2[sccm_pxe]
Roles --> R3[sccm_install_iis]
Roles --> R4[vulns_ntlmdowngrade]
Roles --> R5[trusts]
Roles --> R6[mssql_reporting]
Roles --> R7[domain_controller_slave]
Roles --> R8[disable_user]
Roles --> R9[settings_copy_files]
Roles --> R10[vulns_mssql]
Roles --> R11[laps_verify]
Roles --> R12[ad]
Roles --> R13[vulns_enable_credssp_server]
Roles --> R14[sccm_install_mecm]
Roles --> R15[dc_audit_sacl]
Roles --> R16[security_ensure_kb_not_installed]
Roles --> R17[vulns_openshares]
Roles --> R18[sync_domains]
Roles --> R19[sccm_config_client_push]
Roles --> R20[vulns_schedule]
Roles --> R21[sccm_config_pxe]
Roles --> R22[vulns_shares]
Roles --> R23[laps_dc]
Roles --> R24[settings_updates]
Roles --> R25[groups_domains]
Roles --> R26[vulns_anonymous_enum]
Roles --> R27[sccm_config_client_install]
Roles --> R28[mssql_audit]
Roles --> R29[vulns_enable_llmnr]
Roles --> R30[sccm_config_accounts]
Roles --> R31[settings_admin_password]
Roles --> R32[vulns_acls]
Roles --> R33[security_enable_run_as_ppl]
Roles --> R34[gmsa_hosts]
Roles --> R35[onlyusers]
Roles --> R36[child_domain]
Roles --> R37[sccm_install_adk]
Roles --> R38[mssql_link]
Roles --> R39[vulns_files]
Roles --> R40[parent_child_dns]
Roles --> R41[adcs_templates]
Roles --> R42[laps_server]
Roles --> R43[settings_enable_nat_adapter]
Roles --> R44[elk]
Roles --> R45[sccm_install_prerequisites]
Roles --> R46[vulns_permissions]
Roles --> R47[sccm_config_discovery]
Roles --> R48[settings_windows_defender]
Roles --> R49[member_server]
Roles --> R50[dc_dns_conditional_forwarder]
Roles --> R51[common]
Roles --> R52[sccm_config_boundary]
Roles --> R53[ps]
Roles --> R54[adcs]
Roles --> R55[enable_user]
Roles --> R56[laps_permissions]
Roles --> R57[dns_conditional_forwarder]
Roles --> R58[sccm_config_users]
Roles --> R59[vulns_smbv1]
Roles --> R60[ldap_diagnostic_logging]
Roles --> R61[vulns_enable_credssp_client]
Roles --> R62[dhcp]
Roles --> R63[localusers]
Roles --> R64[sccm_config_naa]
Roles --> R65[password_policy]
Roles --> R66[security_powershell_restrict]
Roles --> R67[settings_keyboard]
Roles --> R68[vulns_autologon]
Roles --> R69[settings_user_rights]
Roles --> R70[commonwkstn]
Roles --> R71[vulns_enable_nbt_ns]
Roles --> R72[mssql_ssms]
Roles --> R73[webdav]
Roles --> R74[settings_gpo_remove]
Roles --> R75[settings_adjust_rights]
Roles --> R76[vulns_disable_firewall]
Roles --> R77[vulns_adcs_templates]
Roles --> R78[gmsa]
Roles --> R79[settings_gpmc]
Roles --> R80[settings_disable_nat_adapter]
Roles --> R81[security_account_is_sensitive]
Roles --> R82[domain_controller]
Roles --> R83[fix_dns]
Roles --> R84[vulns_administrator_folder]
Roles --> R85[iis]
Roles --> R86[move_to_ou]
Roles --> R87[vulns_directory]
Roles --> R88[mssql]
Roles --> R89[acl]
Roles --> R90[settings_no_updates]
Roles --> R91[logs_windows]
Roles --> R92[security_audit_policy]
Roles --> R93[security_asr]
Roles --> R94[settings_hostname]
Collection --> Playbooks[📚 Playbooks]
Playbooks --> PB0[base]
Collection[dreadnode.goad]

Collection --> AD[Active Directory]
Collection --> Server[Server Roles]
Collection --> LAPS[LAPS]
Collection --> Vulns[Vulnerabilities]
Collection --> SCCM[SCCM]
Collection --> Security[Security]
Collection --> Settings[Settings]
Collection --> Playbooks[Playbooks]

AD --> ad & acl & adcs & adcs_templates
AD --> domain_controller & domain_controller_slave
AD --> child_domain & member_server & trusts
AD --> gmsa & gmsa_hosts & password_policy
AD --> move_to_ou & groups_domains & onlyusers
AD --> dns_conditional_forwarder & dc_dns_conditional_forwarder
AD --> parent_child_dns & sync_domains
AD --> disable_user & enable_user

Server --> common & commonwkstn & localusers
Server --> mssql & mssql_link & mssql_ssms & mssql_reporting & mssql_audit
Server --> iis & elk & webdav & dhcp
Server --> logs_windows & ldap_diagnostic_logging
Server --> fix_dns & ps

LAPS --> laps_dc & laps_server & laps_permissions & laps_verify

Vulns --> vulns_credentials & vulns_acls & vulns_permissions
Vulns --> vulns_shares & vulns_openshares & vulns_files & vulns_directory
Vulns --> vulns_smbv1 & vulns_disable_firewall & vulns_anonymous_enum
Vulns --> vulns_autologon & vulns_ntlmdowngrade & vulns_schedule
Vulns --> vulns_mssql & vulns_adcs_templates & vulns_administrator_folder
Vulns --> vulns_enable_llmnr & vulns_enable_nbt_ns
Vulns --> vulns_enable_credssp_server & vulns_enable_credssp_client

SCCM --> sccm_install_prerequisites & sccm_install_adk & sccm_install_mecm
SCCM --> sccm_install_wsus & sccm_install_iis & sccm_pxe
SCCM --> sccm_config_accounts & sccm_config_boundary & sccm_config_discovery
SCCM --> sccm_config_client_push & sccm_config_client_install
SCCM --> sccm_config_naa & sccm_config_pxe & sccm_config_users

Security --> security_audit_policy & security_asr
Security --> security_enable_run_as_ppl & security_account_is_sensitive
Security --> security_powershell_restrict & security_ensure_kb_not_installed
Security --> dc_audit_sacl

Settings --> settings_hostname & settings_keyboard & settings_admin_password
Settings --> settings_updates & settings_no_updates & settings_windows_defender
Settings --> settings_copy_files & settings_user_rights & settings_adjust_rights
Settings --> settings_enable_nat_adapter & settings_disable_nat_adapter
Settings --> settings_gpo_remove & settings_gpmc

Playbooks --> base
```

## Requirements
Expand Down
87 changes: 87 additions & 0 deletions cli/cmd/diagnose.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package cmd

import (
"context"
"fmt"
"os"
"path/filepath"
"time"

"github.com/dreadnode/dreadgoad/internal/ansible"
"github.com/dreadnode/dreadgoad/internal/config"
"github.com/spf13/cobra"
)

var diagnoseCmd = &cobra.Command{
Use: "diagnose",
Short: "Run diagnostic checks against domain controllers",
Long: `Runs the diagnose-dc01 playbook from an independent host to verify
network connectivity, LDAP, WinRM, and DNS for the primary domain controller.

Diagnostics run from dc03/srv03 (vortexindustries domain) to test dc01
(deltasystems domain) connectivity with detailed troubleshooting output.`,
Example: ` dreadgoad diagnose
dreadgoad diagnose --dc01-ip 10.0.1.10
dreadgoad diagnose --env staging --debug`,
RunE: runDiagnose,
}

func init() {
rootCmd.AddCommand(diagnoseCmd)

diagnoseCmd.Flags().String("dc01-ip", "", "Override dc01 IP address (skips AWS lookup)")
}

func runDiagnose(cmd *cobra.Command, args []string) error {
cfg := config.Get()
ctx := context.Background()

dc01IP, _ := cmd.Flags().GetString("dc01-ip")

// Ensure log directory
_ = os.MkdirAll(cfg.LogDir, 0o755)
logFile := filepath.Join(cfg.LogDir, fmt.Sprintf("%s-diagnose-%s.log",
cfg.Env, time.Now().Format("20060102_150405")))

fmt.Println("===============================================")
fmt.Printf("DreadGOAD DC01 Diagnostics - %s\n", time.Now().Format(time.RFC3339))
fmt.Printf("Environment: %s\n", cfg.Env)
fmt.Printf("Log file: %s\n", logFile)
fmt.Println("===============================================")

opts := ansible.RunOptions{
Playbook: "diagnose-dc01.yml",
Env: cfg.Env,
Debug: cfg.Debug,
LogFile: logFile,
}

if dc01IP != "" {
opts.ExtraVars = map[string]string{
"dc01_ip_override": dc01IP,
}
fmt.Printf("Using dc01 IP override: %s\n", dc01IP)
}

fmt.Println("Running diagnostics...")
fmt.Println("-----------------------------------------------")

result := ansible.RunPlaybook(ctx, opts)

fmt.Println("===============================================")
if result.Success {
fmt.Println("Diagnostics completed successfully.")
} else {
fmt.Println("Diagnostics detected issues. Review output above for details.")
if result.TimedOut {
fmt.Println("WARNING: Diagnostic playbook timed out.")
}
}
fmt.Printf("Full log: %s\n", logFile)
fmt.Println("===============================================")

if !result.Success {
return fmt.Errorf("diagnostics failed (exit code %d)", result.ExitCode)
}
return nil
}
61 changes: 61 additions & 0 deletions cli/cmd/variant.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package cmd

import (
"fmt"
"path/filepath"

"github.com/dreadnode/dreadgoad/internal/config"
"github.com/dreadnode/dreadgoad/internal/variant"
"github.com/spf13/cobra"
)

var variantCmd = &cobra.Command{
Use: "variant",
Short: "Generate GOAD variants with randomized entity names",
Long: `Creates a graph-isomorphic copy of GOAD with randomized names while
preserving structure, relationships, vulnerabilities, and attack paths.

All entity names (domains, users, hosts, groups, OUs, passwords) are replaced
with realistic random alternatives. The resulting variant is deployable
exactly like the original GOAD.`,
Example: ` dreadgoad variant generate
dreadgoad variant generate --source ad/GOAD --target ad/GOAD-variant-2 --name variant-2`,
}

var variantGenerateCmd = &cobra.Command{
Use: "generate",
Short: "Generate a new GOAD variant",
RunE: runVariantGenerate,
}

func init() {
rootCmd.AddCommand(variantCmd)
variantCmd.AddCommand(variantGenerateCmd)

variantGenerateCmd.Flags().String("source", "ad/GOAD", "Source GOAD directory")
variantGenerateCmd.Flags().String("target", "ad/GOAD-variant-1", "Target variant directory")
variantGenerateCmd.Flags().String("name", "variant-1", "Variant name")
}

func runVariantGenerate(cmd *cobra.Command, args []string) error {
cfg := config.Get()

source, _ := cmd.Flags().GetString("source")
target, _ := cmd.Flags().GetString("target")
name, _ := cmd.Flags().GetString("name")

// Resolve paths relative to project root
if !filepath.IsAbs(source) {
source = filepath.Join(cfg.ProjectRoot, source)
}
if !filepath.IsAbs(target) {
target = filepath.Join(cfg.ProjectRoot, target)
}

gen := variant.NewGenerator(source, target, name)
if err := gen.Run(); err != nil {
return fmt.Errorf("variant generation failed: %w", err)
}

return nil
}
Loading
Loading