diff --git a/.github/images/setup_domain_end_state.png b/.github/images/setup_domain_end_state.png new file mode 100644 index 0000000..5a67efb Binary files /dev/null and b/.github/images/setup_domain_end_state.png differ diff --git a/.github/images/setup_domain_workflow.png b/.github/images/setup_domain_workflow.png new file mode 100644 index 0000000..9f1a16a Binary files /dev/null and b/.github/images/setup_domain_workflow.png differ diff --git a/.github/images/setup_domain_workflow_domain.png b/.github/images/setup_domain_workflow_domain.png new file mode 100644 index 0000000..4cbc685 Binary files /dev/null and b/.github/images/setup_domain_workflow_domain.png differ diff --git a/.github/images/setup_domain_workflow_inventory.png b/.github/images/setup_domain_workflow_inventory.png new file mode 100644 index 0000000..7d7db57 Binary files /dev/null and b/.github/images/setup_domain_workflow_inventory.png differ diff --git a/windows/README.md b/windows/README.md index a19a64e..60c64b2 100644 --- a/windows/README.md +++ b/windows/README.md @@ -4,12 +4,17 @@ - [Windows Demos](#windows-demos) - [Table of Contents](#table-of-contents) - [About These Demos](#about-these-demos) + - [Known Issues](#known-issues) - [Jobs](#jobs) + - [Workflows](#workflows) - [Suggested Usage](#suggested-usage) ## About These Demos This category of demos shows examples of Windows Server operations and management with Ansible Automation Platform. The list of demos can be found below. See the [Suggested Usage](#suggested-usage) section of this document for recommendations on how to best use these demos. +### Known Issues +We are currently investigating an intermittent connectivity issue related to the credentials for Windows hosts. If encountered, re-provision your demo environment. You can track the issue and related work [here](https://github.com/ansible/product-demos/issues/176). + ### Jobs - [**WINDOWS / Install IIS**](install_iis.yml) - Install IIS feature with a configurable index.html @@ -23,8 +28,13 @@ This category of demos shows examples of Windows Server operations and managemen - [**WINDOWS / Helpdesk new user portal**](helpdesk_new_user_portal.yml) - Create user in AD Domain - [**WINDOWS / Join Active Directory Domain**](join_ad_domain.yml) - Join computer to AD Domain +### Workflows +- [**Setup Active Directory Domain**](setup_domain_workflow.md) - A workflow to create a domain controller with two domain-joined Windows hosts + ## Suggested Usage +**Setup Active Directory Domain** - One-click domain setup, infrastructure included. + **WINDOWS / Create Active Directory Domain** - This job can take some to complete. It is recommended to run ahead of time if you would like to demo creating a helpdesk user. **WINDOWS / Helpdesk new user portal** - This job is dependant on the Create Active Directory Domain completing before users can be created. diff --git a/windows/backup.yml b/windows/backup.yml deleted file mode 100644 index ee05474..0000000 --- a/windows/backup.yml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Rollback playbook - hosts: windows - tasks: - - name: "Rollback this step" - ansible.builtin.debug: - msg: "Rolling back this step" diff --git a/windows/connect.yml b/windows/connect.yml new file mode 100644 index 0000000..e9829b8 --- /dev/null +++ b/windows/connect.yml @@ -0,0 +1,15 @@ +--- +- name: Connectivity test + hosts: "{{ _hosts | default('os_windows') }}" + gather_facts: false + + tasks: + - name: Wait 600 seconds for target connection to become reachable/usable + ansible.builtin.wait_for_connection: + connect_timeout: "{{ wait_for_timeout_sec | default(5) }}" + delay: "{{ wait_for_delay_sec | default(0) }}" + sleep: "{{ wait_for_sleep_sec | default(1) }}" + timeout: "{{ wait_for_timeout_sec | default(300) }}" + + - name: Ping the windows host + ansible.builtin.win_ping: diff --git a/windows/create_ad_domain.yml b/windows/create_ad_domain.yml index 5c8599b..f396774 100644 --- a/windows/create_ad_domain.yml +++ b/windows/create_ad_domain.yml @@ -9,18 +9,24 @@ name: Administrator password: "{{ ansible_password }}" + - name: Update the hostname + ansible.windows.win_hostname: + name: "{{ inventory_hostname.split('.')[0] }}" + + - name: Reboot to apply new hostname + ansible.windows.win_reboot: + reboot_timeout: 3600 + - name: Create new domain in a new forest on the target host + register: r_create_domain ansible.windows.win_domain: dns_domain_name: ansible.local safe_mode_password: "{{ lookup('community.general.random_string', min_lower=1, min_upper=1, min_special=1, min_numeric=1) }}" - notify: - - Reboot host - - Wait for AD services - - Reboot again - - Wait for AD services again - - name: Flush handlers - ansible.builtin.meta: flush_handlers + - name: Verify domain services running + when: r_create_domain is changed + ansible.builtin.include_tasks: + file: tasks/domain_services_check.yml - name: Create some groups community.windows.win_domain_group: @@ -48,28 +54,3 @@ groups: "GroupC" retries: 5 delay: 10 - - handlers: - - name: Reboot host - ansible.windows.win_reboot: - reboot_timeout: 3600 - - - name: Wait for AD services - community.windows.win_wait_for_process: - process_name_exact: Microsoft.ActiveDirectory.WebServices - pre_wait_delay: 60 - state: present - timeout: 600 - sleep: 10 - - - name: Reboot again - ansible.windows.win_reboot: - reboot_timeout: 3600 - - - name: Wait for AD services again - community.windows.win_wait_for_process: - process_name_exact: Microsoft.ActiveDirectory.WebServices - pre_wait_delay: 60 - state: present - timeout: 600 - sleep: 10 diff --git a/windows/join_ad_domain.yml b/windows/join_ad_domain.yml index 529bc8e..e282af7 100644 --- a/windows/join_ad_domain.yml +++ b/windows/join_ad_domain.yml @@ -4,22 +4,31 @@ gather_facts: false tasks: + - name: Extract domain controller private ip + ansible.builtin.set_fact: + domain_controller_private_ip: "{{ hostvars[groups['purpose_domain_controller'][0]]['private_ip_address'] }}" + - name: Set a single address on the adapter named Ethernet ansible.windows.win_dns_client: adapter_names: 'Ethernet*' - dns_servers: "{{ hostvars[domain_controller]['private_ip_address'] }}" + dns_servers: "{{ domain_controller_private_ip }}" - name: Ensure Demo OU exists + run_once: true delegate_to: "{{ domain_controller }}" community.windows.win_domain_ou: name: Demo state: present + - name: Update the hostname + ansible.windows.win_hostname: + name: "{{ inventory_hostname.split('.')[0] }}" + - name: Join ansible.local domain register: r_domain_membership ansible.windows.win_domain_membership: dns_domain_name: ansible.local - hostname: "{{ inventory_hostname }}" + hostname: "{{ inventory_hostname.split('.')[0] }}" domain_admin_user: "{{ ansible_user }}@ansible.local" domain_admin_password: "{{ ansible_password }}" domain_ou_path: "OU=Demo,DC=ansible,DC=local" diff --git a/windows/rollback.yml b/windows/rollback.yml new file mode 100644 index 0000000..92648ae --- /dev/null +++ b/windows/rollback.yml @@ -0,0 +1,9 @@ +--- +- name: Rollback playbook + hosts: "{{ _hosts | default('os_windows') }}" + gather_facts: false + + tasks: + - name: Rollback this step + ansible.builtin.debug: + msg: "{{ rollback_msg | default('rolling back this step') }}" diff --git a/windows/setup.yml b/windows/setup.yml index 19f84d0..e41d5de 100644 --- a/windows/setup.yml +++ b/windows/setup.yml @@ -81,6 +81,52 @@ controller_templates: - 'Yes' - 'No' + - name: "WINDOWS / Rollback" + job_type: run + inventory: "Demo Inventory" + project: "Ansible official demo project" + playbook: "windows/rollback.yml" + execution_environment: Default execution environment + notification_templates_started: Telemetry + notification_templates_success: Telemetry + notification_templates_error: Telemetry + credentials: + - "Demo Credential" + survey_enabled: true + survey: + name: '' + description: '' + spec: + - question_name: Server Name or Pattern + type: text + variable: _hosts + required: false + - question_name: Rollback Message + type: text + variable: rollback_msg + required: false + + - name: "WINDOWS / Test Connectivity" + job_type: run + inventory: "Demo Inventory" + project: "Ansible official demo project" + playbook: "windows/connect.yml" + execution_environment: Default execution environment + notification_templates_started: Telemetry + notification_templates_success: Telemetry + notification_templates_error: Telemetry + credentials: + - "Demo Credential" + survey_enabled: true + survey: + name: '' + description: '' + spec: + - question_name: Server Name or Pattern + type: text + variable: _hosts + required: false + - name: "WINDOWS / Chocolatey install multiple" job_type: run inventory: "Demo Inventory" @@ -306,3 +352,139 @@ controller_templates: type: text variable: HOSTS required: false + +controller_workflows: + - name: Setup Active Directory Domain + description: A workflow to create a domain controller with two domain-joined Windows hosts. + organization: Default + notification_templates_started: Telemetry + notification_templates_success: Telemetry + notification_templates_error: Telemetry + survey_enabled: true + survey: + name: '' + description: '' + spec: + - question_name: AWS Region + type: multiplechoice + variable: create_vm_aws_region + required: true + default: us-east-2 + choices: + - us-east-1 + - us-east-2 + - us-west-1 + - us-west-2 + - question_name: Keypair Public Key + type: textarea + variable: aws_public_key + required: true + # Create VM variables + - question_name: Owner + type: text + variable: create_vm_vm_owner + required: true + - question_name: Environment + type: multiplechoice + variable: create_vm_vm_environment + required: true + choices: + - Dev + - QA + - Prod + - question_name: Subnet + type: text + variable: create_vm_aws_vpc_subnet_name + required: true + default: aws-test-subnet + - question_name: Security Group + type: text + variable: create_vm_aws_securitygroup_name + required: true + default: aws-test-sg + simplified_workflow_nodes: + - identifier: Create Keypair + unified_job_template: Cloud / AWS / Create Keypair + success_nodes: + - Create VPC + - identifier: Create VPC + unified_job_template: Cloud / AWS / Create VPC + success_nodes: + - Create Domain Controller + - Create Computer (1) + - Create Computer (2) + - identifier: Create Domain Controller + unified_job_template: Cloud / AWS / Create VM + job_type: run + extra_data: + create_vm_vm_name: dc01.ansible.local + create_vm_vm_purpose: domain_controller + create_vm_vm_deployment: domain_ansible_local + vm_blueprint: windows_full + success_nodes: + - Inventory Sync + - identifier: Create Computer (1) + unified_job_template: Cloud / AWS / Create VM + job_type: run + extra_data: + create_vm_vm_name: winston.ansible.local + create_vm_vm_purpose: domain_computer + create_vm_vm_deployment: domain_ansible_local + vm_blueprint: windows_core + success_nodes: + - Inventory Sync + - identifier: Create Computer (2) + unified_job_template: Cloud / AWS / Create VM + job_type: run + extra_data: + create_vm_vm_name: winthrop.ansible.local + create_vm_vm_purpose: domain_computer + create_vm_vm_deployment: domain_ansible_local + vm_blueprint: windows_core + success_nodes: + - Inventory Sync + - identifier: Inventory Sync + unified_job_template: AWS Inventory + all_parents_must_converge: true + success_nodes: + - Test Connectivity + - identifier: Test Connectivity + unified_job_template: WINDOWS / Test Connectivity + job_type: run + extra_data: + _hosts: deployment_domain_ansible_local + failure_nodes: + - Cleanup Resources + success_nodes: + - Create Domain + - identifier: Create Domain + unified_job_template: WINDOWS / AD / Create Domain + job_type: run + extra_data: + _hosts: purpose_domain_controller + failure_nodes: + - Cleanup Resources + success_nodes: + - Join Domain + - identifier: Join Domain + unified_job_template: WINDOWS / AD / Join Domain + job_type: run + extra_data: + _hosts: purpose_domain_computer + domain_controller: dc01.ansible.local + failure_nodes: + - Cleanup Resources + success_nodes: + - PowerShell Validation + - identifier: Cleanup Resources + unified_job_template: WINDOWS / Rollback + job_type: run + extra_data: + _hosts: localhost + rollback_msg: "Domain setup failed. Cleaning up resources..." + - identifier: PowerShell Validation + unified_job_template: WINDOWS / Run PowerShell + job_type: run + extra_data: + _hosts: purpose_domain_controller + ps_script: "Get-ADComputer -Filter * | Select-Object -Property 'Name'" diff --git a/windows/setup_domain_workflow.md b/windows/setup_domain_workflow.md new file mode 100644 index 0000000..1133892 --- /dev/null +++ b/windows/setup_domain_workflow.md @@ -0,0 +1,27 @@ +# Setup Active Directory Domain + +A workflow to create a domain controller with two domain-joined Windows hosts. + +## The Workflow + +![Workflow Visualization](../.github/images/setup_domain_workflow.png) + +## Ansible Inventory + +There are additional groups created in the **Demo Inventory** for interacting with different components of the domain: + +- **deployment_domain_ansible_local**: all hosts in the domain +- **purpose_domain_controller**: domain controller instances (1) +- **purpose_domain_computer**: domain computers (2) + +![Inventory](../.github/images/setup_domain_workflow_inventory.png) + +## Domain (ansible.local) + +![Domain Topology](../.github/images/setup_domain_workflow_domain.png) + +## PowerShell Validation + +In the validation step, you can expect to see the following output based on querying AD computers: + +![Expected Output](../.github/images/setup_domain_end_state.png) \ No newline at end of file diff --git a/windows/tasks/domain_services_check.yml b/windows/tasks/domain_services_check.yml new file mode 100644 index 0000000..590a4a0 --- /dev/null +++ b/windows/tasks/domain_services_check.yml @@ -0,0 +1,37 @@ +--- +- name: Initial services check + block: + - name: Initial reboot + ansible.windows.win_reboot: + reboot_timeout: 3600 + + - name: Wait for AD services + community.windows.win_wait_for_process: + process_name_exact: Microsoft.ActiveDirectory.WebServices + pre_wait_delay: 60 + state: present + timeout: 600 + sleep: 10 + rescue: + - name: Note initial failure + ansible.builtin.debug: + msg: "Initial services check failed, rebooting again..." + +- name: Secondary services check + block: + - name: Reboot again + ansible.windows.win_reboot: + reboot_timeout: 3600 + + - name: Wait for AD services again + community.windows.win_wait_for_process: + process_name_exact: Microsoft.ActiveDirectory.WebServices + pre_wait_delay: 60 + state: present + timeout: 600 + sleep: 10 + rescue: + - name: Note secondary failure + failed_when: true + ansible.builtin.debug: + msg: "Secondary services check failed, bailing out..."