From b0326f57e84b75a665c0db17fd1a8c4fed43ce2e Mon Sep 17 00:00:00 2001 From: Jayson Grace Date: Mon, 30 Mar 2026 22:45:34 -0600 Subject: [PATCH 01/11] refactor: restructure project as ansible collection, flatten roles, update paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Added:** - Added `galaxy.yml` and `meta/runtime.yml` for Ansible Galaxy compatibility - Created `changelogs/changelog.yaml` and `changelogs/config.yaml` for structured changelog tracking - Added `roles/` directory with flattened role names (no nested directories) - Added `plugins/modules/` for custom PowerShell modules used by roles - Added `playbooks/` directory consolidating all playbooks and included missing playbooks from `ansible/` - Added `README.md` with updated architecture and usage docs for the collection structure **Changed:** - Refactored all playbooks and role references to use fully qualified collection names (e.g., `dreadnode.goad.role`) - Moved and flattened roles from `ansible/roles/` into `roles/` using single-depth names (e.g., `roles/settings/keyboard` → `roles/settings_keyboard`) - Updated all references in playbooks to point to new `roles/` structure and FQCN style - Moved custom modules from role `library/` directories to `plugins/modules/` - Updated `.gitignore` for new build artifact and collection layout, removing obsolete ignores - Refactored `Taskfile.yaml` to use new collection layout, updated paths for roles, playbooks, and artifacts - Updated `requirements.yml` to reflect collection dependencies only (removed playbook-level requirements) - Updated `scripts/check.sh`, `scripts/setup_*.sh` to reference new requirements and collection paths - Updated `playbooks.yml` and all includes/imports to reference `playbooks/` directory and new role paths - Updated all `import_playbook`, `include_role`, and role references for new structure and FQCN use - Updated documentation in `README.md` to describe the collection, role/architecture, and usage patterns - Updated all file paths in scripts and Taskfile to align with new flat structure **Removed:** - Removed all Python-based provisioner code (`goad.py`, `goad/`, and related submodules) - Deleted Vagrant, Packer, and Terraform provider templates and scripts - Removed legacy `packer/`, `template/`, and variant generation tooling - Deleted old requirements and lock files (`requirements.txt`, `requirements_311.yml`, `pyproject.toml`, `poetry.lock`, etc.) - Removed all non-Ansible build and environment files (e.g., `globalsettings.ini`, `.venv`, legacy scripts) - Removed legacy `ansible/` directory in favor of `playbooks/` and `roles/` - Removed all files related to non-Ansible provisioning (Python, shell scripts, variant generators) - Removed deprecated provider support and playbooks no longer relevant to the collection **Changed:** - All role variable, playbook, and module references updated to match the new collection/role structure - All playbooks, roles, and supporting files now reside in a structure compatible with Ansible Galaxy collections - Windows, AWS, Azure, and other provider-specific code and templates removed or refactored to align with collection-only deployment - Updated all usage and contribution documentation for the new layout and collection packaging **Removed:** - All legacy cloud provider provisioning templates, Vagrant, Packer, and Terraform files - All variant generation and Python-based orchestration tooling - Legacy build system and requirements for non-Ansible provisioning - All workspace, lab manager, and instance orchestration code from the previous implementation --- .gitignore | 59 +- .hooks/linters/markdownlint.json | 1 + .hooks/templates/docsible-template.md.j2 | 6 +- Dockerfile | 16 - README.md | 530 +++--- Taskfile.yaml | 12 +- ad/GOAD-Light/data/config.json | 2 +- ad/GOAD-variant-1/data/config.json | 2 +- ad/GOAD-variant-1/data/dev-config.json | 2 +- ad/GOAD-variant-1/data/staging-config.json | 2 +- ad/GOAD/data/config.json | 2 +- ad/GOAD/data/dev-config.json | 2 +- ad/GOAD/data/staging-config.json | 2 +- ansible/ansible.cfg => ansible.cfg | 6 +- ansible/build.yml | 22 - ansible/disable_vagrant.yml | 5 - ansible/enable_vagrant.yml | 5 - ansible/private_data_dir/.git_keep | 0 ansible/requirements.yml | 12 - ansible/requirements_311.yml | 13 - changelogs/changelog.yaml | 18 + changelogs/config.yaml | 5 + galaxy.yml | 40 + globalsettings.ini | 27 - goad.py | 529 ------ goad.sh | 58 - goad/__init__.py | 0 goad/command/cmd.py | 234 --- goad/command/cmd_factory.py | 15 - goad/command/linux.py | 131 -- goad/command/windows.py | 51 - goad/command/wsl.py | 47 - goad/config.py | 132 -- goad/dependencies.py | 18 - goad/exceptions.py | 10 - goad/extension.py | 49 - goad/goadpath.py | 168 -- goad/infos.py | 33 - goad/instance.py | 411 ----- goad/instances.py | 106 -- goad/jumpbox.py | 73 - goad/lab_manager.py | 209 --- goad/labs.py | 77 - goad/local_jumpbox.py | 60 - goad/log.py | 38 - goad/menu.py | 101 -- goad/provider/ludus/ludus.py | 172 -- goad/provider/provider.py | 53 - goad/provider/provider_factory.py | 39 - goad/provider/terraform/aws.py | 183 --- goad/provider/terraform/azure.py | 300 ---- goad/provider/terraform/proxmox.py | 201 --- goad/provider/terraform/terraform.py | 44 - goad/provider/vagrant/vagrant.py | 55 - goad/provider/vagrant/virtualbox.py | 16 - goad/provider/vagrant/vmware.py | 17 - goad/provider/vagrant/vmware_esxi.py | 17 - goad/provisioner/ansible/ansible.py | 154 -- goad/provisioner/ansible/docker.py | 63 - goad/provisioner/ansible/local.py | 25 - goad/provisioner/ansible/remote.py | 58 - goad/provisioner/ansible/runner.py | 49 - goad/provisioner/ansible/vm.py | 62 - goad/provisioner/provisioner.py | 36 - goad/provisioner/provisioner_factory.py | 37 - goad/settings.py | 163 -- goad/utils.py | 153 -- goad_docker.sh | 56 - meta/runtime.yml | 2 + noansible_requirements.yml | 13 - packer/proxmox/.gitignore | 2 - packer/proxmox/README.md | 62 - .../10_proxmox_cloudinit/Autounattend.xml | 325 ---- .../Autounattend.xml | 325 ---- .../2016_proxmox_cloudinit/Autounattend.xml | 313 ---- .../2019_proxmox_cloudinit/Autounattend.xml | 312 ---- .../Autounattend.xml | 312 ---- packer/proxmox/build_proxmox_iso.sh | 38 - .../proxmox/config.auto.pkrvars.hcl.template | 8 - packer/proxmox/iso/.gitignore | 1 - packer/proxmox/packer.json.pkr.hcl | 82 - .../scripts/ConfigureRemotingForAnsible.ps1 | 453 ----- packer/proxmox/scripts/Install-WMF3Hotfix.ps1 | 152 -- .../proxmox/scripts/disable-screensaver.ps1 | 4 - packer/proxmox/scripts/disable-winrm.ps1 | 8 - packer/proxmox/scripts/enable-winrm.ps1 | 20 - packer/proxmox/scripts/fixnetwork.ps1 | 30 - packer/proxmox/scripts/microsoft-updates.bat | 12 - packer/proxmox/scripts/set-proxy.ps1 | 3 - .../scripts/sysprep/cloudbase-init-p2.ps1 | 21 - .../sysprep/cloudbase-init-unattend.conf | 27 - .../sysprep/cloudbase-init-unattend.xml | 50 - .../scripts/sysprep/cloudbase-init.conf | 26 - .../scripts/sysprep/cloudbase-init.ps1 | 7 - packer/proxmox/scripts/sysprep/sysprep.bat | 3 - packer/proxmox/scripts/win-updates.ps1 | 252 --- packer/proxmox/variables.pkr.hcl | 21 - ...ndows_10_22h2_proxmox_cloudinit.pkvars.hcl | 13 - ...22h2_proxmox_cloudinit_uptodate.pkvars.hcl | 13 - ...ws_server2016_proxmox_cloudinit.pkvars.hcl | 13 - ...ws_server2019_proxmox_cloudinit.pkvars.hcl | 13 - ...2019_proxmox_cloudinit_uptodate.pkvars.hcl | 13 - packer/vagrant/README.md | 4 - .../vagrant/answer_files/10/Autounattend.xml | 303 ---- .../vagrant/answer_files/11/Autounattend.xml | 298 ---- .../answer_files/2016/Autounattend.xml | 248 --- .../answer_files/2019/Autounattend.xml | 302 ---- .../answer_files/2022/Autounattend.xml | 302 ---- packer/vagrant/build_all.sh | 6 - packer/vagrant/build_windows_10.sh | 11 - packer/vagrant/build_windows_11.sh | 11 - packer/vagrant/build_windows_2019.sh | 18 - packer/vagrant/build_windows_2022.sh | 7 - .../scripts/compile-dotnet-assemblies.bat | 17 - packer/vagrant/scripts/dis-updates.bat | 20 - .../vagrant/scripts/disable-screensaver.ps1 | 4 - packer/vagrant/scripts/disable-winrm.ps1 | 8 - packer/vagrant/scripts/enable-rdp.bat | 2 - packer/vagrant/scripts/enable-winrm.ps1 | 15 - packer/vagrant/scripts/fixnetwork.ps1 | 30 - packer/vagrant/scripts/microsoft-updates.bat | 12 - packer/vagrant/scripts/set-powerplan.ps1 | 19 - .../vagrant/scripts/set-winrm-automatic.bat | 2 - packer/vagrant/scripts/sysprep.bat | 7 - packer/vagrant/scripts/uac-enable.bat | 1 - packer/vagrant/scripts/unattend.xml | 41 - packer/vagrant/scripts/vm-guest-tools.ps1 | 96 -- packer/vagrant/scripts/win-updates.ps1 | 252 --- .../vagrant/vagrantfile-windows_10.template | 91 -- .../vagrant/vagrantfile-windows_2016.template | 86 - packer/vagrant/windows_10.json | 129 -- packer/vagrant/windows_11.json | 141 -- packer/vagrant/windows_2019.json | 121 -- packer/vagrant/windows_2022.json | 121 -- playbooks.yml | 77 - {ansible => playbooks}/ad-acl.yml | 2 +- {ansible => playbooks}/ad-child_domain.yml | 6 +- {ansible => playbooks}/ad-data.yml | 8 +- {ansible => playbooks}/ad-gmsa.yml | 4 +- {ansible => playbooks}/ad-members.yml | 4 +- {ansible => playbooks}/ad-parent_domain.yml | 2 +- {ansible => playbooks}/ad-relations.yml | 6 +- {ansible => playbooks}/ad-servers.yml | 4 +- {ansible => playbooks}/ad-trusts.yml | 10 +- {ansible => playbooks}/ad.yml | 0 {ansible => playbooks}/adcs.yml | 4 +- .../playbooks => playbooks}/base/README.md | 0 .../playbooks => playbooks}/base/dc_base.yml | 0 .../base/member_base.yml | 0 .../base/mssql_base.yml | 0 playbooks/build.yml | 22 + {ansible => playbooks}/data.yml | 0 {ansible => playbooks}/dhcp.yml | 4 +- {ansible => playbooks}/diagnose-dc01.yml | 0 playbooks/disable_vagrant.yml | 5 + {ansible => playbooks}/elk.yml | 4 +- playbooks/enable_vagrant.yml | 5 + {ansible => playbooks}/fix_dns.yml | 4 +- {ansible => playbooks}/fix_trust.yml | 2 +- {ansible => playbooks}/interfaces.yml | 2 +- {ansible => playbooks}/laps.yml | 8 +- {ansible => playbooks}/localusers.yml | 4 +- {ansible => playbooks}/main.yml | 2 +- {ansible => playbooks}/onlyusers.yml | 4 +- {ansible => playbooks}/reboot.yml | 0 {ansible => playbooks}/sccm-client.yml | 4 +- {ansible => playbooks}/sccm-config.yml | 16 +- {ansible => playbooks}/sccm-install.yml | 12 +- {ansible => playbooks}/sccm-pxe.yml | 6 +- {ansible => playbooks}/security.yml | 12 +- {ansible => playbooks}/security_logging.yml | 4 +- {ansible => playbooks}/servers.yml | 12 +- {ansible => playbooks}/vulnerabilities.yml | 6 +- {ansible => playbooks}/wait5m.yml | 0 .../modules}/sccm_boundary.ps1 | 0 .../modules}/sccm_boundary_group.ps1 | 0 .../sccm_boundary_to_boundarygroup.ps1 | 0 .../modules}/win_ad_dacl.ps1 | 0 .../modules}/win_ad_object.ps1 | 0 .../library => plugins/modules}/win_gpo.ps1 | 0 .../modules}/win_gpo_link.ps1 | 0 .../modules}/win_gpo_reg.ps1 | 0 poetry.lock | 1454 ----------------- pyproject.toml | 31 - requirements.txt | 19 - requirements.yml | 11 +- requirements_311.yml | 21 - roles/acl/README.md | 38 + roles/acl/meta/main.yml | 14 + {ansible/roles => roles}/acl/tasks/main.yml | 0 roles/ad/README.md | 68 + roles/ad/meta/main.yml | 14 + {ansible/roles => roles}/ad/tasks/groups.yml | 0 {ansible/roles => roles}/ad/tasks/main.yml | 0 {ansible/roles => roles}/ad/tasks/ou.yml | 0 {ansible/roles => roles}/ad/tasks/users.yml | 0 roles/adcs/README.md | 42 + roles/adcs/meta/main.yml | 14 + {ansible/roles => roles}/adcs/tasks/main.yml | 0 roles/adcs_templates/README.md | 42 + .../files/ADCSTemplate/.gitignore | 0 .../files/ADCSTemplate/ADCSTemplate.psd1 | Bin .../files/ADCSTemplate/ADCSTemplate.psm1 | 0 .../COMMUNITY_ADCSTemplate.psm1 | Bin .../COMMUNITY_ADCSTemplate.schema.mof | Bin .../ADCSTemplate/Examples/Build-ADCS.ps1 | 0 .../files/ADCSTemplate/Examples/Demo.ps1 | 0 .../ADCSTemplate/Examples/PowerShellCMS.json | Bin .../files/ADCSTemplate/Examples/Tanium.json | Bin .../adcs_templates/files/ADCSTemplate/LICENSE | 0 .../files/ADCSTemplate/README.md | 0 .../adcs_templates/files/ESC1.json | Bin .../adcs_templates/files/ESC2.json | Bin .../adcs_templates/files/ESC3-CRA.json | Bin .../adcs_templates/files/ESC3.json | Bin .../adcs_templates/files/ESC4.json | Bin roles/adcs_templates/meta/main.yml | 14 + .../adcs_templates/tasks/main.yml | 0 roles/child_domain/README.md | 49 + roles/child_domain/meta/main.yml | 14 + .../child_domain/tasks/main.yml | 0 roles/common/README.md | 53 + roles/common/meta/main.yml | 14 + .../common/tasks/chocolatey.yml | 0 .../roles => roles}/common/tasks/main.yml | 0 roles/commonwkstn/README.md | 41 + roles/commonwkstn/meta/main.yml | 14 + .../commonwkstn/tasks/main.yml | 0 roles/dc_audit_sacl/README.md | 56 + .../dc_audit_sacl/defaults/main.yml | 0 .../dc_audit_sacl/handlers/main.yml | 0 .../dc_audit_sacl/meta/main.yml | 0 .../dc_audit_sacl/tasks/main.yml | 0 roles/dc_dns_conditional_forwarder/README.md | 37 + .../meta/main.yml | 14 + .../tasks/main.yml | 0 roles/dhcp/README.md | 44 + roles/dhcp/meta/main.yml | 14 + {ansible/roles => roles}/dhcp/tasks/main.yml | 0 roles/disable_user/README.md | 37 + roles/disable_user/meta/main.yml | 14 + .../disable_user/tasks/main.yml | 0 roles/dns_conditional_forwarder/README.md | 37 + roles/dns_conditional_forwarder/meta/main.yml | 14 + .../dns_conditional_forwarder/tasks/main.yml | 0 roles/domain_controller/README.md | 60 + roles/domain_controller/meta/main.yml | 14 + .../domain_controller/tasks/main.yml | 0 roles/domain_controller_slave/README.md | 38 + roles/domain_controller_slave/meta/main.yml | 14 + .../domain_controller_slave/tasks/main.yml | 0 roles/elk/README.md | 60 + .../roles => roles}/elk/defaults/main.yml | 0 .../elk/files/elasticsearch.yml | 0 {ansible/roles => roles}/elk/files/kibana.yml | 0 roles/elk/meta/main.yml | 14 + {ansible/roles => roles}/elk/tasks/main.yml | 0 roles/enable_user/README.md | 37 + roles/enable_user/meta/main.yml | 14 + .../enable_user/tasks/main.yml | 0 roles/fix_dns/README.md | 41 + roles/fix_dns/meta/main.yml | 14 + .../roles => roles}/fix_dns/tasks/main.yml | 0 roles/gmsa/README.md | 37 + roles/gmsa/meta/main.yml | 14 + {ansible/roles => roles}/gmsa/tasks/main.yml | 0 roles/gmsa_hosts/README.md | 38 + roles/gmsa_hosts/meta/main.yml | 14 + .../roles => roles}/gmsa_hosts/tasks/main.yml | 0 roles/groups_domains/README.md | 39 + roles/groups_domains/meta/main.yml | 14 + .../groups_domains/tasks/main.yml | 0 roles/iis/README.md | 43 + {ansible/roles => roles}/iis/files/index.html | 0 roles/iis/meta/main.yml | 14 + {ansible/roles => roles}/iis/tasks/main.yml | 0 roles/laps_dc/README.md | 89 + .../dc => roles/laps_dc}/defaults/main.yml | 0 .../dc => roles/laps_dc}/files/comment.cmtx | 0 roles/laps_dc/meta/main.yml | 14 + .../dc => roles/laps_dc}/tasks/install.yml | 24 +- .../laps/dc => roles/laps_dc}/tasks/main.yml | 0 .../laps_dc}/tasks/move_server_to_ou.yml | 0 .../laps/dc => roles/laps_dc}/vars/main.yml | 0 roles/laps_permissions/README.md | 41 + roles/laps_permissions/meta/main.yml | 14 + .../laps_permissions}/tasks/main.yml | 0 roles/laps_server/README.md | 45 + roles/laps_server/meta/main.yml | 14 + .../laps_server}/tasks/install.yml | 0 .../laps_server}/tasks/main.yml | 0 roles/laps_verify/README.md | 38 + roles/laps_verify/meta/main.yml | 14 + .../laps_verify}/tasks/main.yml | 0 roles/ldap_diagnostic_logging/README.md | 60 + .../ldap_diagnostic_logging/defaults/main.yml | 0 .../ldap_diagnostic_logging/handlers/main.yml | 0 .../ldap_diagnostic_logging/meta/main.yml | 0 .../ldap_diagnostic_logging/tasks/main.yml | 0 roles/localusers/README.md | 37 + roles/localusers/meta/main.yml | 14 + .../roles => roles}/localusers/tasks/main.yml | 0 roles/logs_windows/README.md | 77 + .../logs_windows/defaults/main.yml | 0 .../logs_windows/files/Sysmon.zip | Bin .../files/sysmonconfig-export.xml | 0 .../files/uninstall-service-winlogbeat.ps1 | 0 .../logs_windows/handlers/main.yml | 0 roles/logs_windows/meta/main.yml | 14 + .../logs_windows/tasks/main.yml | 0 .../logs_windows/tasks/winlogbeat.yml | 0 .../logs_windows/templates/winlogbeat.yml.j2 | 0 roles/member_server/README.md | 41 + roles/member_server/meta/main.yml | 14 + .../member_server/tasks/main.yml | 0 roles/move_to_ou/README.md | 37 + roles/move_to_ou/meta/main.yml | 14 + .../roles => roles}/move_to_ou/tasks/main.yml | 0 roles/mssql/README.md | 92 ++ .../roles => roles}/mssql/defaults/main.yml | 0 .../mssql/files/install_sql.ps1 | 0 .../mssql/files/sql_conf.ini.MSSQL_2019.j2 | 0 .../mssql/files/sql_conf.ini.MSSQL_2022.j2 | 0 roles/mssql/meta/main.yml | 14 + .../roles => roles}/mssql/tasks/config.yml | 0 .../roles => roles}/mssql/tasks/install.yml | 0 {ansible/roles => roles}/mssql/tasks/main.yml | 0 roles/mssql_audit/README.md | 60 + .../mssql_audit/defaults/main.yml | 0 .../roles => roles}/mssql_audit/meta/main.yml | 0 .../mssql_audit/tasks/main.yml | 0 roles/mssql_link/README.md | 45 + roles/mssql_link/meta/main.yml | 14 + .../mssql_link/tasks/logins.yml | 0 .../roles => roles}/mssql_link/tasks/main.yml | 0 roles/mssql_reporting/README.md | 41 + roles/mssql_reporting/meta/main.yml | 14 + .../mssql_reporting/tasks/main.yml | 0 roles/mssql_ssms/README.md | 43 + roles/mssql_ssms/meta/main.yml | 14 + .../roles => roles}/mssql_ssms/tasks/main.yml | 0 roles/onlyusers/README.md | 37 + roles/onlyusers/meta/main.yml | 14 + .../roles => roles}/onlyusers/tasks/main.yml | 2 +- roles/parent_child_dns/README.md | 39 + roles/parent_child_dns/meta/main.yml | 14 + .../parent_child_dns/tasks/main.yml | 0 roles/password_policy/README.md | 37 + roles/password_policy/meta/main.yml | 14 + .../password_policy/tasks/main.yml | 0 roles/ps/README.md | 37 + roles/ps/meta/main.yml | 14 + {ansible/roles => roles}/ps/tasks/main.yml | 0 roles/sccm_config_accounts/README.md | 37 + roles/sccm_config_accounts/meta/main.yml | 14 + .../sccm_config_accounts}/tasks/main.yml | 0 roles/sccm_config_boundary/README.md | 39 + roles/sccm_config_boundary/meta/main.yml | 14 + .../sccm_config_boundary}/tasks/main.yml | 6 +- roles/sccm_config_client_install/README.md | 37 + .../sccm_config_client_install/meta/main.yml | 14 + .../tasks/main.yml | 0 roles/sccm_config_client_push/README.md | 37 + roles/sccm_config_client_push/meta/main.yml | 14 + .../sccm_config_client_push}/tasks/main.yml | 0 roles/sccm_config_discovery/README.md | 38 + roles/sccm_config_discovery/meta/main.yml | 14 + .../sccm_config_discovery}/tasks/main.yml | 0 roles/sccm_config_naa/README.md | 37 + roles/sccm_config_naa/meta/main.yml | 14 + .../sccm_config_naa}/tasks/main.yml | 0 roles/sccm_config_pxe/README.md | 37 + roles/sccm_config_pxe/meta/main.yml | 14 + .../sccm_config_pxe}/tasks/main.yml | 0 roles/sccm_config_users/README.md | 37 + roles/sccm_config_users/meta/main.yml | 14 + .../sccm_config_users}/tasks/main.yml | 0 roles/sccm_install_adk/README.md | 44 + roles/sccm_install_adk/meta/main.yml | 14 + .../sccm_install_adk}/tasks/main.yml | 0 roles/sccm_install_iis/README.md | 44 + roles/sccm_install_iis/meta/main.yml | 14 + .../sccm_install_iis}/tasks/main.yml | 0 roles/sccm_install_mecm/README.md | 51 + .../files/ConfigMgrAutoSave.ini | 0 roles/sccm_install_mecm/meta/main.yml | 14 + .../sccm_install_mecm}/tasks/main.yml | 0 roles/sccm_install_prerequisites/README.md | 44 + .../sccm_install_prerequisites/meta/main.yml | 14 + .../tasks/main.yml | 0 roles/sccm_install_wsus/README.md | 40 + roles/sccm_install_wsus/meta/main.yml | 14 + .../sccm_install_wsus}/tasks/main.yml | 0 roles/sccm_pxe/README.md | 54 + .../pxe => roles/sccm_pxe}/defaults/main.yml | 0 roles/sccm_pxe/meta/main.yml | 14 + .../pxe => roles/sccm_pxe}/tasks/main.yml | 0 roles/security_account_is_sensitive/README.md | 37 + .../meta/main.yml | 14 + .../tasks/main.yml | 0 roles/security_asr/README.md | 37 + roles/security_asr/meta/main.yml | 14 + .../asr => roles/security_asr}/tasks/main.yml | 0 roles/security_audit_policy/README.md | 44 + roles/security_audit_policy/meta/main.yml | 14 + .../security_audit_policy}/tasks/main.yml | 0 roles/security_enable_run_as_ppl/README.md | 37 + .../security_enable_run_as_ppl/meta/main.yml | 14 + .../tasks/main.yml | 0 .../README.md | 40 + .../meta/main.yml | 14 + .../tasks/main.yml | 0 roles/security_powershell_restrict/README.md | 37 + .../meta/main.yml | 14 + .../tasks/main.yml | 0 roles/settings_adjust_rights/README.md | 37 + roles/settings_adjust_rights/meta/main.yml | 14 + .../settings_adjust_rights}/tasks/main.yml | 0 roles/settings_admin_password/README.md | 37 + roles/settings_admin_password/meta/main.yml | 14 + .../settings_admin_password}/tasks/main.yml | 0 roles/settings_copy_files/README.md | 38 + .../settings_copy_files}/files/GOAD.png | Bin .../settings_copy_files}/files/starks.jpg | Bin roles/settings_copy_files/meta/main.yml | 14 + .../settings_copy_files}/tasks/main.yml | 0 roles/settings_disable_nat_adapter/README.md | 37 + .../meta/main.yml | 14 + .../tasks/main.yml | 0 roles/settings_enable_nat_adapter/README.md | 37 + .../settings_enable_nat_adapter/meta/main.yml | 14 + .../tasks/main.yml | 0 roles/settings_gpmc/README.md | 37 + roles/settings_gpmc/meta/main.yml | 14 + .../settings_gpmc}/tasks/main.yml | 0 roles/settings_gpo_remove/README.md | 37 + .../settings_gpo_remove}/files/remove-gpo.ps1 | 0 roles/settings_gpo_remove/meta/main.yml | 14 + .../settings_gpo_remove}/tasks/main.yml | 0 roles/settings_hostname/README.md | 40 + roles/settings_hostname/meta/main.yml | 14 + .../settings_hostname}/tasks/main.yml | 0 roles/settings_keyboard/README.md | 38 + roles/settings_keyboard/meta/main.yml | 14 + .../settings_keyboard}/tasks/main.yml | 0 roles/settings_no_updates/README.md | 37 + roles/settings_no_updates/meta/main.yml | 14 + .../settings_no_updates}/tasks/main.yml | 0 roles/settings_updates/README.md | 38 + roles/settings_updates/meta/main.yml | 14 + .../settings_updates}/tasks/default.yml | 0 roles/settings_user_rights/README.md | 37 + roles/settings_user_rights/meta/main.yml | 14 + .../settings_user_rights}/tasks/main.yml | 0 roles/settings_windows_defender/README.md | 42 + roles/settings_windows_defender/meta/main.yml | 14 + .../settings_windows_defender}/tasks/main.yml | 0 roles/sync_domains/README.md | 37 + roles/sync_domains/meta/main.yml | 14 + .../sync_domains/tasks/main.yml | 0 roles/trusts/README.md | 39 + roles/trusts/meta/main.yml | 14 + .../roles => roles}/trusts/tasks/main.yml | 0 roles/vulns_acls/README.md | 37 + roles/vulns_acls/meta/main.yml | 14 + .../acls => roles/vulns_acls}/tasks/main.yml | 0 roles/vulns_adcs_templates/README.md | 41 + .../files/ADCSTemplate/.gitignore | 0 .../files/ADCSTemplate/ADCSTemplate.psd1 | Bin .../files/ADCSTemplate/ADCSTemplate.psm1 | 0 .../COMMUNITY_ADCSTemplate.psm1 | Bin .../COMMUNITY_ADCSTemplate.schema.mof | Bin .../ADCSTemplate/Examples/Build-ADCS.ps1 | 0 .../files/ADCSTemplate/Examples/Demo.ps1 | 0 .../ADCSTemplate/Examples/PowerShellCMS.json | Bin .../files/ADCSTemplate/Examples/Tanium.json | Bin .../files/ADCSTemplate/LICENSE | 0 .../files/ADCSTemplate/README.md | 0 roles/vulns_adcs_templates/meta/main.yml | 14 + .../vulns_adcs_templates}/tasks/main.yml | 0 roles/vulns_administrator_folder/README.md | 44 + .../vulns_administrator_folder/meta/main.yml | 14 + .../tasks/main.yml | 0 roles/vulns_anonymous_enum/README.md | 49 + roles/vulns_anonymous_enum/meta/main.yml | 14 + .../vulns_anonymous_enum}/tasks/main.yml | 0 roles/vulns_autologon/README.md | 37 + roles/vulns_autologon/meta/main.yml | 14 + .../vulns_autologon}/tasks/main.yml | 0 roles/vulns_credentials/README.md | 37 + roles/vulns_credentials/meta/main.yml | 14 + .../vulns_credentials}/tasks/main.yml | 0 roles/vulns_directory/README.md | 37 + roles/vulns_directory/meta/main.yml | 14 + .../vulns_directory}/tasks/main.yml | 0 roles/vulns_disable_firewall/README.md | 37 + roles/vulns_disable_firewall/meta/main.yml | 14 + .../vulns_disable_firewall}/tasks/main.yml | 0 roles/vulns_enable_credssp_client/README.md | 37 + .../vulns_enable_credssp_client/meta/main.yml | 14 + .../tasks/main.yml | 2 +- roles/vulns_enable_credssp_server/README.md | 37 + .../vulns_enable_credssp_server/meta/main.yml | 14 + .../tasks/main.yml | 2 +- roles/vulns_enable_llmnr/README.md | 37 + roles/vulns_enable_llmnr/meta/main.yml | 14 + .../vulns_enable_llmnr}/tasks/main.yml | 0 roles/vulns_enable_nbt_ns/README.md | 37 + roles/vulns_enable_nbt_ns/meta/main.yml | 14 + .../vulns_enable_nbt_ns}/tasks/main.yml | 0 roles/vulns_files/README.md | 37 + roles/vulns_files/meta/main.yml | 14 + .../vulns_files}/tasks/main.yml | 0 roles/vulns_mssql/README.md | 37 + roles/vulns_mssql/meta/main.yml | 14 + .../vulns_mssql}/tasks/main.yml | 0 roles/vulns_ntlmdowngrade/README.md | 37 + roles/vulns_ntlmdowngrade/meta/main.yml | 14 + .../vulns_ntlmdowngrade}/tasks/main.yml | 0 roles/vulns_openshares/README.md | 43 + roles/vulns_openshares/meta/main.yml | 14 + .../vulns_openshares}/tasks/main.yml | 0 roles/vulns_permissions/README.md | 37 + roles/vulns_permissions/meta/main.yml | 14 + .../vulns_permissions}/tasks/main.yml | 0 roles/vulns_schedule/README.md | 37 + roles/vulns_schedule/meta/main.yml | 14 + .../vulns_schedule}/tasks/main.yml | 0 roles/vulns_shares/README.md | 38 + roles/vulns_shares/meta/main.yml | 14 + .../vulns_shares}/tasks/main.yml | 0 roles/vulns_smbv1/README.md | 38 + roles/vulns_smbv1/meta/main.yml | 14 + .../vulns_smbv1}/tasks/main.yml | 0 roles/webdav/README.md | 38 + roles/webdav/meta/main.yml | 14 + .../roles => roles}/webdav/tasks/main.yml | 0 scripts/check.sh | 2 +- scripts/get-playbook-files.sh | 234 +-- scripts/run-playbook-with-retry.sh | 32 +- scripts/setup_aws.sh | 2 +- scripts/setup_azure.sh | 2 +- scripts/setup_esxi.sh | 2 +- scripts/setup_proxmox.sh | 2 +- template/provider/aws/instance-init.ps1.tpl | 11 - template/provider/aws/instance-init.sh.tpl | 6 - template/provider/aws/jumpbox-init.sh.tpl | 12 - template/provider/aws/jumpbox.tf | 45 - template/provider/aws/linux.tf | 60 - template/provider/aws/main.tf | 15 - template/provider/aws/network.tf | 192 --- template/provider/aws/outputs.tf | 15 - template/provider/aws/variables.tf | 74 - template/provider/aws/windows.tf | 60 - template/provider/azure/jumpbox.tf | 59 - template/provider/azure/linux.tf | 57 - template/provider/azure/main.tf | 20 - template/provider/azure/network.tf | 43 - template/provider/azure/outputs.tf | 15 - template/provider/azure/variables.tf | 26 - template/provider/azure/windows.tf | 61 - template/provider/ludus/config.yml | 2 - template/provider/proxmox/main.tf | 15 - template/provider/proxmox/variables.tf | 53 - template/provider/proxmox/windows.tf | 148 -- template/provider/virtualbox/Vagrantfile | 84 - template/provider/vmware/Vagrantfile | 84 - template/provider/vmware_esxi/.env | 6 - template/provider/vmware_esxi/Vagrantfile | 90 - tools/variant_generator/README.md | 145 -- tools/variant_generator/__init__.py | 10 - .../goad_variant_generator.py | 948 ----------- tools/variant_generator/name_generator.py | 265 --- vagrant/ConfigureRemotingForAnsible.ps1 | 453 ----- vagrant/Install-WMF3Hotfix.ps1 | 152 -- vagrant/fix_ip.ps1 | 6 - workspace/.git_keep | 0 577 files changed, 5985 insertions(+), 15634 deletions(-) delete mode 100644 Dockerfile rename ansible/ansible.cfg => ansible.cfg (91%) delete mode 100644 ansible/build.yml delete mode 100644 ansible/disable_vagrant.yml delete mode 100644 ansible/enable_vagrant.yml delete mode 100644 ansible/private_data_dir/.git_keep delete mode 100644 ansible/requirements.yml delete mode 100644 ansible/requirements_311.yml create mode 100644 changelogs/changelog.yaml create mode 100644 changelogs/config.yaml create mode 100644 galaxy.yml delete mode 100644 globalsettings.ini delete mode 100644 goad.py delete mode 100755 goad.sh delete mode 100644 goad/__init__.py delete mode 100644 goad/command/cmd.py delete mode 100644 goad/command/cmd_factory.py delete mode 100644 goad/command/linux.py delete mode 100644 goad/command/windows.py delete mode 100644 goad/command/wsl.py delete mode 100644 goad/config.py delete mode 100644 goad/dependencies.py delete mode 100644 goad/exceptions.py delete mode 100644 goad/extension.py delete mode 100644 goad/goadpath.py delete mode 100644 goad/infos.py delete mode 100644 goad/instance.py delete mode 100644 goad/instances.py delete mode 100644 goad/jumpbox.py delete mode 100644 goad/lab_manager.py delete mode 100644 goad/labs.py delete mode 100644 goad/local_jumpbox.py delete mode 100644 goad/log.py delete mode 100644 goad/menu.py delete mode 100644 goad/provider/ludus/ludus.py delete mode 100644 goad/provider/provider.py delete mode 100644 goad/provider/provider_factory.py delete mode 100644 goad/provider/terraform/aws.py delete mode 100644 goad/provider/terraform/azure.py delete mode 100644 goad/provider/terraform/proxmox.py delete mode 100644 goad/provider/terraform/terraform.py delete mode 100644 goad/provider/vagrant/vagrant.py delete mode 100644 goad/provider/vagrant/virtualbox.py delete mode 100644 goad/provider/vagrant/vmware.py delete mode 100644 goad/provider/vagrant/vmware_esxi.py delete mode 100644 goad/provisioner/ansible/ansible.py delete mode 100644 goad/provisioner/ansible/docker.py delete mode 100644 goad/provisioner/ansible/local.py delete mode 100644 goad/provisioner/ansible/remote.py delete mode 100644 goad/provisioner/ansible/runner.py delete mode 100644 goad/provisioner/ansible/vm.py delete mode 100644 goad/provisioner/provisioner.py delete mode 100644 goad/provisioner/provisioner_factory.py delete mode 100644 goad/settings.py delete mode 100644 goad/utils.py delete mode 100755 goad_docker.sh create mode 100644 meta/runtime.yml delete mode 100644 noansible_requirements.yml delete mode 100644 packer/proxmox/.gitignore delete mode 100644 packer/proxmox/README.md delete mode 100644 packer/proxmox/answer_files/10_proxmox_cloudinit/Autounattend.xml delete mode 100644 packer/proxmox/answer_files/10_proxmox_cloudinit_uptodate/Autounattend.xml delete mode 100644 packer/proxmox/answer_files/2016_proxmox_cloudinit/Autounattend.xml delete mode 100644 packer/proxmox/answer_files/2019_proxmox_cloudinit/Autounattend.xml delete mode 100644 packer/proxmox/answer_files/2019_proxmox_cloudinit_uptodate/Autounattend.xml delete mode 100755 packer/proxmox/build_proxmox_iso.sh delete mode 100644 packer/proxmox/config.auto.pkrvars.hcl.template delete mode 100644 packer/proxmox/iso/.gitignore delete mode 100644 packer/proxmox/packer.json.pkr.hcl delete mode 100644 packer/proxmox/scripts/ConfigureRemotingForAnsible.ps1 delete mode 100644 packer/proxmox/scripts/Install-WMF3Hotfix.ps1 delete mode 100644 packer/proxmox/scripts/disable-screensaver.ps1 delete mode 100644 packer/proxmox/scripts/disable-winrm.ps1 delete mode 100644 packer/proxmox/scripts/enable-winrm.ps1 delete mode 100644 packer/proxmox/scripts/fixnetwork.ps1 delete mode 100644 packer/proxmox/scripts/microsoft-updates.bat delete mode 100644 packer/proxmox/scripts/set-proxy.ps1 delete mode 100644 packer/proxmox/scripts/sysprep/cloudbase-init-p2.ps1 delete mode 100644 packer/proxmox/scripts/sysprep/cloudbase-init-unattend.conf delete mode 100644 packer/proxmox/scripts/sysprep/cloudbase-init-unattend.xml delete mode 100644 packer/proxmox/scripts/sysprep/cloudbase-init.conf delete mode 100644 packer/proxmox/scripts/sysprep/cloudbase-init.ps1 delete mode 100644 packer/proxmox/scripts/sysprep/sysprep.bat delete mode 100644 packer/proxmox/scripts/win-updates.ps1 delete mode 100644 packer/proxmox/variables.pkr.hcl delete mode 100644 packer/proxmox/windows_10_22h2_proxmox_cloudinit.pkvars.hcl delete mode 100644 packer/proxmox/windows_10_22h2_proxmox_cloudinit_uptodate.pkvars.hcl delete mode 100644 packer/proxmox/windows_server2016_proxmox_cloudinit.pkvars.hcl delete mode 100644 packer/proxmox/windows_server2019_proxmox_cloudinit.pkvars.hcl delete mode 100644 packer/proxmox/windows_server2019_proxmox_cloudinit_uptodate.pkvars.hcl delete mode 100644 packer/vagrant/README.md delete mode 100644 packer/vagrant/answer_files/10/Autounattend.xml delete mode 100644 packer/vagrant/answer_files/11/Autounattend.xml delete mode 100644 packer/vagrant/answer_files/2016/Autounattend.xml delete mode 100644 packer/vagrant/answer_files/2019/Autounattend.xml delete mode 100644 packer/vagrant/answer_files/2022/Autounattend.xml delete mode 100755 packer/vagrant/build_all.sh delete mode 100755 packer/vagrant/build_windows_10.sh delete mode 100755 packer/vagrant/build_windows_11.sh delete mode 100755 packer/vagrant/build_windows_2019.sh delete mode 100755 packer/vagrant/build_windows_2022.sh delete mode 100644 packer/vagrant/scripts/compile-dotnet-assemblies.bat delete mode 100644 packer/vagrant/scripts/dis-updates.bat delete mode 100644 packer/vagrant/scripts/disable-screensaver.ps1 delete mode 100644 packer/vagrant/scripts/disable-winrm.ps1 delete mode 100644 packer/vagrant/scripts/enable-rdp.bat delete mode 100644 packer/vagrant/scripts/enable-winrm.ps1 delete mode 100644 packer/vagrant/scripts/fixnetwork.ps1 delete mode 100644 packer/vagrant/scripts/microsoft-updates.bat delete mode 100644 packer/vagrant/scripts/set-powerplan.ps1 delete mode 100644 packer/vagrant/scripts/set-winrm-automatic.bat delete mode 100644 packer/vagrant/scripts/sysprep.bat delete mode 100644 packer/vagrant/scripts/uac-enable.bat delete mode 100644 packer/vagrant/scripts/unattend.xml delete mode 100644 packer/vagrant/scripts/vm-guest-tools.ps1 delete mode 100644 packer/vagrant/scripts/win-updates.ps1 delete mode 100644 packer/vagrant/vagrantfile-windows_10.template delete mode 100644 packer/vagrant/vagrantfile-windows_2016.template delete mode 100644 packer/vagrant/windows_10.json delete mode 100644 packer/vagrant/windows_11.json delete mode 100644 packer/vagrant/windows_2019.json delete mode 100644 packer/vagrant/windows_2022.json delete mode 100644 playbooks.yml rename {ansible => playbooks}/ad-acl.yml (91%) rename {ansible => playbooks}/ad-child_domain.yml (86%) rename {ansible => playbooks}/ad-data.yml (75%) rename {ansible => playbooks}/ad-gmsa.yml (89%) rename {ansible => playbooks}/ad-members.yml (92%) rename {ansible => playbooks}/ad-parent_domain.yml (97%) rename {ansible => playbooks}/ad-relations.yml (80%) rename {ansible => playbooks}/ad-servers.yml (75%) rename {ansible => playbooks}/ad-trusts.yml (85%) rename {ansible => playbooks}/ad.yml (100%) rename {ansible => playbooks}/adcs.yml (88%) rename {ansible/playbooks => playbooks}/base/README.md (100%) rename {ansible/playbooks => playbooks}/base/dc_base.yml (100%) rename {ansible/playbooks => playbooks}/base/member_base.yml (100%) rename {ansible/playbooks => playbooks}/base/mssql_base.yml (100%) create mode 100644 playbooks/build.yml rename {ansible => playbooks}/data.yml (100%) rename {ansible => playbooks}/dhcp.yml (89%) rename {ansible => playbooks}/diagnose-dc01.yml (100%) create mode 100644 playbooks/disable_vagrant.yml rename {ansible => playbooks}/elk.yml (68%) create mode 100644 playbooks/enable_vagrant.yml rename {ansible => playbooks}/fix_dns.yml (63%) rename {ansible => playbooks}/fix_trust.yml (96%) rename {ansible => playbooks}/interfaces.yml (97%) rename {ansible => playbooks}/laps.yml (82%) rename {ansible => playbooks}/localusers.yml (76%) rename {ansible => playbooks}/main.yml (98%) rename {ansible => playbooks}/onlyusers.yml (88%) rename {ansible => playbooks}/reboot.yml (100%) rename {ansible => playbooks}/sccm-client.yml (79%) rename {ansible => playbooks}/sccm-config.yml (73%) rename {ansible => playbooks}/sccm-install.yml (71%) rename {ansible => playbooks}/sccm-pxe.yml (82%) rename {ansible => playbooks}/security.yml (66%) rename {ansible => playbooks}/security_logging.yml (92%) rename {ansible => playbooks}/servers.yml (86%) rename {ansible => playbooks}/vulnerabilities.yml (86%) rename {ansible => playbooks}/wait5m.yml (100%) rename {ansible/roles/sccm/config/boundary/library => plugins/modules}/sccm_boundary.ps1 (100%) rename {ansible/roles/sccm/config/boundary/library => plugins/modules}/sccm_boundary_group.ps1 (100%) rename {ansible/roles/sccm/config/boundary/library => plugins/modules}/sccm_boundary_to_boundarygroup.ps1 (100%) rename {ansible/roles/laps/dc/library => plugins/modules}/win_ad_dacl.ps1 (100%) rename {ansible/roles/laps/dc/library => plugins/modules}/win_ad_object.ps1 (100%) rename {ansible/roles/laps/dc/library => plugins/modules}/win_gpo.ps1 (100%) rename {ansible/roles/laps/dc/library => plugins/modules}/win_gpo_link.ps1 (100%) rename {ansible/roles/laps/dc/library => plugins/modules}/win_gpo_reg.ps1 (100%) delete mode 100644 poetry.lock delete mode 100644 pyproject.toml delete mode 100644 requirements.txt delete mode 100644 requirements_311.yml create mode 100644 roles/acl/README.md create mode 100644 roles/acl/meta/main.yml rename {ansible/roles => roles}/acl/tasks/main.yml (100%) create mode 100644 roles/ad/README.md create mode 100644 roles/ad/meta/main.yml rename {ansible/roles => roles}/ad/tasks/groups.yml (100%) rename {ansible/roles => roles}/ad/tasks/main.yml (100%) rename {ansible/roles => roles}/ad/tasks/ou.yml (100%) rename {ansible/roles => roles}/ad/tasks/users.yml (100%) create mode 100644 roles/adcs/README.md create mode 100644 roles/adcs/meta/main.yml rename {ansible/roles => roles}/adcs/tasks/main.yml (100%) create mode 100644 roles/adcs_templates/README.md rename {ansible/roles => roles}/adcs_templates/files/ADCSTemplate/.gitignore (100%) rename {ansible/roles => roles}/adcs_templates/files/ADCSTemplate/ADCSTemplate.psd1 (100%) rename {ansible/roles => roles}/adcs_templates/files/ADCSTemplate/ADCSTemplate.psm1 (100%) rename {ansible/roles => roles}/adcs_templates/files/ADCSTemplate/DSCResources/COMMUNITY_ADCSTemplate/COMMUNITY_ADCSTemplate.psm1 (100%) rename {ansible/roles => roles}/adcs_templates/files/ADCSTemplate/DSCResources/COMMUNITY_ADCSTemplate/COMMUNITY_ADCSTemplate.schema.mof (100%) rename {ansible/roles => roles}/adcs_templates/files/ADCSTemplate/Examples/Build-ADCS.ps1 (100%) rename {ansible/roles => roles}/adcs_templates/files/ADCSTemplate/Examples/Demo.ps1 (100%) rename {ansible/roles => roles}/adcs_templates/files/ADCSTemplate/Examples/PowerShellCMS.json (100%) rename {ansible/roles => roles}/adcs_templates/files/ADCSTemplate/Examples/Tanium.json (100%) rename {ansible/roles => roles}/adcs_templates/files/ADCSTemplate/LICENSE (100%) rename {ansible/roles => roles}/adcs_templates/files/ADCSTemplate/README.md (100%) rename {ansible/roles => roles}/adcs_templates/files/ESC1.json (100%) rename {ansible/roles => roles}/adcs_templates/files/ESC2.json (100%) rename {ansible/roles => roles}/adcs_templates/files/ESC3-CRA.json (100%) rename {ansible/roles => roles}/adcs_templates/files/ESC3.json (100%) rename {ansible/roles => roles}/adcs_templates/files/ESC4.json (100%) create mode 100644 roles/adcs_templates/meta/main.yml rename {ansible/roles => roles}/adcs_templates/tasks/main.yml (100%) create mode 100644 roles/child_domain/README.md create mode 100644 roles/child_domain/meta/main.yml rename {ansible/roles => roles}/child_domain/tasks/main.yml (100%) create mode 100644 roles/common/README.md create mode 100644 roles/common/meta/main.yml rename {ansible/roles => roles}/common/tasks/chocolatey.yml (100%) rename {ansible/roles => roles}/common/tasks/main.yml (100%) create mode 100644 roles/commonwkstn/README.md create mode 100644 roles/commonwkstn/meta/main.yml rename {ansible/roles => roles}/commonwkstn/tasks/main.yml (100%) create mode 100644 roles/dc_audit_sacl/README.md rename {ansible/roles => roles}/dc_audit_sacl/defaults/main.yml (100%) rename {ansible/roles => roles}/dc_audit_sacl/handlers/main.yml (100%) rename {ansible/roles => roles}/dc_audit_sacl/meta/main.yml (100%) rename {ansible/roles => roles}/dc_audit_sacl/tasks/main.yml (100%) create mode 100644 roles/dc_dns_conditional_forwarder/README.md create mode 100644 roles/dc_dns_conditional_forwarder/meta/main.yml rename {ansible/roles => roles}/dc_dns_conditional_forwarder/tasks/main.yml (100%) create mode 100644 roles/dhcp/README.md create mode 100644 roles/dhcp/meta/main.yml rename {ansible/roles => roles}/dhcp/tasks/main.yml (100%) create mode 100644 roles/disable_user/README.md create mode 100644 roles/disable_user/meta/main.yml rename {ansible/roles => roles}/disable_user/tasks/main.yml (100%) create mode 100644 roles/dns_conditional_forwarder/README.md create mode 100644 roles/dns_conditional_forwarder/meta/main.yml rename {ansible/roles => roles}/dns_conditional_forwarder/tasks/main.yml (100%) create mode 100644 roles/domain_controller/README.md create mode 100644 roles/domain_controller/meta/main.yml rename {ansible/roles => roles}/domain_controller/tasks/main.yml (100%) create mode 100644 roles/domain_controller_slave/README.md create mode 100644 roles/domain_controller_slave/meta/main.yml rename {ansible/roles => roles}/domain_controller_slave/tasks/main.yml (100%) create mode 100644 roles/elk/README.md rename {ansible/roles => roles}/elk/defaults/main.yml (100%) rename {ansible/roles => roles}/elk/files/elasticsearch.yml (100%) rename {ansible/roles => roles}/elk/files/kibana.yml (100%) create mode 100644 roles/elk/meta/main.yml rename {ansible/roles => roles}/elk/tasks/main.yml (100%) create mode 100644 roles/enable_user/README.md create mode 100644 roles/enable_user/meta/main.yml rename {ansible/roles => roles}/enable_user/tasks/main.yml (100%) create mode 100644 roles/fix_dns/README.md create mode 100644 roles/fix_dns/meta/main.yml rename {ansible/roles => roles}/fix_dns/tasks/main.yml (100%) create mode 100644 roles/gmsa/README.md create mode 100644 roles/gmsa/meta/main.yml rename {ansible/roles => roles}/gmsa/tasks/main.yml (100%) create mode 100644 roles/gmsa_hosts/README.md create mode 100644 roles/gmsa_hosts/meta/main.yml rename {ansible/roles => roles}/gmsa_hosts/tasks/main.yml (100%) create mode 100644 roles/groups_domains/README.md create mode 100644 roles/groups_domains/meta/main.yml rename {ansible/roles => roles}/groups_domains/tasks/main.yml (100%) create mode 100644 roles/iis/README.md rename {ansible/roles => roles}/iis/files/index.html (100%) create mode 100644 roles/iis/meta/main.yml rename {ansible/roles => roles}/iis/tasks/main.yml (100%) create mode 100644 roles/laps_dc/README.md rename {ansible/roles/laps/dc => roles/laps_dc}/defaults/main.yml (100%) rename {ansible/roles/laps/dc => roles/laps_dc}/files/comment.cmtx (100%) create mode 100644 roles/laps_dc/meta/main.yml rename {ansible/roles/laps/dc => roles/laps_dc}/tasks/install.yml (94%) rename {ansible/roles/laps/dc => roles/laps_dc}/tasks/main.yml (100%) rename {ansible/roles/laps/dc => roles/laps_dc}/tasks/move_server_to_ou.yml (100%) rename {ansible/roles/laps/dc => roles/laps_dc}/vars/main.yml (100%) create mode 100644 roles/laps_permissions/README.md create mode 100644 roles/laps_permissions/meta/main.yml rename {ansible/roles/laps/permissions => roles/laps_permissions}/tasks/main.yml (100%) create mode 100644 roles/laps_server/README.md create mode 100644 roles/laps_server/meta/main.yml rename {ansible/roles/laps/server => roles/laps_server}/tasks/install.yml (100%) rename {ansible/roles/laps/server => roles/laps_server}/tasks/main.yml (100%) create mode 100644 roles/laps_verify/README.md create mode 100644 roles/laps_verify/meta/main.yml rename {ansible/roles/laps/verify => roles/laps_verify}/tasks/main.yml (100%) create mode 100644 roles/ldap_diagnostic_logging/README.md rename {ansible/roles => roles}/ldap_diagnostic_logging/defaults/main.yml (100%) rename {ansible/roles => roles}/ldap_diagnostic_logging/handlers/main.yml (100%) rename {ansible/roles => roles}/ldap_diagnostic_logging/meta/main.yml (100%) rename {ansible/roles => roles}/ldap_diagnostic_logging/tasks/main.yml (100%) create mode 100644 roles/localusers/README.md create mode 100644 roles/localusers/meta/main.yml rename {ansible/roles => roles}/localusers/tasks/main.yml (100%) create mode 100644 roles/logs_windows/README.md rename {ansible/roles => roles}/logs_windows/defaults/main.yml (100%) rename {ansible/roles => roles}/logs_windows/files/Sysmon.zip (100%) rename {ansible/roles => roles}/logs_windows/files/sysmonconfig-export.xml (100%) rename {ansible/roles => roles}/logs_windows/files/uninstall-service-winlogbeat.ps1 (100%) rename {ansible/roles => roles}/logs_windows/handlers/main.yml (100%) create mode 100644 roles/logs_windows/meta/main.yml rename {ansible/roles => roles}/logs_windows/tasks/main.yml (100%) rename {ansible/roles => roles}/logs_windows/tasks/winlogbeat.yml (100%) rename {ansible/roles => roles}/logs_windows/templates/winlogbeat.yml.j2 (100%) create mode 100644 roles/member_server/README.md create mode 100644 roles/member_server/meta/main.yml rename {ansible/roles => roles}/member_server/tasks/main.yml (100%) create mode 100644 roles/move_to_ou/README.md create mode 100644 roles/move_to_ou/meta/main.yml rename {ansible/roles => roles}/move_to_ou/tasks/main.yml (100%) create mode 100644 roles/mssql/README.md rename {ansible/roles => roles}/mssql/defaults/main.yml (100%) rename {ansible/roles => roles}/mssql/files/install_sql.ps1 (100%) rename {ansible/roles => roles}/mssql/files/sql_conf.ini.MSSQL_2019.j2 (100%) rename {ansible/roles => roles}/mssql/files/sql_conf.ini.MSSQL_2022.j2 (100%) create mode 100644 roles/mssql/meta/main.yml rename {ansible/roles => roles}/mssql/tasks/config.yml (100%) rename {ansible/roles => roles}/mssql/tasks/install.yml (100%) rename {ansible/roles => roles}/mssql/tasks/main.yml (100%) create mode 100644 roles/mssql_audit/README.md rename {ansible/roles => roles}/mssql_audit/defaults/main.yml (100%) rename {ansible/roles => roles}/mssql_audit/meta/main.yml (100%) rename {ansible/roles => roles}/mssql_audit/tasks/main.yml (100%) create mode 100644 roles/mssql_link/README.md create mode 100644 roles/mssql_link/meta/main.yml rename {ansible/roles => roles}/mssql_link/tasks/logins.yml (100%) rename {ansible/roles => roles}/mssql_link/tasks/main.yml (100%) create mode 100644 roles/mssql_reporting/README.md create mode 100644 roles/mssql_reporting/meta/main.yml rename {ansible/roles => roles}/mssql_reporting/tasks/main.yml (100%) create mode 100644 roles/mssql_ssms/README.md create mode 100644 roles/mssql_ssms/meta/main.yml rename {ansible/roles => roles}/mssql_ssms/tasks/main.yml (100%) create mode 100644 roles/onlyusers/README.md create mode 100644 roles/onlyusers/meta/main.yml rename {ansible/roles => roles}/onlyusers/tasks/main.yml (92%) create mode 100644 roles/parent_child_dns/README.md create mode 100644 roles/parent_child_dns/meta/main.yml rename {ansible/roles => roles}/parent_child_dns/tasks/main.yml (100%) create mode 100644 roles/password_policy/README.md create mode 100644 roles/password_policy/meta/main.yml rename {ansible/roles => roles}/password_policy/tasks/main.yml (100%) create mode 100644 roles/ps/README.md create mode 100644 roles/ps/meta/main.yml rename {ansible/roles => roles}/ps/tasks/main.yml (100%) create mode 100644 roles/sccm_config_accounts/README.md create mode 100644 roles/sccm_config_accounts/meta/main.yml rename {ansible/roles/sccm/config/accounts => roles/sccm_config_accounts}/tasks/main.yml (100%) create mode 100644 roles/sccm_config_boundary/README.md create mode 100644 roles/sccm_config_boundary/meta/main.yml rename {ansible/roles/sccm/config/boundary => roles/sccm_config_boundary}/tasks/main.yml (90%) create mode 100644 roles/sccm_config_client_install/README.md create mode 100644 roles/sccm_config_client_install/meta/main.yml rename {ansible/roles/sccm/config/client_install => roles/sccm_config_client_install}/tasks/main.yml (100%) create mode 100644 roles/sccm_config_client_push/README.md create mode 100644 roles/sccm_config_client_push/meta/main.yml rename {ansible/roles/sccm/config/client_push => roles/sccm_config_client_push}/tasks/main.yml (100%) create mode 100644 roles/sccm_config_discovery/README.md create mode 100644 roles/sccm_config_discovery/meta/main.yml rename {ansible/roles/sccm/config/discovery => roles/sccm_config_discovery}/tasks/main.yml (100%) create mode 100644 roles/sccm_config_naa/README.md create mode 100644 roles/sccm_config_naa/meta/main.yml rename {ansible/roles/sccm/config/naa => roles/sccm_config_naa}/tasks/main.yml (100%) create mode 100644 roles/sccm_config_pxe/README.md create mode 100644 roles/sccm_config_pxe/meta/main.yml rename {ansible/roles/sccm/config/pxe => roles/sccm_config_pxe}/tasks/main.yml (100%) create mode 100644 roles/sccm_config_users/README.md create mode 100644 roles/sccm_config_users/meta/main.yml rename {ansible/roles/sccm/config/users => roles/sccm_config_users}/tasks/main.yml (100%) create mode 100644 roles/sccm_install_adk/README.md create mode 100644 roles/sccm_install_adk/meta/main.yml rename {ansible/roles/sccm/install/adk => roles/sccm_install_adk}/tasks/main.yml (100%) create mode 100644 roles/sccm_install_iis/README.md create mode 100644 roles/sccm_install_iis/meta/main.yml rename {ansible/roles/sccm/install/iis => roles/sccm_install_iis}/tasks/main.yml (100%) create mode 100644 roles/sccm_install_mecm/README.md rename {ansible/roles/sccm/install/mecm => roles/sccm_install_mecm}/files/ConfigMgrAutoSave.ini (100%) create mode 100644 roles/sccm_install_mecm/meta/main.yml rename {ansible/roles/sccm/install/mecm => roles/sccm_install_mecm}/tasks/main.yml (100%) create mode 100644 roles/sccm_install_prerequisites/README.md create mode 100644 roles/sccm_install_prerequisites/meta/main.yml rename {ansible/roles/sccm/install/prerequisites => roles/sccm_install_prerequisites}/tasks/main.yml (100%) create mode 100644 roles/sccm_install_wsus/README.md create mode 100644 roles/sccm_install_wsus/meta/main.yml rename {ansible/roles/sccm/install/wsus => roles/sccm_install_wsus}/tasks/main.yml (100%) create mode 100644 roles/sccm_pxe/README.md rename {ansible/roles/sccm/pxe => roles/sccm_pxe}/defaults/main.yml (100%) create mode 100644 roles/sccm_pxe/meta/main.yml rename {ansible/roles/sccm/pxe => roles/sccm_pxe}/tasks/main.yml (100%) create mode 100644 roles/security_account_is_sensitive/README.md create mode 100644 roles/security_account_is_sensitive/meta/main.yml rename {ansible/roles/security/account_is_sensitive => roles/security_account_is_sensitive}/tasks/main.yml (100%) create mode 100644 roles/security_asr/README.md create mode 100644 roles/security_asr/meta/main.yml rename {ansible/roles/security/asr => roles/security_asr}/tasks/main.yml (100%) create mode 100644 roles/security_audit_policy/README.md create mode 100644 roles/security_audit_policy/meta/main.yml rename {ansible/roles/security/audit_policy => roles/security_audit_policy}/tasks/main.yml (100%) create mode 100644 roles/security_enable_run_as_ppl/README.md create mode 100644 roles/security_enable_run_as_ppl/meta/main.yml rename {ansible/roles/security/enable_run_as_ppl => roles/security_enable_run_as_ppl}/tasks/main.yml (100%) create mode 100644 roles/security_ensure_kb_not_installed/README.md create mode 100644 roles/security_ensure_kb_not_installed/meta/main.yml rename {ansible/roles/security/ensure_kb_not_installed => roles/security_ensure_kb_not_installed}/tasks/main.yml (100%) create mode 100644 roles/security_powershell_restrict/README.md create mode 100644 roles/security_powershell_restrict/meta/main.yml rename {ansible/roles/security/powershell_restrict => roles/security_powershell_restrict}/tasks/main.yml (100%) create mode 100644 roles/settings_adjust_rights/README.md create mode 100644 roles/settings_adjust_rights/meta/main.yml rename {ansible/roles/settings/adjust_rights => roles/settings_adjust_rights}/tasks/main.yml (100%) create mode 100644 roles/settings_admin_password/README.md create mode 100644 roles/settings_admin_password/meta/main.yml rename {ansible/roles/settings/admin_password => roles/settings_admin_password}/tasks/main.yml (100%) create mode 100644 roles/settings_copy_files/README.md rename {ansible/roles/settings/copy_files => roles/settings_copy_files}/files/GOAD.png (100%) rename {ansible/roles/settings/copy_files => roles/settings_copy_files}/files/starks.jpg (100%) create mode 100644 roles/settings_copy_files/meta/main.yml rename {ansible/roles/settings/copy_files => roles/settings_copy_files}/tasks/main.yml (100%) create mode 100644 roles/settings_disable_nat_adapter/README.md create mode 100644 roles/settings_disable_nat_adapter/meta/main.yml rename {ansible/roles/settings/disable_nat_adapter => roles/settings_disable_nat_adapter}/tasks/main.yml (100%) create mode 100644 roles/settings_enable_nat_adapter/README.md create mode 100644 roles/settings_enable_nat_adapter/meta/main.yml rename {ansible/roles/settings/enable_nat_adapter => roles/settings_enable_nat_adapter}/tasks/main.yml (100%) create mode 100644 roles/settings_gpmc/README.md create mode 100644 roles/settings_gpmc/meta/main.yml rename {ansible/roles/settings/gpmc => roles/settings_gpmc}/tasks/main.yml (100%) create mode 100644 roles/settings_gpo_remove/README.md rename {ansible/roles/settings/gpo_remove => roles/settings_gpo_remove}/files/remove-gpo.ps1 (100%) create mode 100644 roles/settings_gpo_remove/meta/main.yml rename {ansible/roles/settings/gpo_remove => roles/settings_gpo_remove}/tasks/main.yml (100%) create mode 100644 roles/settings_hostname/README.md create mode 100644 roles/settings_hostname/meta/main.yml rename {ansible/roles/settings/hostname => roles/settings_hostname}/tasks/main.yml (100%) create mode 100644 roles/settings_keyboard/README.md create mode 100644 roles/settings_keyboard/meta/main.yml rename {ansible/roles/settings/keyboard => roles/settings_keyboard}/tasks/main.yml (100%) create mode 100644 roles/settings_no_updates/README.md create mode 100644 roles/settings_no_updates/meta/main.yml rename {ansible/roles/settings/no_updates => roles/settings_no_updates}/tasks/main.yml (100%) create mode 100644 roles/settings_updates/README.md create mode 100644 roles/settings_updates/meta/main.yml rename {ansible/roles/settings/updates => roles/settings_updates}/tasks/default.yml (100%) create mode 100644 roles/settings_user_rights/README.md create mode 100644 roles/settings_user_rights/meta/main.yml rename {ansible/roles/settings/user_rights => roles/settings_user_rights}/tasks/main.yml (100%) create mode 100644 roles/settings_windows_defender/README.md create mode 100644 roles/settings_windows_defender/meta/main.yml rename {ansible/roles/settings/windows_defender => roles/settings_windows_defender}/tasks/main.yml (100%) create mode 100644 roles/sync_domains/README.md create mode 100644 roles/sync_domains/meta/main.yml rename {ansible/roles => roles}/sync_domains/tasks/main.yml (100%) create mode 100644 roles/trusts/README.md create mode 100644 roles/trusts/meta/main.yml rename {ansible/roles => roles}/trusts/tasks/main.yml (100%) create mode 100644 roles/vulns_acls/README.md create mode 100644 roles/vulns_acls/meta/main.yml rename {ansible/roles/vulns/acls => roles/vulns_acls}/tasks/main.yml (100%) create mode 100644 roles/vulns_adcs_templates/README.md rename {ansible/roles/vulns/adcs_templates => roles/vulns_adcs_templates}/files/ADCSTemplate/.gitignore (100%) rename {ansible/roles/vulns/adcs_templates => roles/vulns_adcs_templates}/files/ADCSTemplate/ADCSTemplate.psd1 (100%) rename {ansible/roles/vulns/adcs_templates => roles/vulns_adcs_templates}/files/ADCSTemplate/ADCSTemplate.psm1 (100%) rename {ansible/roles/vulns/adcs_templates => roles/vulns_adcs_templates}/files/ADCSTemplate/DSCResources/COMMUNITY_ADCSTemplate/COMMUNITY_ADCSTemplate.psm1 (100%) rename {ansible/roles/vulns/adcs_templates => roles/vulns_adcs_templates}/files/ADCSTemplate/DSCResources/COMMUNITY_ADCSTemplate/COMMUNITY_ADCSTemplate.schema.mof (100%) rename {ansible/roles/vulns/adcs_templates => roles/vulns_adcs_templates}/files/ADCSTemplate/Examples/Build-ADCS.ps1 (100%) rename {ansible/roles/vulns/adcs_templates => roles/vulns_adcs_templates}/files/ADCSTemplate/Examples/Demo.ps1 (100%) rename {ansible/roles/vulns/adcs_templates => roles/vulns_adcs_templates}/files/ADCSTemplate/Examples/PowerShellCMS.json (100%) rename {ansible/roles/vulns/adcs_templates => roles/vulns_adcs_templates}/files/ADCSTemplate/Examples/Tanium.json (100%) rename {ansible/roles/vulns/adcs_templates => roles/vulns_adcs_templates}/files/ADCSTemplate/LICENSE (100%) rename {ansible/roles/vulns/adcs_templates => roles/vulns_adcs_templates}/files/ADCSTemplate/README.md (100%) create mode 100644 roles/vulns_adcs_templates/meta/main.yml rename {ansible/roles/vulns/adcs_templates => roles/vulns_adcs_templates}/tasks/main.yml (100%) create mode 100644 roles/vulns_administrator_folder/README.md create mode 100644 roles/vulns_administrator_folder/meta/main.yml rename {ansible/roles/vulns/administrator_folder => roles/vulns_administrator_folder}/tasks/main.yml (100%) create mode 100644 roles/vulns_anonymous_enum/README.md create mode 100644 roles/vulns_anonymous_enum/meta/main.yml rename {ansible/roles/vulns/anonymous_enum => roles/vulns_anonymous_enum}/tasks/main.yml (100%) create mode 100644 roles/vulns_autologon/README.md create mode 100644 roles/vulns_autologon/meta/main.yml rename {ansible/roles/vulns/autologon => roles/vulns_autologon}/tasks/main.yml (100%) create mode 100644 roles/vulns_credentials/README.md create mode 100644 roles/vulns_credentials/meta/main.yml rename {ansible/roles/vulns/credentials => roles/vulns_credentials}/tasks/main.yml (100%) create mode 100644 roles/vulns_directory/README.md create mode 100644 roles/vulns_directory/meta/main.yml rename {ansible/roles/vulns/directory => roles/vulns_directory}/tasks/main.yml (100%) create mode 100644 roles/vulns_disable_firewall/README.md create mode 100644 roles/vulns_disable_firewall/meta/main.yml rename {ansible/roles/vulns/disable_firewall => roles/vulns_disable_firewall}/tasks/main.yml (100%) create mode 100644 roles/vulns_enable_credssp_client/README.md create mode 100644 roles/vulns_enable_credssp_client/meta/main.yml rename {ansible/roles/vulns/enable_credssp_client => roles/vulns_enable_credssp_client}/tasks/main.yml (75%) create mode 100644 roles/vulns_enable_credssp_server/README.md create mode 100644 roles/vulns_enable_credssp_server/meta/main.yml rename {ansible/roles/vulns/enable_credssp_server => roles/vulns_enable_credssp_server}/tasks/main.yml (69%) create mode 100644 roles/vulns_enable_llmnr/README.md create mode 100644 roles/vulns_enable_llmnr/meta/main.yml rename {ansible/roles/vulns/enable_llmnr => roles/vulns_enable_llmnr}/tasks/main.yml (100%) create mode 100644 roles/vulns_enable_nbt_ns/README.md create mode 100644 roles/vulns_enable_nbt_ns/meta/main.yml rename {ansible/roles/vulns/enable_nbt-ns => roles/vulns_enable_nbt_ns}/tasks/main.yml (100%) create mode 100644 roles/vulns_files/README.md create mode 100644 roles/vulns_files/meta/main.yml rename {ansible/roles/vulns/files => roles/vulns_files}/tasks/main.yml (100%) create mode 100644 roles/vulns_mssql/README.md create mode 100644 roles/vulns_mssql/meta/main.yml rename {ansible/roles/vulns/mssql => roles/vulns_mssql}/tasks/main.yml (100%) create mode 100644 roles/vulns_ntlmdowngrade/README.md create mode 100644 roles/vulns_ntlmdowngrade/meta/main.yml rename {ansible/roles/vulns/ntlmdowngrade => roles/vulns_ntlmdowngrade}/tasks/main.yml (100%) create mode 100644 roles/vulns_openshares/README.md create mode 100644 roles/vulns_openshares/meta/main.yml rename {ansible/roles/vulns/openshares => roles/vulns_openshares}/tasks/main.yml (100%) create mode 100644 roles/vulns_permissions/README.md create mode 100644 roles/vulns_permissions/meta/main.yml rename {ansible/roles/vulns/permissions => roles/vulns_permissions}/tasks/main.yml (100%) create mode 100644 roles/vulns_schedule/README.md create mode 100644 roles/vulns_schedule/meta/main.yml rename {ansible/roles/vulns/schedule => roles/vulns_schedule}/tasks/main.yml (100%) create mode 100644 roles/vulns_shares/README.md create mode 100644 roles/vulns_shares/meta/main.yml rename {ansible/roles/vulns/shares => roles/vulns_shares}/tasks/main.yml (100%) create mode 100644 roles/vulns_smbv1/README.md create mode 100644 roles/vulns_smbv1/meta/main.yml rename {ansible/roles/vulns/smbv1 => roles/vulns_smbv1}/tasks/main.yml (100%) create mode 100644 roles/webdav/README.md create mode 100644 roles/webdav/meta/main.yml rename {ansible/roles => roles}/webdav/tasks/main.yml (100%) delete mode 100644 template/provider/aws/instance-init.ps1.tpl delete mode 100755 template/provider/aws/instance-init.sh.tpl delete mode 100755 template/provider/aws/jumpbox-init.sh.tpl delete mode 100644 template/provider/aws/jumpbox.tf delete mode 100644 template/provider/aws/linux.tf delete mode 100644 template/provider/aws/main.tf delete mode 100644 template/provider/aws/network.tf delete mode 100644 template/provider/aws/outputs.tf delete mode 100644 template/provider/aws/variables.tf delete mode 100644 template/provider/aws/windows.tf delete mode 100644 template/provider/azure/jumpbox.tf delete mode 100644 template/provider/azure/linux.tf delete mode 100644 template/provider/azure/main.tf delete mode 100644 template/provider/azure/network.tf delete mode 100644 template/provider/azure/outputs.tf delete mode 100644 template/provider/azure/variables.tf delete mode 100644 template/provider/azure/windows.tf delete mode 100644 template/provider/ludus/config.yml delete mode 100644 template/provider/proxmox/main.tf delete mode 100644 template/provider/proxmox/variables.tf delete mode 100644 template/provider/proxmox/windows.tf delete mode 100644 template/provider/virtualbox/Vagrantfile delete mode 100644 template/provider/vmware/Vagrantfile delete mode 100644 template/provider/vmware_esxi/.env delete mode 100644 template/provider/vmware_esxi/Vagrantfile delete mode 100644 tools/variant_generator/README.md delete mode 100644 tools/variant_generator/__init__.py delete mode 100755 tools/variant_generator/goad_variant_generator.py delete mode 100755 tools/variant_generator/name_generator.py delete mode 100644 vagrant/ConfigureRemotingForAnsible.ps1 delete mode 100644 vagrant/Install-WMF3Hotfix.ps1 delete mode 100644 vagrant/fix_ip.ps1 delete mode 100644 workspace/.git_keep diff --git a/.gitignore b/.gitignore index 43854939..08f71ee5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,47 +1,34 @@ -.vagrant/ .idea/ .venv/ -.archives/ -writeup/ -docs/scenarios/ -docs/notes.md -temp/ -ansible/.venv/ -ansible/collections/ -ansible/test.yml -*VBoxHeadless*.log -.terraform/ -.terraform.lock.hcl -*.tfstate* -tfplan -*.pem +.DS_Store +__pycache__/ +*.pyc +*.tar.gz +*.log +*retry + +# Ansible artifacts +.ansible/ +.task/ + +# Build artifacts +roles/adcs_templates/files/ADCSTemplate.zip +roles/vulns_adcs_templates/files/ADCSTemplate.zip + +# Scenario data (keep only tracked environments) ad/PURPLE ad/REDLAB ad/EDRLAB ad/DEMO ad/FEDGOAD -ansible/roles/edr -ansible/edr.yml -ansible/private_data_dir/artifacts/ -.vscode ad/MINILAB + +# Keys and secrets +*.pem ad/*/providers/*/ssh_keys/*id_rsa* ad/*/providers/*/ssh_keys/*.pub ad/*/providers/*/extensions/*.rb -__pycache__/ -*.pyc -workspace/* -todo.md -next_extensions/ -/extensions/exchange/ansible/iso/resources/iso/*.ISO -docs/site/ -docs/olddocs/ -docs/mkdocs/site/ -scripts/archives/ -.task -*retry -*.log -ansible/.\\AnsiballZ_command.ps1 -.ansible -ansible/roles/adcs_templates/files/ADCSTemplate.zip -ansible/roles/vulns/adcs_templates/files/ADCSTemplate.zip + +# IDE / OS +.vscode +temp/ diff --git a/.hooks/linters/markdownlint.json b/.hooks/linters/markdownlint.json index 1ec7abaa..fce036cd 100644 --- a/.hooks/linters/markdownlint.json +++ b/.hooks/linters/markdownlint.json @@ -12,6 +12,7 @@ "MD055": false, "MD056": false, "MD057": false, + "MD060": false, "line-length": false, "no-multiple-blanks": false } diff --git a/.hooks/templates/docsible-template.md.j2 b/.hooks/templates/docsible-template.md.j2 index b8fd21ff..afcfb167 100755 --- a/.hooks/templates/docsible-template.md.j2 +++ b/.hooks/templates/docsible-template.md.j2 @@ -23,7 +23,7 @@ ### Default Variables ({{ defaultfile.file }}) | Variable | Type | Default | Description | -|----------|------|---------|-------------| +| -------- | ---- | ------- | ----------- | {%- for key, details in defaultfile.data.items() %} {%- if not key.endswith('.0') and not key.endswith('.1') and not key.endswith('.2') and not key.endswith('.3') and not key.endswith('.4') and not key.endswith('.5') and not key.endswith('.6') and '.' not in key or key.count('.') == 1 %} | `{{ key }}` | {{ details.type }} | `{{ details.value }}` | {{ details.description or 'No description' }} | @@ -36,7 +36,7 @@ ### Role Variables ({{ varsfile.file }}) | Variable | Type | Value | Description | -|----------|------|-------|-------------| +| -------- | ---- | ----- | ----------- | {%- for key, details in varsfile.data.items() %} | `{{ key }}` | {{ details.type }} | `{{ details.value }}` | {{ details.description or 'No description' }} | {%- endfor %} @@ -63,7 +63,7 @@ ## Author Information - **Author**: {{ role.meta.galaxy_info.author }} -- **Company**: {{ role.meta.galaxy_info.company }} +- **Company**:{% if role.meta.galaxy_info.company %} {{ role.meta.galaxy_info.company }}{% endif %} - **License**: {{ role.meta.galaxy_info.license }} ## Platforms diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index f0d14028..00000000 --- a/Dockerfile +++ /dev/null @@ -1,16 +0,0 @@ -FROM ubuntu:24.04 - -RUN apt-get update \ - && apt-get install -y python3-pip - -RUN pip install --upgrade pip -RUN pip install ansible-core==2.12.6 -RUN pip install pywinrm - -RUN apt-get update -y && \ - DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ - sshpass lftp rsync openssh-client - -COPY ./ansible/requirements.yml . - -RUN ansible-galaxy install -r requirements.yml diff --git a/README.md b/README.md index 57607bb5..b790c5ad 100644 --- a/README.md +++ b/README.md @@ -1,278 +1,340 @@ -
-

GOAD (Game Of Active Directory)

-
-
+# dreadnode.goad -## 🚀 Overview +Ansible collection for deploying and configuring vulnerable Active Directory +lab environments for penetration testing and security research. -**DreadGOAD** is a heavily refactored version of -[GOAD (Game of Active Directory)](https://github.com/Orange-Cyberdefense/GOAD), -specifically tailored for efficient Active Directory (AD) pentesting -environments. It simplifies infrastructure provisioning using Terraform and -Ansible under the [DreadOps Project](https://github.com/dreadnode/DreadOps), -specifically within the [alpha-operator-range](https://github.com/dreadnode/DreadOps/tree/main/dread-infra/alpha-operator-range) -deployment. - -📖 **Legacy Documentation:** For historical reference, see [Original GOAD Documentation](./docs/original-readme.md). - ---- - -## 📋 Vulnerable Lab - -Currently, DreadGOAD provides the following windows-based lab environment: - -- [GOAD](https://orange-cyberdefense.github.io/GOAD/labs/GOAD/) : 5 VMs, 2 - forests, 3 domains - -
-GOAD -
- -**Please note:** - -- All of the other original GOAD labs are deprecated and unsupported. -- The IP addresses found in the above schema diagram are not accurate for the - DreadGOAD environment. Please refer to the - [AWS console](#-access-via-the-aws-console) for the correct IP addresses. - ---- - -## ⚙️ Getting Started - -DreadGOAD provisioning and management utilize Ansible and AWS Systems Manager -(SSM), orchestrated via [Task](https://taskfile.dev). Follow these steps to set -up and deploy the lab environment: - -### ✅ Prerequisites - -Before provisioning, ensure the following are installed and configured: - -- [AWS CLI](https://aws.amazon.com/cli/) -- [jq](https://stedolan.github.io/jq/) -- [Task](https://taskfile.dev) (`brew install go-task/tap/go-task`) - -### 🚧 Provisioning the Environment - -1. **Set Task environment variable:** - - ```bash - export TASK_X_REMOTE_TASKFILES=1 - ``` - -2. **List available Ansible playbooks:** - - ```bash - task -y list-plays - ``` - -3. **Update the Ansible inventory with AWS instance IDs:** - - ```bash - task -y update-inventory ENV=dev --force - ``` - -4. **Generate instance-to-IP mapping (recommended for faster provisioning):** - - ```bash - task generate-mapping ENV=dev - ``` - - This pre-computes instance ID → private IP mappings and caches them, skipping - the slow PowerShell network detection on each playbook run. This saves ~30-40 - seconds per playbook execution. - - > **Note:** Re-run this command if infrastructure changes (instances replaced, - > IPs changed, etc.) - -5. **Provision the AD environment:** - - ```bash - task provision ENV=dev - ``` - - > **Note:** Full provisioning of the DreadGOAD environment typically takes - > approximately **2.5 hours** to complete all playbooks. - ---- - -### 🛠️ Useful Task Examples - -- **Provision using specific playbooks:** - - ```bash - task provision PLAYS="build.yml ad-servers.yml" ENV=staging - ``` - -- **Limit execution to specific hosts:** - - ```bash - task provision PLAYS=laps.yml LIMIT=srv03 - ``` - -- **Combine specific playbooks with host limits:** - - ```bash - task provision LIMIT="dc01,srv03" PLAYS="ad-members.yml laps.yml" - ``` - -- **Generate instance mapping for staging environment:** - - ```bash - task generate-mapping ENV=staging - ``` - -- **Inspect files related to specific playbooks:** - - ```bash - task get-files PLAYBOOK=security - ``` - -- **Run with verbose output for debugging:** - - ```bash - task provision PLAYS="ad-data.yml" DEBUG=true - ``` +Based on [GOAD (Game of Active Directory)](https://github.com/Orange-Cyberdefense/GOAD) +by Orange Cyberdefense. --- -## 🔐 Accessing Provisioned DreadGOAD Systems - -You can access the provisioned DreadGOAD systems through several methods -detailed below: - -### 📌 Access via the AWS Console - -**Step 1:** Navigate to the [AWS account portal](https://dreadnode.awsapps.com/start/#/?tab=accounts). - -**Step 2:** Click the **Administrator** link under the **Dreadnode - Lab** -account. If you do not have access, please contact Jayson or Nick. - -![AWS Account](docs/img/dreadGOAD/aws-account.png) - -**Step 3:** Click the **EC2** link on the left-hand side and navigate to the -running instances. - -![Running Instances](docs/img/dreadGOAD/running-instances.png) - -> **Note:** Ensure you are viewing the correct region: -> -> - **dev**: `us-west-2` -> - **staging**: `us-west-1` - -**Step 4:** Right-click the instance you want to access and select **Connect**. +## Architecture Diagram + +```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] +``` -![Connect Instance](docs/img/dreadGOAD/connect-step-one.png) +## Requirements -**Step 5:** Under the **Session Manager** tab, click **Connect**. +- Ansible >= 2.15 +- Windows target hosts accessible via WinRM or AWS SSM -![Session Manager Connect](docs/img/dreadGOAD/connect-step-two.png) +### Collection Dependencies -You should now have a PowerShell terminal open in your browser. +- `ansible.windows` >= 2.5.0 +- `community.general` +- `community.windows` >= 2.3.0 +- `chocolatey.chocolatey` >= 1.5.3 +- `microsoft.ad` --- -### 📌 Access via AWS CLI - -**Step 1:** [Install the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html). +## Installation -**Step 2:** Create a new profile in your `~/.aws/config`: +### From source ```bash -################################################################################ -############################### Dreadnode ###################################### -[sso-session organization-sso] -cli_pager= -sso_start_url = https://dreadnode.awsapps.com/start/# -sso_region = us-east-1 -sso_registration_scopes = sso:account:access - -[profile lab] -cli_pager= -sso_session = organization-sso -sso_account_id = 381491903301 -sso_role_name = Administrator -region = us-west-2 -output = json +ansible-galaxy collection build . +ansible-galaxy collection install dreadnode-goad-1.0.0.tar.gz ``` -**Step 3:** Log in via the AWS CLI: +### Install dependencies ```bash -export AWS_PROFILE=lab -export AWS_SDK_LOAD_CONFIG=1 -export AWS_DEFAULT_REGION=us-west-2 -aws sso login --profile lab --region us-west-2 +ansible-galaxy collection install -r requirements.yml ``` -**Step 4:** Install the Session Manager plugin: - -```bash -brew install cask session-manager-plugin --no-quarantine -``` - -**Step 5:** Start a session with: - -```bash -aws ssm start-session --target $INSTANCE_ID -``` - -> Replace `$INSTANCE_ID` with the ID of your desired instance. - --- -### 📌 Access via RDP +## Lab Environment -**Step 1:** Start a port forwarding session: +The GOAD lab provides: -```bash -aws ssm start-session --target $INSTANCE_ID --document-name AWS-StartPortForwardingSession --parameters "portNumber=3389,localPortNumber=13390" -``` - -> Replace `$INSTANCE_ID` with the ID of your desired instance. You can use any -> local port number. +- **3 domains**: `sevenkingdoms.local`, `north.sevenkingdoms.local`, + `essos.local` +- **2 forests** with cross-domain trusts +- **5-6 hosts**: Domain controllers + member servers (Windows Server 2016/2019) -**Step 2:** Open **Remote Desktop Connection** and connect to `localhost:13390`. +--- -Log in using either: +## Roles + +### Active Directory + +| Role | Description | +| ---- | ----------- | +| `domain_controller` | Promote server to domain controller | +| `domain_controller_slave` | Add replica domain controller | +| `child_domain` | Create child domain | +| `member_server` | Join server to domain | +| `ad` | Create AD users, groups, and OUs | +| `acl` | Configure AD ACLs and permissions | +| `adcs` | Install Active Directory Certificate Services | +| `adcs_templates` | Deploy ADCS certificate templates | +| `trusts` | Configure cross-domain trusts | +| `gmsa` | Configure group managed service accounts | +| `gmsa_hosts` | Configure gMSA host permissions | +| `password_policy` | Set domain password policies | +| `move_to_ou` | Move objects to organizational units | +| `groups_domains` | Configure cross-domain group membership | +| `dns_conditional_forwarder` | Configure DNS conditional forwarders | +| `dc_dns_conditional_forwarder` | Configure DC-specific DNS forwarders | +| `parent_child_dns` | Configure parent-child domain DNS | +| `sync_domains` | Synchronize domain data | +| `onlyusers` | Create AD users only | +| `disable_user` | Disable AD user accounts | +| `enable_user` | Enable AD user accounts | + +### Server Roles + +| Role | Description | +| ---- | ----------- | +| `common` | Base server configuration (DNS, proxy, modules) | +| `commonwkstn` | Workstation-specific configuration | +| `iis` | Install and configure IIS | +| `mssql` | Install and configure SQL Server | +| `mssql_link` | Configure SQL Server linked servers | +| `mssql_ssms` | Install SQL Server Management Studio | +| `mssql_reporting` | Install SQL Server Reporting Services | +| `mssql_audit` | Configure SQL Server audit logging | +| `elk` | Install Elasticsearch, Logstash, Kibana | +| `logs_windows` | Configure Windows event logging | +| `webdav` | Configure WebDAV server | +| `dhcp` | Configure DHCP server | +| `localusers` | Manage local user accounts | +| `fix_dns` | Fix DNS configuration issues | +| `ps` | Execute PowerShell scripts | + +### LAPS + +| Role | Description | +| ---- | ----------- | +| `laps_dc` | Install LAPS on domain controllers | +| `laps_server` | Install LAPS on member servers | +| `laps_verify` | Verify LAPS installation | +| `laps_permissions` | Configure LAPS permissions | + +### Settings + +| Role | Description | +| ---- | ----------- | +| `settings_hostname` | Set Windows hostname | +| `settings_admin_password` | Set local admin password | +| `settings_keyboard` | Configure keyboard layout | +| `settings_no_updates` | Disable Windows updates | +| `settings_updates` | Run Windows updates | +| `settings_windows_defender` | Enable/disable Windows Defender | +| `settings_copy_files` | Copy files to target hosts | +| `settings_adjust_rights` | Adjust local group membership | +| `settings_user_rights` | Configure user rights assignments | +| `settings_disable_nat_adapter` | Disable NAT network adapter | +| `settings_enable_nat_adapter` | Enable NAT network adapter | +| `settings_gpmc` | Install Group Policy Management Console | +| `settings_gpo_remove` | Remove Group Policy Objects | + +### Security + +| Role | Description | +| ---- | ----------- | +| `security_account_is_sensitive` | Mark accounts as sensitive | +| `security_asr` | Configure Attack Surface Reduction | +| `security_audit_policy` | Configure audit policies | +| `security_enable_run_as_ppl` | Enable RunAsPPL for LSASS | +| `security_ensure_kb_not_installed` | Ensure specific KBs not installed | +| `security_powershell_restrict` | Restrict PowerShell execution | +| `dc_audit_sacl` | Configure DC SACL auditing | +| `ldap_diagnostic_logging` | Configure LDAP diagnostic logging | + +### Vulnerabilities + +| Role | Description | +| ---- | ----------- | +| `vulns_disable_firewall` | Disable Windows Firewall | +| `vulns_credentials` | Plant credentials in various locations | +| `vulns_autologon` | Configure autologon credentials | +| `vulns_shares` | Create vulnerable file shares | +| `vulns_openshares` | Create open file shares | +| `vulns_directory` | Create vulnerable directories | +| `vulns_files` | Deploy vulnerable files | +| `vulns_enable_llmnr` | Enable LLMNR | +| `vulns_enable_nbt_ns` | Enable NBT-NS | +| `vulns_smbv1` | Enable SMBv1 | +| `vulns_ntlmdowngrade` | Downgrade NTLM settings | +| `vulns_enable_credssp_client` | Enable CredSSP client | +| `vulns_enable_credssp_server` | Enable CredSSP server | +| `vulns_anonymous_enum` | Enable anonymous enumeration | +| `vulns_administrator_folder` | Create vulnerable admin folders | +| `vulns_permissions` | Configure vulnerable permissions | +| `vulns_acls` | Configure vulnerable ACLs | +| `vulns_schedule` | Create vulnerable scheduled tasks | +| `vulns_mssql` | Configure MSSQL vulnerabilities | +| `vulns_adcs_templates` | Deploy vulnerable ADCS templates | + +### SCCM + +| Role | Description | +| ---- | ----------- | +| `sccm_install_prerequisites` | Install SCCM prerequisites | +| `sccm_install_iis` | Install IIS for SCCM | +| `sccm_install_adk` | Install Windows ADK | +| `sccm_install_wsus` | Install WSUS | +| `sccm_install_mecm` | Install MECM/SCCM | +| `sccm_config_discovery` | Configure SCCM discovery | +| `sccm_config_boundary` | Configure SCCM boundaries | +| `sccm_config_accounts` | Configure SCCM accounts | +| `sccm_config_client_push` | Configure client push installation | +| `sccm_config_client_install` | Install SCCM client | +| `sccm_config_naa` | Configure network access account | +| `sccm_config_pxe` | Configure PXE boot | +| `sccm_config_users` | Configure SCCM users | +| `sccm_pxe` | Configure PXE deployment | -- The `Administrator` account with the password located in the - environment-specific DreadOPS SOPS file, for example: +--- -> - **Dev (us-west-2):** [https://github.com/dreadnode/DreadOps/tree/main/dread-infra/alpha-operator-range/dev/us-west-2/secrets](https://github.com/dreadnode/DreadOps/tree/main/dread-infra/alpha-operator-range/dev/us-west-2/secrets) -> - **Staging (us-west-1):** [https://github.com/dreadnode/DreadOps/tree/main/dread-infra/alpha-operator-range/staging/us-west-1/secrets](https://github.com/dreadnode/DreadOps/tree/main/dread-infra/alpha-operator-range/staging/us-west-1/secrets) +## Custom Modules -or: +| Module | Description | +| ------ | ----------- | +| `win_ad_dacl` | Manage AD ACL/DACL entries | +| `win_ad_object` | Create/modify AD objects | +| `win_gpo` | Create/modify Group Policy Objects | +| `win_gpo_link` | Link GPOs to OUs | +| `win_gpo_reg` | Manage GPO registry settings | +| `sccm_boundary` | Manage SCCM boundaries | +| `sccm_boundary_group` | Manage SCCM boundary groups | +| `sccm_boundary_to_boundarygroup` | Map boundaries to groups | -- Any domain user/password combination listed in the corresponding - environment-specific configuration file, such as: +--- -> - `ad/GOAD/data/dev-config.json` -> - `ad/GOAD/data/staging-config.json` +## Usage +```yaml --- +- name: Deploy GOAD lab + hosts: all + collections: + - dreadnode.goad + + roles: + - role: dreadnode.goad.common + - role: dreadnode.goad.domain_controller +``` -## 🔗 Additional Resources +For full orchestration, use the playbooks in the `playbooks/` directory with +the Taskfile: -- [GOAD Vulnerabilities & Attack Scenarios](./docs/GOAD-vulnerabilities-comprehensive.md) -- [Taskfile Reference](./docs/taskfile.md) -- [Troubleshooting Guide](./docs/troubleshooting.md) -- [Synchronizing DreadGOAD with Upstream](./docs/sync-upstream.md) +```bash +task provision ENV=dev +``` --- -## 🚨 Important Notes +## License -- **AWS CLI configuration** (`aws configure`) is required. -- Run `update-inventory` when instance IDs change. -- Run `generate-mapping` after infrastructure changes for optimal performance. -- Provisioning tasks handle retries and error handling automatically. -- The mapping file (`/tmp/aws_instance_mapping.json`) speeds up provisioning by - ~30-40 seconds per playbook run. +GPL-3.0-or-later --- -## 🛡️ Disclaimer +## Disclaimer -This lab environment is intentionally vulnerable and is strictly intended for -security research. **Do not deploy this environment publicly or use it as a -template for production environments.** +This collection deploys intentionally vulnerable configurations for security +research and penetration testing. **Do not use in production environments.** diff --git a/Taskfile.yaml b/Taskfile.yaml index 1d0b2b11..cd963727 100644 --- a/Taskfile.yaml +++ b/Taskfile.yaml @@ -22,7 +22,7 @@ vars: VERBOSE_FLAG: '{{if eq .DEBUG "true"}}-vvv{{else}}{{end}}' env: - ANSIBLE_CONFIG: './ansible/ansible.cfg' + ANSIBLE_CONFIG: './ansible.cfg' ANSIBLE_CACHE_PLUGIN_CONNECTION: '$HOME/.ansible/cache/{{.ENV}}_dreadgoad_facts' ANSIBLE_HOST_KEY_CHECKING: 'False' ANSIBLE_RETRY_FILES_ENABLED: 'True' @@ -135,11 +135,11 @@ tasks: desc: Create ADCSTemplate.zip files for ADCS roles internal: true cmds: - - cd ansible/roles/adcs_templates/files && zip -r ADCSTemplate.zip ADCSTemplate/ - - cd ansible/roles/vulns/adcs_templates/files && zip -r ADCSTemplate.zip ADCSTemplate/ + - cd roles/adcs_templates/files && zip -r ADCSTemplate.zip ADCSTemplate/ + - cd roles/vulns_adcs_templates/files && zip -r ADCSTemplate.zip ADCSTemplate/ status: - - test -f ansible/roles/adcs_templates/files/ADCSTemplate.zip - - test -f ansible/roles/vulns/adcs_templates/files/ADCSTemplate.zip + - test -f roles/adcs_templates/files/ADCSTemplate.zip + - test -f roles/vulns_adcs_templates/files/ADCSTemplate.zip log-provision-header: internal: true @@ -157,7 +157,7 @@ tasks: echo "" echo "Playbooks to be executed:" for playbook in $(echo '{{.PLAYS}}' | tr '\n' ' '); do - echo " - ansible/$playbook" + echo " - playbooks/$playbook" done echo "-----------------------------------------------" } | tee "{{.LOG_FILE}}" diff --git a/ad/GOAD-Light/data/config.json b/ad/GOAD-Light/data/config.json index 0c20da4f..51b04d07 100644 --- a/ad/GOAD-Light/data/config.json +++ b/ad/GOAD-Light/data/config.json @@ -67,7 +67,7 @@ "gpo_abuse.ps1", "rdp_scheduler.ps1" ], - "vulns" : ["disable_firewall", "directory", "credentials", "autologon", "files", "ntlmdowngrade", "enable_llmnr", "enable_nbt-ns", "shares"], + "vulns" : ["disable_firewall", "directory", "credentials", "autologon", "files", "ntlmdowngrade", "enable_llmnr", "enable_nbt_ns", "shares"], "vulns_vars" : { "directory": { "setup": "C:\\setup" diff --git a/ad/GOAD-variant-1/data/config.json b/ad/GOAD-variant-1/data/config.json index 61d95e19..78c4b6a4 100644 --- a/ad/GOAD-variant-1/data/config.json +++ b/ad/GOAD-variant-1/data/config.json @@ -68,7 +68,7 @@ "autologon", "files", "enable_llmnr", - "enable_nbt-ns", + "enable_nbt_ns", "shares" ], "vulns_vars": { diff --git a/ad/GOAD-variant-1/data/dev-config.json b/ad/GOAD-variant-1/data/dev-config.json index a6534649..cf02bb17 100644 --- a/ad/GOAD-variant-1/data/dev-config.json +++ b/ad/GOAD-variant-1/data/dev-config.json @@ -69,7 +69,7 @@ "autologon", "files", "enable_llmnr", - "enable_nbt-ns", + "enable_nbt_ns", "shares", "anonymous_enum" ], diff --git a/ad/GOAD-variant-1/data/staging-config.json b/ad/GOAD-variant-1/data/staging-config.json index 600f3b98..dfdf3ba4 100644 --- a/ad/GOAD-variant-1/data/staging-config.json +++ b/ad/GOAD-variant-1/data/staging-config.json @@ -69,7 +69,7 @@ "autologon", "files", "enable_llmnr", - "enable_nbt-ns", + "enable_nbt_ns", "shares", "anonymous_enum" ], diff --git a/ad/GOAD/data/config.json b/ad/GOAD/data/config.json index 520885f0..ed667279 100644 --- a/ad/GOAD/data/config.json +++ b/ad/GOAD/data/config.json @@ -50,7 +50,7 @@ "gpo_abuse.ps1", "rdp_scheduler.ps1" ], - "vulns" : ["disable_firewall","directory", "credentials", "autologon", "files", "enable_llmnr", "enable_nbt-ns", "shares"], + "vulns" : ["disable_firewall","directory", "credentials", "autologon", "files", "enable_llmnr", "enable_nbt_ns", "shares"], "vulns_vars" : { "directory": { "setup": "C:\\setup" diff --git a/ad/GOAD/data/dev-config.json b/ad/GOAD/data/dev-config.json index 64f18fda..773aba24 100644 --- a/ad/GOAD/data/dev-config.json +++ b/ad/GOAD/data/dev-config.json @@ -51,7 +51,7 @@ "rdp_scheduler.ps1", "unconstrained_delegation_user.ps1" ], - "vulns" : ["disable_firewall","directory", "credentials", "autologon", "files", "enable_llmnr", "enable_nbt-ns", "shares", "anonymous_enum"], + "vulns" : ["disable_firewall","directory", "credentials", "autologon", "files", "enable_llmnr", "enable_nbt_ns", "shares", "anonymous_enum"], "vulns_vars" : { "directory": { "setup": "C:\\setup" diff --git a/ad/GOAD/data/staging-config.json b/ad/GOAD/data/staging-config.json index 4aff0e27..8193c49a 100644 --- a/ad/GOAD/data/staging-config.json +++ b/ad/GOAD/data/staging-config.json @@ -51,7 +51,7 @@ "rdp_scheduler.ps1", "unconstrained_delegation_user.ps1" ], - "vulns" : ["disable_firewall","directory", "credentials", "autologon", "files", "enable_llmnr", "enable_nbt-ns", "shares", "anonymous_enum"], + "vulns" : ["disable_firewall","directory", "credentials", "autologon", "files", "enable_llmnr", "enable_nbt_ns", "shares", "anonymous_enum"], "vulns_vars" : { "directory": { "setup": "C:\\setup" diff --git a/ansible/ansible.cfg b/ansible.cfg similarity index 91% rename from ansible/ansible.cfg rename to ansible.cfg index 662eb10c..43731d6e 100644 --- a/ansible/ansible.cfg +++ b/ansible.cfg @@ -2,10 +2,14 @@ # Core settings host_key_checking = False forks = 3 -retry_files_enabled = True +retry_files_enabled = False deprecation_warnings = False no_log = False +# Collection and role paths +roles_path = ~/.ansible/roles:./roles +collections_path = ~/.ansible/collections + # Remote temp directory for Windows SSM connections remote_tmp = C:\\Windows\\Temp diff --git a/ansible/build.yml b/ansible/build.yml deleted file mode 100644 index d99301cd..00000000 --- a/ansible/build.yml +++ /dev/null @@ -1,22 +0,0 @@ ---- -# Load data -- name: Import Data - ansible.builtin.import_playbook: data.yml - tags: data - -- name: Build all - hosts: domain - roles: - - { role: 'common', tags: 'common', http_proxy: "{{ enable_http_proxy }}"} - - { role: 'settings/keyboard', tags: 'keyboard', layouts: "{{ keyboard_layouts }}" } - -# do not add srv with no update -> generate error on iis install -- name: Build all no update - hosts: no_update - roles: - - { role: 'settings/no_updates', tags: 'no_updates' } - -- name: Launch windows updates before continue - hosts: update - roles: - - { role: 'settings/updates', tags: 'updates'} diff --git a/ansible/disable_vagrant.yml b/ansible/disable_vagrant.yml deleted file mode 100644 index 54288156..00000000 --- a/ansible/disable_vagrant.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -- name: "Disable vagrant" - hosts: domain - roles: - - { role: 'disable_user', tags: 'disable_vagrant', username: "vagrant"} diff --git a/ansible/enable_vagrant.yml b/ansible/enable_vagrant.yml deleted file mode 100644 index 007f059a..00000000 --- a/ansible/enable_vagrant.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -- name: "Enable vagrant" - hosts: domain - roles: - - { role: 'enable_user', tags: 'enable_vagrant', username: "vagrant"} diff --git a/ansible/private_data_dir/.git_keep b/ansible/private_data_dir/.git_keep deleted file mode 100644 index e69de29b..00000000 diff --git a/ansible/requirements.yml b/ansible/requirements.yml deleted file mode 100644 index 97bcf4fb..00000000 --- a/ansible/requirements.yml +++ /dev/null @@ -1,12 +0,0 @@ ---- -collections: - # Install a collection from Ansible Galaxy. - - name: ansible.windows - version: 1.11.0 - - name: community.general - - name: community.windows - version: 1.13.0 - - name: chocolatey.chocolatey -# - name: goad.windows -# type: dir -# source: ./collections/goad/windows diff --git a/ansible/requirements_311.yml b/ansible/requirements_311.yml deleted file mode 100644 index 2f247892..00000000 --- a/ansible/requirements_311.yml +++ /dev/null @@ -1,13 +0,0 @@ ---- -collections: - # Install a collection from Ansible Galaxy. - # ansible.windows 2.5.0 and community.windows 2.3.0 need ansible-core >= 2.16 - - name: ansible.windows - version: 2.5.0 - - name: community.general - - name: community.windows - version: 2.3.0 - - name: chocolatey.chocolatey -# - name: goad.windows -# type: dir -# source: ./collections/goad/windows diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml new file mode 100644 index 00000000..32e01774 --- /dev/null +++ b/changelogs/changelog.yaml @@ -0,0 +1,18 @@ +--- +ancestor: null +releases: + 1.0.0: + release_date: "2026-03-30" + changes: + release_summary: >- + Initial release of the dreadnode.goad Ansible collection. + Restructured from the DreadGOAD project into a proper + Ansible collection format. + major_changes: + - Restructured repository as a standalone Ansible collection (dreadnode.goad). + - Flattened nested roles (settings/*, security/*, vulns/*, laps/*, sccm/*) with prefix naming. + - Extracted custom PowerShell modules to plugins/modules/. + - All role references updated to use fully qualified collection names (FQCN). + - Removed non-Ansible components (Python provisioner, Vagrant, Packer, Terraform). + deprecated_features: + - Replaced community.windows.win_domain_user with microsoft.ad.user in onlyusers role. diff --git a/changelogs/config.yaml b/changelogs/config.yaml new file mode 100644 index 00000000..b67d0837 --- /dev/null +++ b/changelogs/config.yaml @@ -0,0 +1,5 @@ +--- +notesdir: fragments +changes_file: changelog.yaml +changes_format: combined +title: dreadnode.goad diff --git a/galaxy.yml b/galaxy.yml new file mode 100644 index 00000000..808baac6 --- /dev/null +++ b/galaxy.yml @@ -0,0 +1,40 @@ +--- +namespace: dreadnode +name: goad +version: 1.0.0 +readme: README.md +authors: + - Dreadnode +description: >- + Game of Active Directory (GOAD) - Ansible collection for deploying + and configuring vulnerable Active Directory lab environments for + penetration testing and security research. +license_file: LICENSE +tags: + - windows + - activedirectory + - security + - pentest + - goad +dependencies: + ansible.windows: ">=2.5.0" + community.general: "*" + community.windows: ">=2.3.0" + chocolatey.chocolatey: ">=1.5.3" +repository: https://github.com/dreadnode/ansible-collection-goad +documentation: https://github.com/dreadnode/ansible-collection-goad +homepage: https://github.com/dreadnode/ansible-collection-goad +issues: https://github.com/dreadnode/ansible-collection-goad/issues +build_ignore: + - "*.retry" + - "*.log" + - "*.tar.gz" + - .git + - .github + - .claude + - .task + - .hooks + - .venv + - .ansible + - scripts + - docs diff --git a/globalsettings.ini b/globalsettings.ini deleted file mode 100644 index 9e74b7e6..00000000 --- a/globalsettings.ini +++ /dev/null @@ -1,27 +0,0 @@ -[all:vars] -; This is the global inventory file, data here will override all lab or provider inventory data -; modify this to add layouts to VMs -; https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/windows-language-pack-default-values -; French : 0000040C -; US : 00000409 -; German : 00000407 -; Spanish : 0000040A -; the first in the list will be the default layout (here: FR | US) -keyboard_layouts=["0000040C", "00000409"] - -; Uncomment to not use SSL in ansible (useful if you get Digest initialization failed: initialization error with vagrant) -# ansible_winrm_transport=basic -# ansible_port=5985 - -; modify this to add a default route -add_route=no -route_gateway=192.168.56.1 -route_network=10.0.0.0/8 - -; modify this to enable http proxy -enable_http_proxy=no -ad_http_proxy=http://x.x.x.x:xxxx -ad_https_proxy=http://x.x.x.x:xxxx - -; dns server fallback forwarder -;dns_server_forwarder=1.1.1.1 diff --git a/goad.py b/goad.py deleted file mode 100644 index 3bf4a071..00000000 --- a/goad.py +++ /dev/null @@ -1,529 +0,0 @@ -import cmd -import argparse -import sys -import time -from goad.config import Config -from goad.log import Log -from goad.exceptions import JumpBoxInitFailed -from goad.menu import print_menu, print_logo -from goad.infos import * - - -class Goad(cmd.Cmd): - - def __init__(self, args): - super().__init__() - # get the arguments - self.args = args - # prepare config, read configuration file and merge with args - config = Config() - config.merge_config(args) - # prepare lab controller to manage labs - # import lab manager after the loading of the dependencies to allow disabling some provider and provisioning method - from goad.lab_manager import LabManager - self.lab_manager = LabManager().init(config, args) - - if args.task == '' or args.task is None: - Log.info('Start Loading default instance') - # load instance marked as default only if no args are provided - self.lab_manager.load_default_instance() - - self.welcome() - # set current lab and provider - self.refresh_prompt() - - def welcome(self): - Log.info('lab instances :') - # show instances tables - self.lab_manager.lab_instances.show_instances(current_instance_id=self.lab_manager.get_current_instance_id()) - # show current configuration - # self.lab_manager.show_settings() - - def refresh_prompt(self): - if self.lab_manager.get_current_instance_id() == '': - self.prompt = f"\n{self.lab_manager.inline_settings()} > " - else: - self.prompt = f"\n{self.lab_manager.inline_settings()} ({self.lab_manager.get_current_instance_id()}) > " - - def default(self, line): - print() - - def do_help(self, arg): - print_menu(self.lab_manager) - - def do_exit(self, arg): - print('bye') - return True - - # main commands - def do_check(self, arg=''): - self.lab_manager.check() - - def do_status(self, arg=''): - if self.lab_manager.get_current_instance(): - self.lab_manager.get_current_instance().provider.status() - - def do_install(self, arg=''): - self.do_create() - - def do_start(self, arg=''): - if self.lab_manager.get_current_instance_provider(): - self.lab_manager.get_current_instance_provider().start() - - def do_start_vm(self, arg): - if arg == '': - Log.error('missing virtual machine name') - Log.info('start_vm ') - else: - self.lab_manager.get_current_instance_provider().start_vm(arg) - - def do_stop(self, arg=''): - if self.lab_manager.get_current_instance_provider(): - self.lab_manager.get_current_instance_provider().stop() - - def do_stop_vm(self, arg): - if arg == '': - Log.error('missing virtual machine name') - Log.info('stop_vm ') - else: - self.lab_manager.get_current_instance_provider().stop_vm(arg) - - def do_destroy(self, arg=''): - if self.lab_manager.get_current_instance_provider(): - self.lab_manager.get_current_instance_provider().destroy() - - def do_destroy_vm(self, arg): - if arg == '': - Log.error('missing virtual machine name') - Log.info('destroy_vm ') - else: - self.lab_manager.get_current_instance_provider().destroy_vm(arg) - - def do_snapshot(self, arg=''): - self.do_stop() - if self.lab_manager.get_current_instance_provider(): - self.lab_manager.get_current_instance_provider().snapshot() - self.do_start() - - def do_reset(self, arg=''): - self.do_stop() - if self.lab_manager.get_current_instance_provider(): - self.lab_manager.get_current_instance_provider().reset() - self.do_start() - - def do_provide(self, arg=''): - result = self.lab_manager.get_current_instance_provider().install() - if result: - self.lab_manager.get_current_instance().set_status(PROVIDED) - # if ip range change after provisioning - if self.lab_manager.get_current_instance_provider().update_ip_range: - Log.info('Update IP range') - new_range = self.lab_manager.get_current_instance_provider().get_ip_range() - if new_range is not None: - Log.info(f'new range : {new_range}') - self.lab_manager.get_current_instance().update_ip_range(new_range) - Log.info(f'reload instance') - # reload instance - instance_id = self.lab_manager.get_current_instance_id() - self.do_load(instance_id) - self.refresh_prompt() - - def do_provision(self, arg): - if arg == '': - Log.error('missing playbook argument') - Log.info('provision ') - else: - start = time.time() - # run playbook - self.lab_manager.get_current_instance_provisioner().run(arg) - time_provision = time.ctime(time.time() - start)[11:19] - Log.info(f'Provisioned with {arg} in {time_provision}') - - def do_provision_lab(self, arg=''): - start = time.time() - provision_result = self.lab_manager.get_current_instance_provisioner().run() - if provision_result: - self.lab_manager.get_current_instance().set_status(READY) - time_provision = time.ctime(time.time() - start)[11:19] - Log.info(f'Lab successfully provisioned in {time_provision}') - return provision_result - - def do_provision_lab_from(self, arg): - start = time.time() - provision_result = self.lab_manager.get_current_instance_provisioner().run_from(arg) - if provision_result: - self.lab_manager.get_current_instance().set_status(READY) - time_provision = time.ctime(time.time() - start)[11:19] - Log.info(f'Provisioned from {arg} in {time_provision}') - - def do_sync_source_jumpbox(self, arg=''): - if self.lab_manager.get_current_instance_provisioner().use_jumpbox: - self.lab_manager.get_current_instance_provisioner().sync_source_jumpbox() - - def do_prepare_jumpbox(self, arg=''): - if self.lab_manager.get_current_instance_provisioner().use_jumpbox: - jumpbox_ip = self.lab_manager.get_current_instance_provider().get_jumpbox_ip(self.lab_manager.get_ip_range()) - if jumpbox_ip is not None: - self.lab_manager.get_current_instance_provisioner().prepare_jumpbox(jumpbox_ip) - else: - Log.error('cannot find jumpbox ip') - - def do_config(self, arg): - self.lab_manager.show_settings() - - def do_ssh_jumpbox(self, arg): - if self.lab_manager.get_current_instance_provisioner().use_jumpbox: - try: - jump_box = self.lab_manager.get_current_instance_provisioner().jumpbox - jump_box.ssh() - except JumpBoxInitFailed as e: - Log.error('Jumpbox retrieve connection info failed, abort') - else: - Log.error('No jump box for this provider') - - def do_ssh_jumpbox_proxy(self, arg): - if self.lab_manager.get_current_instance_provisioner().use_jumpbox: - try: - jump_box = self.lab_manager.get_current_instance_provisioner().jumpbox - if arg.isnumeric() and 1024 < int(arg) <= 65535: - jump_box.ssh_proxy(arg) - else: - Log.error(f'Port value invalid : {arg}') - except JumpBoxInitFailed as e: - Log.error('Jumpbox retrieve connection info failed, abort') - else: - Log.error('No jump box for this provider') - - # configuration - def do_set_lab(self, arg): - """ - Change/Set the lab to use - :param arg: lab name - :return: void - """ - if arg == '': - Log.error('missing lab argument') - Log.info('set_lab ') - else: - try: - self.lab_manager.set_lab(arg) - self.refresh_prompt() - except ValueError as err: - Log.error(err.args[0]) - Log.info('Available labs :') - for lab in self.lab_manager.labs: - Log.info(f' - {lab}') - - def complete_set_lab(self, text, line, begidx, endidx): - options = self.lab_manager.get_labs_options() - if not text: - completions = options - else: - completions = [option for option in options if option.startswith(text)] - return completions - - def do_set_provider(self, arg): - """ - Change/Set the provider to use - :param arg: provider name - :return: void - """ - if arg == '': - Log.error('missing provider argument') - Log.info(f'set_provider (allowed values : {",".join(ALLOWED_PROVIDERS)})') - else: - try: - self.lab_manager.set_provider(arg) - self.refresh_prompt() - except ValueError as err: - Log.error(err.args[0]) - - def complete_set_provider(self, text, line, begidx, endidx): - options = self.lab_manager.get_provider_options() - if not text: - completions = options - else: - completions = [option for option in options if option.startswith(text)] - return completions - - def do_set_provisioning_method(self, arg): - if arg == '': - Log.error('missing provisioner argument') - Log.info(f'set_provisioner (allowed values : {",".join(ALLOWED_PROVISIONER)})') - else: - try: - self.lab_manager.set_provisioner(arg) - self.refresh_prompt() - except ValueError as err: - Log.error(err.args[0]) - - def complete_set_provisioning_method(self, text, line, begidx, endidx): - options = self.lab_manager.provisioning_method_options() - if not text: - completions = options - else: - completions = [option for option in options if option.startswith(text)] - return completions - - def do_set_ip_range(self, arg): - if arg == '': - Log.error('missing ip_start argument') - Log.info(f'set_ip_start ') - else: - self.lab_manager.set_ip_range(arg) - self.refresh_prompt() - - def do_set_extensions(self, arg): - if arg == '': - Log.error('missing extensions arguments') - Log.info(f'set_extensions ...') - else: - extensions_name = arg.split(' ') - self.lab_manager.set_extensions(extensions_name) - self.refresh_prompt() - - def do_list_extensions(self, arg): - if self.lab_manager.get_current_instance_lab() is not None: - self.lab_manager.get_current_instance_lab().show_extensions() - else: - self.lab_manager.get_lab(self.lab_manager.get_current_lab_name()).show_extensions() - - def do_install_extension(self, arg): - if arg == '': - Log.error('missing extension argument') - Log.info(f'provision_extension ') - else: - Log.info('start install extension') - if self.lab_manager.current_instance is not None: - extension_name = arg - extension = self.lab_manager.get_current_instance_lab().get_extension(extension_name) - if extension is not None: - # enable and create files - self.lab_manager.get_current_instance().enable_extension(extension_name) - # # start lab with extensions files (vagrant up / terraform plan) - self.lab_manager.get_current_instance_provider().install() - # # provision extension - self.do_provision_extension(extension_name) - else: - Log.error(f'extension {extension_name} not found abort') - else: - Log.error('Install extension can only be run from an instance') - - def do_provision_extension(self, arg): - if arg == '': - Log.error('missing extension argument') - Log.info(f'provision_extension ') - else: - extension_name = arg - start = time.time() - current_instance_extensions_name = self.lab_manager.get_current_instance().extensions - if extension_name in current_instance_extensions_name: - self.do_sync_source_jumpbox() - extension = self.lab_manager.get_current_instance_lab().get_extension(extension_name) - provision_result = self.lab_manager.get_current_instance_provisioner().run_extension(extension, current_instance_extensions_name) - if provision_result: - time_provision = time.ctime(time.time() - start)[11:19] - Log.info(f'Provision extension done in {time_provision}') - else: - Log.error(f'extension {extension_name} not enabled in instance abort') - - def do_labs(self, arg): - show_labs_providers_table(self.lab_manager.get_labs()) - - def do_show_list_providers(self, arg): - show_labs_providers_list(self.lab_manager.get_labs()) - - def do_update_instance_files(self, arg): - self.lab_manager.update_instance_files() - - def do_create(self, arg=''): - if self.lab_manager.get_current_instance() is not None: - self.do_install_instance() - else: - Log.success('Current Settings') - self.lab_manager.current_settings.show() - print() - if Utils.confirm('Create lab with these settings ? (y/N)'): - Log.info('Create instance folder') - self.lab_manager.create_instance() - Log.info('Launch providing') - self.do_provide() - if self.lab_manager.get_current_instance().get_status() == PROVIDED: - Log.info('Prepare jumpbox if needed') - self.do_prepare_jumpbox() - Log.info('Launch provisioning') - provision_result = self.do_provision_lab() - if provision_result: - for extension_name in self.lab_manager.current_settings.extensions_name: - Log.info(f'Start installation of extension : {extension_name}') - self.do_install_extension(extension_name) - self.refresh_prompt() - else: - Log.error('Providing error stop') - - def do_install_instance(self, arg=''): - Log.info('Launch providing') - self.do_provide() - if self.lab_manager.get_current_instance().get_status() == PROVIDED: - Log.info('Prepare jumpbox if needed') - self.do_prepare_jumpbox() - Log.info('Launch provisioning') - provision_result = self.do_provision_lab() - if provision_result: - for extension_name in self.lab_manager.current_settings.extensions_name: - Log.info(f'Start installation of extension : {extension_name}') - self.do_install_extension(extension_name) - self.refresh_prompt() - else: - Log.error('Providing error stop') - - def do_create_empty(self, arg=''): - Log.info('Create instance folder') - self.lab_manager.create_instance() - - def do_set_as_default(self, arg): - self.lab_manager.set_as_default_instance() - - # load alias - def do_use(self, arg): - self.do_load(arg) - - def complete_use(self, text, line, begidx, endidx): - return self.complete_load(text, line, begidx, endidx) - - # load alias - def do_cd(self, arg): - if arg == '..': - self.do_unload() - else: - self.do_load(arg) - - def complete_cd(self, text, line, begidx, endidx): - return self.complete_load(text, line, begidx, endidx) - - def do_load(self, arg): - if arg == '': - Log.error('missing instance id argument') - Log.info(f'use_instance ') - else: - self.lab_manager.load_instance(arg) - if self.lab_manager.current_instance is not None: - self.lab_manager.lab_instances.show_instances(current_instance_id=self.lab_manager.get_current_instance_id(), filter_instance_id=self.lab_manager.get_current_instance_id()) - self.refresh_prompt() - - def complete_load(self, text, line, begidx, endidx): - options = self.lab_manager.get_instance_options() - if not text: - completions = options - else: - completions = [option for option in options if option.startswith(text)] - return completions - - def do_unload(self, arg=''): - if self.lab_manager.get_current_instance_id() is not None: - self.lab_manager.unload_instance() - self.refresh_prompt() - - def do_delete(self, arg): - if self.lab_manager.get_current_instance_id() is not None: - deleted = self.lab_manager.delete_instance() - if deleted: - self.refresh_prompt() - - def do_disable_vagrant(self, arg): - start = time.time() - provision_result = self.lab_manager.get_current_instance_provisioner().run_disable_vagrant(disable_vagrant=True) - if provision_result: - time_provision = time.ctime(time.time() - start)[11:19] - Log.info(f'Disable vagrant done in {time_provision}') - Log.info(f'Please restart the lab to avoid administrator NT hash in lsass') - - def do_enable_vagrant(self, arg): - start = time.time() - provision_result = self.lab_manager.get_current_instance_provisioner().run_disable_vagrant(disable_vagrant=False) - if provision_result: - time_provision = time.ctime(time.time() - start)[11:19] - Log.info(f'Enable vagrant done in {time_provision}') - - # alias to list - def do_ls(self, arg=''): - self.do_list(arg) - - def do_list(self, arg=''): - self.lab_manager.lab_instances.show_instances(current_instance_id=self.lab_manager.get_current_instance_id()) - - -def parse_args(): - task_help = 'tasks available : (install/start/stop/restart/destroy/status/show)' - parser = argparse.ArgumentParser(prog='goad.py', - description='Description : goad lab management console.', - epilog=show_help(), formatter_class=argparse.RawDescriptionHelpFormatter) - parser.add_argument("-t", "--task", help=f"{task_help}", required=False) - parser.add_argument("-l", "--lab", help="lab to use (default: GOAD)", default='GOAD', required=False) - parser.add_argument("-p", "--provider", help="provider to use (default: vmware)", default='vmware', required=False) - parser.add_argument("-ip", "--ip_range", help="ip range to use (default: 192.168.56)", default='', required=False) - parser.add_argument("-m", "--method", help="deploy method to use (default: local)", default='local', required=False) - parser.add_argument("-i", "--instance", help="use a specific instance (use default if not selected)", required=False) - parser.add_argument("-e", "--extensions", help="extensions to use", action='append', required=False) - parser.add_argument("-a", "--ansible_only", help="run only provisioning (ansible) on instance (-i) (for task install only)", required=False) - parser.add_argument("-r", "--run_playbook", help="run only one ansible playbook on instance (-i) (for task install only)", required=False) - parser.add_argument("-d", "--disable_dependencies", help="disable_dependencies", action='append', required=False) - args = parser.parse_args() - return args - - -def show_help(): - return ''' -Example : - - Install GOAD on virtualbox : python3 goad.py -t install -l GOAD -p virtualbox - - Launch GOAD interactive console : python3 goad.py -''' - - -if __name__ == '__main__': - print_logo() - args = parse_args() - goad = Goad(args) - - if args is None or args.task is None: - goad.cmdloop() - else: - if args.instance is not None: - goad.do_load(args.instance) - - if args.run_playbook is not None or args.ansible_only is not None: - if args.instance is None: - Log.error('Instance must be selected (-i) to use --run_playbook (-r) or --ansible_only (-a)') - sys.exit(1) - - # Command line args like the old goad.sh commands - if args.task is not None: - if args.task == 'install': - if args.instance is not None: - if args.run_playbook is not None: - goad.do_provision(args.run_playbook) - elif args.ansible_only: - goad.do_provision_lab() - else: - goad.do_install_instance() - else: - goad.do_install() - elif args.task == 'check': - goad.do_check() - elif args.task == 'start': - goad.do_start() - elif args.task == 'stop': - goad.do_stop() - elif args.task == 'restart': - goad.do_stop() - goad.do_start() - elif args.task == 'destroy': - goad.do_destroy() - elif args.task == 'status': - goad.do_status() - elif args.task == 'snapshot': - goad.do_snapshot() - elif args.task == 'reset': - goad.do_reset() - elif args.task == 'show': - pass diff --git a/goad.sh b/goad.sh deleted file mode 100755 index 37f53f18..00000000 --- a/goad.sh +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env bash - -py=python3 -venv="$HOME/.goad/.venv" -requirement_file="requirements.yml" - -if [ ! -d "$venv" ]; then - # Get the Python version (removes 'Python' from output) - version=$($py --version 2>&1 | awk '{print $2}') - echo "Python version in use : $version" - # Convert the version to comparable format (removes the dot and treats it as an integer) - version_numeric=$(echo "$version" | awk -F. '{printf "%d%02d%02d\n", $1, $2, $3}') - # Check if the version is >= 3.8.0 - if [ "$version_numeric" -ge 30800 ]; then - # echo "Python version is >= 3.8.0 - echo 'python version >= 3.8 ok' - if [ "$version_numeric" -lt 31100 ]; then - # python version < 3.11 - requirement_file="requirements.yml" - else - # python version >= 3.11 - requirement_file="requirements_311.yml" - fi - else - echo "Python version is < 3.8 please update python before install" - exit - fi - - if $py -m venv -h 2> /dev/null | grep -qi 'usage:'; then - echo "venv module is installed. continue" - else - echo "venv module is not installed." - echo "please install $py-venv according to your system" - echo "exit" - exit 0 - fi - - echo '[+] venv not found, start python venv creation' - mkdir -p ~/.goad - $py -m venv "$venv" - if source "$venv"/bin/activate; then - $py -m pip install --upgrade pip - export SETUPTOOLS_USE_DISTUTILS=stdlib - $py -m pip install -r "$requirement_file" - pushd ansible > /dev/null || exit - ansible-galaxy install -r "$requirement_file" - popd > /dev/null || exit - else - echo "Error in venv creation" - rm -rf "$venv" - exit 0 - fi -fi - -# launch the app -source "$venv"/bin/activate -$py goad.py "$@" -deactivate diff --git a/goad/__init__.py b/goad/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/goad/command/cmd.py b/goad/command/cmd.py deleted file mode 100644 index ab706f8c..00000000 --- a/goad/command/cmd.py +++ /dev/null @@ -1,234 +0,0 @@ -import subprocess -import psutil -import sys -from goad.log import Log -from goad.utils import Utils -from goad.dependencies import Dependencies - -class Command: - - def __init__(self): - self.vagrant_bin = '' - self.terraform_bin = '' - - # CHECK - def is_in_path(self, bin_file): - command = f'which {bin_file} >/dev/null' - try: - subprocess.run(command, shell=True, check=True) - Log.success(f'{bin_file} found in PATH') - return True - except subprocess.CalledProcessError as e: - Log.error(f'{bin_file} not found in PATH') - return False - - def check_vagrant(self): - return self.is_in_path(self.vagrant_bin) - - def check_vagrant_plugin(self, plugin_name, mandatory=True): - try: - result = subprocess.run([self.vagrant_bin, 'plugin', 'list'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) - if plugin_name in result.stdout: - Log.success(f'vagrant plugin {plugin_name} is installed') - return True - else: - if not mandatory: - Log.warning(f'Missing vagrant plugin {plugin_name}') - else: - Log.error(f'Missing vagrant plugin {plugin_name}') - return False - except FileNotFoundError: - Log.error("Vagrant is not installed or not found in PATH.") - return False - - def check_vmware_utility(self): - pass - - def check_ovftool(self): - pass - - def check_gem(self, gem_name): - pass - - def check_vmware(self): - pass - - def check_virtualbox(self): - pass - - def check_terraform(self): - return self.is_in_path(self.terraform_bin) - - def check_aws(self): - return self.is_in_path('aws') - - def check_azure(self): - return self.is_in_path('az') - - def check_rsync(self): - return self.is_in_path('rsync') - - def check_ansible(self): - if not Dependencies.provisioner_local_enabled and not Dependencies.provisioner_runner_enabled: - Log.info('skip ansible check as no local and runner provisionner enabled') - return True - checks = [ - self.is_in_path('ansible-playbook'), - self.check_ansible_galaxy('ansible.windows'), - self.check_ansible_galaxy('community.general'), - self.check_ansible_galaxy('community.windows'), - ] - return all(checks) - - def check_ansible_galaxy(self, collection): - try: - result = subprocess.run(['ansible-galaxy', 'collection', 'list'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, cwd='./ansible') - if collection in result.stdout: - Log.success(f'Ansible galaxy collection {collection} is installed') - return True - else: - Log.error(f'Missing ansible-galaxy collection {collection}') - return False - except FileNotFoundError: - Log.error("ansible-galaxy is not installed or not found in PATH.") - return False - - def check_ludus(self): - # linux only - pass - - def check_disk(self, min_disk_gb=120): - # If the system has multiple mountpoints, '.' will correctly calculate the available space on the current disk - disk_usage = psutil.disk_usage('.') - free_disk_gb = disk_usage.free / (1024 ** 3) # Convert bytes to GB - if free_disk_gb < min_disk_gb: - Log.warning(f'not enough disk space, only {str(free_disk_gb)} Gb available') - return False - return True - - def check_ram(self, min_ram_gb=24): - total_ram_gb = psutil.virtual_memory().total / (1024 ** 3) # Convert bytes to GB - if total_ram_gb < min_ram_gb: - Log.error('not enough ram on the system') - return False - return True - - # RUN - def run_shell(self, command, path): - try: - Log.info('CWD: ' + Utils.get_relative_path(str(path))) - Log.cmd(command) - subprocess.run(command, cwd=path, shell=True) - except subprocess.CalledProcessError as e: - Log.error(f"An error occurred while running the command: {e}") - - def run_command(self, command, path): - result = None - try: - Log.info('CWD: ' + Utils.get_relative_path(str(path))) - Log.cmd(command) - result = subprocess.run(command, cwd=path, stderr=sys.stderr, stdout=sys.stdout, shell=True) - except subprocess.CalledProcessError as e: - Log.error(f"An error occurred while running the command: {e}") - return False - return result.returncode == 0 - - def run_vagrant(self, args, path): - result = None - try: - command = [self.vagrant_bin] - command += args - Log.info('CWD: ' + Utils.get_relative_path(str(path))) - Log.cmd(' '.join(command)) - result = subprocess.run(command, cwd=path, stderr=sys.stderr, stdout=sys.stdout) - except subprocess.CalledProcessError as e: - Log.error(f"An error occurred while running the command: {e}") - return result.returncode == 0 - - def run_terraform(self, args, path): - result = None - try: - command = [self.terraform_bin] - command += args - Log.info('CWD: ' + Utils.get_relative_path(str(path))) - Log.cmd(' '.join(command)) - result = subprocess.run(command, cwd=path, stderr=sys.stderr, stdout=sys.stdout) - except subprocess.CalledProcessError as e: - Log.error(f"An error occurred while running the command: {e}") - return result.returncode == 0 - - def run_terraform_output(self, args, path): - result = None - try: - command = [self.terraform_bin, 'output', '-raw'] - command += args - Log.info('CWD: ' + Utils.get_relative_path(str(path))) - Log.cmd(' '.join(command)) - result = subprocess.run(command, cwd=path, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - text=True - ) - if result.returncode != 0: - print(f"Error: {result.stderr}") - return None - - return result.stdout - except subprocess.CalledProcessError as e: - Log.error(f"An error occurred while running the command: {e}") - return None - - def run_ludus(self, args, path, api_key, user_id='', impersonation=False): - # linux only - pass - - def run_docker_ansible(self, args, path, ansible_path, sudo): - # linux only - pass - - def run_ansible(self, args, path): - result = None - try: - command = 'ansible-playbook ' - command += args - Log.info('CWD: ' + Utils.get_relative_path(str(path))) - Log.cmd(command) - result = subprocess.run(command, cwd=path, stderr=sys.stderr, stdout=sys.stdout, shell=True) - except subprocess.CalledProcessError as e: - Log.error(f"An error occurred while running the command: {e}") - return False - return result.returncode == 0 - - def run_docker_ansible(self, args, path, sudo): - # Linux only - pass - - def get_azure_account_output(self): - result = subprocess.run( - ["az", "account", "list", "--output", "json"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - text=True - ) - if result.returncode != 0: - print(f"Error: {result.stderr}") - return None - - return result.stdout - - def scp(self, source, destination, ssh_key, path): - # scp files - Log.info(f'Launch scp {source} -> {destination}') - scp_command = f"scp -o StrictHostKeyChecking=no -i {ssh_key}" - command = f'{scp_command} {source} {destination}' - self.run_shell(command, path) - - def rsync(self, source, destination, ssh_key, exclude=True): - # rsync = f'rsync -a --exclude-from='.gitignore' -e "ssh -o 'StrictHostKeyChecking no' -i $CURRENT_DIR/ad/$lab/providers/$provider/ssh_keys/ubuntu-jumpbox.pem" "$CURRENT_DIR/" goad@$public_ip:~/GOAD/' - Log.info(f'Launch Rsync {source} -> {destination}') - ssh_command = f"ssh -o StrictHostKeyChecking=no -i {ssh_key}" - exclude_from = '' - if exclude: - exclude_from = '--exclude-from=".gitignore"' - command = f'rsync -a {exclude_from} -e "{ssh_command}" {source} {destination}' - self.run_shell(command, source) diff --git a/goad/command/cmd_factory.py b/goad/command/cmd_factory.py deleted file mode 100644 index 262ce9f3..00000000 --- a/goad/command/cmd_factory.py +++ /dev/null @@ -1,15 +0,0 @@ -from goad.command.windows import WindowsCommand -from goad.command.linux import LinuxCommand -from goad.command.wsl import WslCommand -from goad.utils import Utils - - -class CommandFactory: - - @staticmethod - def get_command(): - if Utils.is_wsl(): - return WslCommand() - elif Utils.is_windows(): - return WindowsCommand() - return LinuxCommand() diff --git a/goad/command/linux.py b/goad/command/linux.py deleted file mode 100644 index 14344fd7..00000000 --- a/goad/command/linux.py +++ /dev/null @@ -1,131 +0,0 @@ -import sys -import os -from goad.command.cmd import Command -import subprocess - -from goad.goadpath import GoadPath -from goad.log import Log -from goad.utils import Utils - - -class LinuxCommand(Command): - - def __init__(self): - super().__init__() - self.vagrant_bin = 'vagrant' - self.terraform_bin = 'terraform' - - # CHECK - def check_gem(self, gem_name): - try: - result = subprocess.run(['gem', 'list'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) - if gem_name in result.stdout: - Log.success(f'ruby gem {gem_name} is installed') - return True - else: - Log.warning(f'ruby gem {gem_name} not installed') - return False - except FileNotFoundError: - Log.error("Ruby or gem is not installed or not found in PATH.") - return False - - def check_vmware(self): - return self.is_in_path('vmrun') - - def check_vmware_utility(self): - try: - result = subprocess.run( - ['systemctl', 'is-active', '--quiet', 'vagrant-vmware-utility'], - check=True - ) - Log.success(f'vmware utility is installed') - return True - except subprocess.CalledProcessError: - Log.error("vagrant-vmware-utility is not installed") - return False - - def check_ovftool(self): - try: - result = subprocess.run(['ovftool', '-v'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, cwd='.') - fields = result.stdout.split(' ') - if len(fields) > 2: - version = fields[2] - Log.success(f'Ovftool version {version} is installed') - return True - else: - Log.error(f'Failed to parse ovftool version') - return False - except FileNotFoundError: - Log.error("ovftool is not installed or not found in PATH.") - return False - - def check_virtualbox(self): - return self.is_in_path('VBoxManage') - - def check_ludus(self): - return self.is_in_path('ludus') - - # RUN - def run_ludus(self, args, path, api_key, user_id='', impersonation=False): - env = os.environ.copy() - if "LUDUS_API_KEY" not in os.environ: - Log.info('Using api key from config file') - env["LUDUS_API_KEY"] = api_key - else: - Log.info('Using api key from env') - result = None - try: - command = 'ludus ' - if impersonation: - command += f'--user {user_id} ' - command += args - Log.info('CWD: ' + Utils.get_relative_path(str(path))) - Log.cmd(command) - result = subprocess.run(command, cwd=path, stderr=sys.stderr, stdout=sys.stdout, shell=True, env=env) - except subprocess.CalledProcessError as e: - Log.error(f"An error occurred while running the command: {e}") - return result.returncode == 0 - - def run_ludus_result(self, command, path, api_key, do_log=True, user_id='', impersonation=False): - result = None - env = os.environ.copy() - if "LUDUS_API_KEY" not in os.environ: - Log.info('Using api key from config file') - env["LUDUS_API_KEY"] = api_key - else: - Log.info('Using api key from env') - try: - cmd = ['ludus'] - if impersonation: - cmd += ['--user', user_id] - cmd += command - if do_log: - Log.info('CWD: ' + Utils.get_relative_path(str(path))) - Log.cmd(' '.join(cmd)) - result = subprocess.run(cmd, cwd=path, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - text=True, - env=env - ) - if result.returncode != 0: - print(f"Error: {result.stderr}") - return None - - return result.stdout - except subprocess.CalledProcessError as e: - Log.error(f"An error occurred while running the command: {e}") - return None - - def run_docker_ansible(self, args, path, ansible_path, sudo): - result = None - try: - ansible_command = 'ansible-playbook ' - ansible_command += args - command = f"{sudo} docker run -ti --rm --network host -h goadansible -v {GoadPath.get_project_path()}:/goad -w {ansible_path} goadansible /bin/bash -c '{ansible_command}'" - Log.cmd(command) - result = subprocess.run(command, cwd=path, stderr=sys.stderr, stdout=sys.stdout, shell=True) - except subprocess.CalledProcessError as e: - Log.error(f"An error occurred while running the command: {e}") - return False - return result.returncode == 0 diff --git a/goad/command/windows.py b/goad/command/windows.py deleted file mode 100644 index 616f2b61..00000000 --- a/goad/command/windows.py +++ /dev/null @@ -1,51 +0,0 @@ -import os -from goad.command.cmd import Command -import subprocess -from goad.log import Log - - -class WindowsCommand(Command): - - def __init__(self): - super().__init__() - self.vagrant_bin = 'vagrant.exe' - self.terraform_bin = 'terraform.exe' - - def file_exist(self, file): - exist = os.path.isfile(file) - if exist: - Log.success(f'File {file} present in the file system') - return exist - - def is_in_path(self, bin_file): - command = f'where {bin_file} >nul' - try: - subprocess.run(command, shell=True, check=True) - Log.success(f'{bin_file} found in PATH') - return True - except subprocess.CalledProcessError as e: - Log.error(f'{bin_file} not found in PATH') - return False - - # CHECK - def check_gem(self, gem_name): - # not needed - pass - - def check_vmware(self): - return self.file_exist("C:\\Program Files (x86)\\VMware\\VMware Workstation\\vmrun.exe") - - def check_vmware_utility(self): - return self.file_exist("C:\\Program Files\\VagrantVMwareUtility\\vagrant-vmware-utility.exe") - - def check_ovftool(self): - return self.file_exist("C:\\Program Files\\VMware\\VMware OVF Tool\\ovftool.exe") - - def check_virtualbox(self): - return self.file_exist("C:\\Program Files\\Oracle\\VirtualBox\\VBoxManage.exe") - - def check_terraform(self): - return self.is_in_path('terraform.exe') - - def check_ludus(self): - return False diff --git a/goad/command/wsl.py b/goad/command/wsl.py deleted file mode 100644 index c4a3af84..00000000 --- a/goad/command/wsl.py +++ /dev/null @@ -1,47 +0,0 @@ -import sys -import os -from goad.command.cmd import Command -import subprocess -from goad.goadpath import GoadPath -from goad.log import Log -from goad.utils import Utils - - -class WslCommand(Command): - - def __init__(self): - super().__init__() - self.vagrant_bin = 'vagrant.exe' - self.terraform_bin = 'terraform.exe' - - def file_exist(self, file): - exist = os.path.isfile(file) - if exist: - Log.success(f'File {file} present in the file system') - return exist - - # CHECK - def check_gem(self, gem_name): - # not needed - pass - - def check_vmware(self): - return self.file_exist("/mnt/c/Program Files (x86)/VMware/VMware Workstation/vmrun.exe") - - def check_vmware_utility(self): - return self.file_exist("/mnt/c/Program Files/VagrantVMwareUtility/vagrant-vmware-utility.exe") - - def check_ovftool(self): - return self.file_exist("/mnt/c/Program Files/VMware/VMware OVF Tool/ovftool.exe") - - def check_virtualbox(self): - return self.file_exist("/mnt/c/Program Files/Oracle/VirtualBox/VBoxManage.exe") - - def check_terraform(self): - return self.is_in_path('terraform.exe') - - def check_ludus(self): - return False - - # RUN - # see Command diff --git a/goad/config.py b/goad/config.py deleted file mode 100644 index 0d3a9e27..00000000 --- a/goad/config.py +++ /dev/null @@ -1,132 +0,0 @@ -import configparser -from goad.goadpath import GoadPath -from goad.utils import * -from goad.log import Log -from goad.dependencies import Dependencies - - -class Config: - config = None - - def __init__(self): - if not os.path.isdir(GoadPath.get_config_path()): - Log.info(f'goad config path not found, create dir {GoadPath.get_config_path()}') - os.mkdir(GoadPath.get_config_path(), 0o750) - if not os.path.isfile(GoadPath.get_config_file()): - Log.info(f'goad config file not found, create file {GoadPath.get_config_file()}') - self.create_config_file() - - def get_config_parser(self): - return self.config - - def create_config_file(self): - cfgfile = open(GoadPath.get_config_file(), "w") - config = configparser.ConfigParser(allow_no_value=True) - - config.add_section('default') - config.set('default', '; lab: GOAD / GOAD-Light / MINILAB / NHA / SCCM') - config.set('default', 'lab', 'GOAD') - - config.set('default', '; provider : virtualbox / vmware / vmware_esxi / aws / azure / proxmox') - config.set('default', 'provider', 'vmware') - - config.set('default', "; provisioner method : local / remote") - config.set('default', 'provisioner', 'local') - - config.set('default', '; ip_range (3 first ip digits)') - config.set('default', 'ip_range', '192.168.56') - - config.add_section('aws') - config.set('aws', 'aws_region', 'eu-west-3') - config.set('aws', 'aws_zone', 'eu-west-3c') - - config.add_section('azure') - config.set('azure', 'az_location', 'westeurope') - - config.add_section('proxmox') - config.set('proxmox', 'pm_api_url', 'https://192.168.1.1:8006/api2/json') - config.set('proxmox', 'pm_user', 'infra_as_code@pve') - config.set('proxmox', 'pm_node', 'GOAD') - config.set('proxmox', 'pm_pool', 'GOAD') - config.set('proxmox', 'pm_full_clone', 'false') - config.set('proxmox', 'pm_storage', 'local') - config.set('proxmox', 'pm_vlan', '10') - config.set('proxmox', 'pm_network_bridge', 'vmbr3') - config.set('proxmox', 'pm_network_model', 'e1000') - - config.add_section('proxmox_templates_id') - config.set('proxmox_templates_id', 'WinServer2019_x64', '102') - config.set('proxmox_templates_id', 'WinServer2016_x64', '103') - config.set('proxmox_templates_id', 'WinServer2019_x64_utd', '104') - config.set('proxmox_templates_id', 'Windows10_22h2_x64', '105') - - config.add_section('ludus') - config.set('ludus', '; api key must not have % if you have a % in it, change it by a %%') - config.set('ludus', 'ludus_api_key', 'change_me') - config.set('ludus', 'use_impersonation', 'yes') - - config.add_section('vmware_esxi') - config.set('vmware_esxi', 'esxi_hostname', '10.10.10.10') - config.set('vmware_esxi', 'esxi_username', 'root') - config.set('vmware_esxi', 'esxi_password', 'password') - config.set('vmware_esxi', 'esxi_net_nat', 'VM Network') - config.set('vmware_esxi', 'esxi_net_domain', 'GOAD-LAN') - config.set('vmware_esxi', 'esxi_datastore', 'datastore1') - config.write(cfgfile) - cfgfile.close() - - def merge_config(self, args): - """ - Merge the configuration with the script arguments - :param args: goad.py arguments - :return: goad.Config object - """ - self.config = configparser.ConfigParser() - self.config.read(GoadPath.get_config_file()) - if args is not None: - if args.lab: - self.set_value('default', LAB, args.lab) - if args.provider: - self.set_value('default', PROVIDER, args.provider) - if args.method: - self.set_value('default', PROVISIONER, args.method) - if args.ip_range: - self.set_value('default', IP_RANGE, args.ip_range) - if args.disable_dependencies: - for disable_dependence in args.disable_dependencies: - if disable_dependence == 'vmware': - Dependencies.vmware_enabled = False - elif disable_dependence == 'vmware_esxi': - Dependencies.vmware_esxi_enabled = False - elif disable_dependence == 'virtualbox': - Dependencies.virtualbox_enabled = False - elif disable_dependence == 'azure': - Dependencies.azure_enabled = False - elif disable_dependence == 'aws': - Dependencies.aws_enabled = False - elif disable_dependence == 'ludus': - Dependencies.ludus_enabled = False - elif disable_dependence == 'proxmox': - Dependencies.proxmox_enabled_enabled = False - elif disable_dependence == 'local': - Dependencies.provisioner_local_enabled = False - elif disable_dependence == 'runner': - Dependencies.provisioner_runner_enabled = False - elif disable_dependence == 'remote': - Dependencies.provisioner_remote_enabled = False - elif disable_dependence == 'docker': - Dependencies.provisioner_docker_enabled = False - return self - - def get_value(self, section, key, fallback=None): - return self.config.get(section, key, fallback=fallback) - - def set_value(self, section, key, value): - return self.config.set(section, key, value) - - def show(self): - for section in self.config.sections(): - Log.basic(f'[yellow]\\[{section}][/yellow]') - for key in self.config[section]: - Log.basic(f' {key} : {self.config[section][key]}') - Log.basic('') diff --git a/goad/dependencies.py b/goad/dependencies.py deleted file mode 100644 index 4fa87f29..00000000 --- a/goad/dependencies.py +++ /dev/null @@ -1,18 +0,0 @@ -from goad.utils import Utils - - -class Dependencies: - # Can change enabled providers (useful if you don't want some dependencies) - vmware_enabled = True - vmware_esxi_enabled = True - virtualbox_enabled = True - azure_enabled = True - aws_enabled = True - proxmox_enabled = True - ludus_enabled = True - # Can change enabled provisioners (useful if you don't want some dependencies) - provisioner_local_enabled = False if Utils.is_windows() else True - provisioner_runner_enabled = False if Utils.is_windows() else True - provisioner_remote_enabled = True - provisioner_vm_enabled = True - provisioner_docker_enabled = False if Utils.is_wsl() or Utils.is_windows() else True diff --git a/goad/exceptions.py b/goad/exceptions.py deleted file mode 100644 index 5900e4a6..00000000 --- a/goad/exceptions.py +++ /dev/null @@ -1,10 +0,0 @@ -class ProviderPathNotFound(Exception): - pass - - -class AuthenticationFailed(Exception): - pass - - -class JumpBoxInitFailed(Exception): - pass diff --git a/goad/extension.py b/goad/extension.py deleted file mode 100644 index 69826456..00000000 --- a/goad/extension.py +++ /dev/null @@ -1,49 +0,0 @@ -from goad.utils import * -from goad.goadpath import GoadPath -from goad.log import Log -import json - - -class Extension: - - def __init__(self, extension_name): - self.name = extension_name - self.providers_name_list = self.load_extension_providers(extension_name) - self.compatibility = [] - self.description = '' - self.load_extension_config_file(extension_name) - - def load_extension_providers(self, extension_name): - providers_name_list = [] - for provider_name in Utils.list_folders(GoadPath.get_extension_providers_path(extension_name)): - if provider_name in ALLOWED_PROVIDERS: - providers_name_list.append(provider_name) - return providers_name_list - - def load_extension_config_file(self, extension_name): - extension_json_file = GoadPath.get_extension_config_file(extension_name) - if os.path.isfile(extension_json_file): - with open(extension_json_file, 'r') as extension_json_openfile: - # Reading from json file - extension_info = json.load(extension_json_openfile) - self.compatibility = extension_info['compatibility'] - self.description = extension_info['description'] - - def is_available(self, lab_name): - return '*' in self.compatibility or lab_name in self.compatibility - - def list_providers_name(self): - return self.providers_name_list - - def get_playbook(self, install=True): - if install: - return 'install.yml' - else: - return 'uninstall.yml' - - def get_ansible_path(self): - return GoadPath.get_extension_ansible_path(self.name) - - def show(self): - name = f'{self.name}'.ljust(30, '.') - Log.info(f'{name} {self.description}') diff --git a/goad/goadpath.py b/goad/goadpath.py deleted file mode 100644 index 25c8b6dd..00000000 --- a/goad/goadpath.py +++ /dev/null @@ -1,168 +0,0 @@ -from goad.utils import * - -sep = os.path.sep -project_path = os.path.normpath(os.path.dirname(os.path.abspath(__file__)) + sep + '..') - - -class GoadPath: - - @staticmethod - def get_config_path(): - home = str(Path.home()) - return home + sep + '.goad' - - @staticmethod - def get_config_file(): - return GoadPath.get_config_path() + sep + 'goad.ini' - - @staticmethod - def get_global_inventory_path(): - return project_path + os.path.sep + 'globalsettings.ini' - - @staticmethod - def get_workspace_path(): - return project_path + sep + 'workspace' - - @staticmethod - def get_project_path(): - return project_path + sep - - @staticmethod - def get_template_path(provider): - """ - :return: /template/provider// - """ - return project_path + sep + 'template' + sep + 'provider' + sep + provider + sep - - # config - @staticmethod - def get_playbooks_lab_config(): - """ - :return: /playbooks.yml - """ - return project_path + os.path.sep + 'playbooks.yml' - - # LAB recipe - @staticmethod - def get_labs_path(): - """ - :return: /ad - """ - return project_path + sep + 'ad' - - @staticmethod - def get_lab_path(lab_name): - """ - :return: /ad/ - """ - return GoadPath.get_labs_path() + sep + lab_name - - @staticmethod - def get_lab_data_path(lab_name): - """ - :return: /ad//data - """ - return GoadPath.get_lab_path(lab_name) + sep + 'data' - - @staticmethod - def get_lab_providers_path(lab_name): - """ - :return: /ad//providers - """ - return project_path + os.path.sep + 'ad' + os.path.sep + lab_name + os.path.sep + 'providers' - - @staticmethod - def get_lab_provider_path(lab_name, provider_name): - """ - :return: /ad//providers/ - """ - return GoadPath.get_lab_providers_path(lab_name) + sep + provider_name - - @staticmethod - def get_provider_inventory_file(lab_name, provider_name): - """ - :return: /ad//providers//inventory - """ - return GoadPath.get_lab_provider_path(lab_name, provider_name) + sep + 'inventory' - - @staticmethod - def get_lab_inventory_file(lab_name): - """ - :return: /ad//data/inventory - """ - return GoadPath.get_lab_path(lab_name) + os.path.sep + 'data' + os.path.sep + 'inventory' - - # script - @staticmethod - def get_script_path(): - """ - :return: /scripts - """ - return project_path + os.path.sep + 'scripts' - - @staticmethod - def get_script_file(script): - """ - :return: /scripts/