# Automation with Ansible
Demonisioning: web01, nmon-01, docker-01 😢
___
## New Machines
### controller-charlotte - Ubuntu
configure with netplan
```
network:
  ethernets:
    ens160:
      dhcp4: no
      addresses:
        - 10.0.5.90/24
      routes:
        - to: default
          via: 10.0.5.2
      nameservers:
        addresses:
          - 10.0.5.5
  version: 2
```
#### to reset DNS
```
dhclient -r
dhclient
```
### ansible1-charlotte - CentOS
configure with nmtui
- IP: 10.0.5.91
- DG: 10.0.5.2
- DNS: 10.0.5.5
### ansible2-charlotte - CentOS
configure with nmtui
- IP: 10.0.5.92
- DG: 10.0.5.2
- DNS: 10.0.5.5

## Initial Configuration
- on all machines, create a sudo account named deployer (use same password across all systems)
- install ansible on controller
```
sudo apt install ansible sshpass python3-paramiko
```
- Configure sudo access:
  - create `/etc/sudoers.d/sys265` on all systems
  - add the following line to allow passwordless sudo for deployer:
   ```
   deployer ALL=(ALL) NOPASSWD:ALL
   ```

> [!Note]
> Although it is not uncommon to update `/etc/sudoers` directly, it is far easier to script the addition of a file to `/etc/sudoers.d`


## SSH Key Setup
As the deployer user on controller:
- Create RSA keypair with passphrase:
```
ssh-keygen -t rsa
```
- copy pukey to ansible1 and ansible2
```
ssh-copy-id deployer@ansible1-charlotte
ssh-copy-id deployer@ansible2-charlotte
```
-configure `ssh-agent` to avoid typing passphrase for 4 hours
```
eval(ssh-agent) # test to see if ssh-agent is running, and if not,run it
ssh-add -t 14400
```
## Ansible Configuration
in `deployer@controller:/home/deployer/`
- make directory structure
```
mkdir -p ansible/roles
cd ansible/
```
- create inventory and test conection
```
echo ansible1-charlotte >> inventory.txt
echo ansible2-charlotte >> inventory.txt
cat inventory.txt
```
```
ansible all -m ping -i inventory.txt
```

- add webmin tag to `inventory.txt` and test

```
ansible1-charlotte
[webmin]
ansible2-charlotte
```

```
deployer@controller-charlotte:~/ansible$ ansible webmin -m ping -i inventory.txt
ansible2-charlotte | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}
```

## webmin installation
- install webmin role
```
ansible-galaxy install semuadmin.webmin -p roles/
```
- create `webmin.yml` playbook to handle repository setup, installation, and firewall configuration
```
- name: webmin sys265
  hosts: webmin
  become: true    # Run all tasks with sudo/root privileges
  vars:
    install_utilities: false
    firewalld_enable: true

  pre_tasks: # before role execution. we need the repo/key before executing webmin installation role
    - name: add webmin repo and GPG key
      yum_repository:
        name: webmin
        description: Webmin Distribution Neutral
        baseurl: http://download.webmin.com/download/yum
        enabled: true
        gpgcheck: true
        gpgkey: http://www.webmin.com/jcameron-key.asc

   # update YUM cache to recognize new repository
    - name: clean and update YUM cache
      yum:
        update_cache: yes

  roles:
    - semuadmin.webmin    # apply the webmin installation role

  handlers: # will run when a task has notify:name parameter
    - name: reload firewall # runs after adding firewall rule
      command: firewall-cmd --reload

  tasks:
    # open port 10000 in firewall for webmin web interface
    - name: add firewall rule
      firewalld:
        port: 10000/tcp
        permanent: true
        state: enabled
      notify: reload firewall

    - name: install webmin
      yum:
        name: webmin
        state: present # will only install if not already

    - name: enable and start webmin service
      systemd:
        name: webmin
        enabled: true
        state: started
        daemon_reload: yes # reload systemd to recognize new service
```
- run playbook
```
ansible-playbook -i inventory.txt roles/webmin.yml
```
- change webmin root password
```
 sudo /usr/libexec/webmin/changepass.pl /etc/webmin root newpassword
```


## apache isntallation
- edit inventory.txt
```
[apache]
ansible1-charlotte
[webmin]
ansible2-charlotte
```
- install apache role
```
ansible-galaxy install geerlingguy.apache -p roles/
```
- create `apache.yml` file
```
- name: apache sys265
  hosts: apache
  become: true    # Run all tasks with sudo/root privileges
  vars:
    install_utilities: false
    firewalld_enable: true
    ansible_os_family: RedHat
    ansible_distribution: CentOS # required because role searches for Rocky config files
  roles:
    - geerlingguy.apache    # apply the apache installation role

  handlers: # will run when a task has notify:name parameter
    - name: reload firewall # runs after adding firewall rule
      command: firewall-cmd --reload

  tasks:
    # open port 443 in firewall for apache web interface
    - name: add firewall rule
      firewalld:
        port: "{{ item }}"
        permanent: true
        immediate: true
        state: enabled
      loop:
        - 80/tcp
        - 443/tcp
      notify: reload firewall

    - name: install apache
      yum:
        name: httpd
        state: present # will only install if not already

    - name: enable and start apache service
      systemd:
        name: httpd
        enabled: true
        state: started
        daemon_reload: yes # reload systemd to recognize new service

```
- run playbook
```
ansible-playbook -i inventory.txt roles/webmin.yml
```

# Ansible on Windows
## OpenSSH Server Setup

>[!Caution]
> DO NOT INSTALL 32 BIT VERSION

### Install OpenSSH
Run these commands in PowerShell as Administrator:
```
wget https://github.com/PowerShell/Win32-OpenSSH/releases/download/v9.8.1.0p1-Preview/OpenSSH-Win64.zip -O 'C:\Program Files\OpenSSH.zip'
Expand-Archive -Path 'C:\Program Files\OpenSSH.zip' -DestinationPath 'C:\Program Files\OpenSSH'
rm 'C:\Program Files\OpenSSH.zip'
powershell.exe -ExecutionPolicy Bypass -File 'C:\Program Files\OpenSSH\OpenSSH-Win64\install-sshd.ps1'
```
### Configure OpenSSH
- start service
```
Start-Service sshd
Set-Service -Name sshd -StartupType 'Automatic'
Get-Service -Name sshd # check if running
```
- add firewall rule
```
New-NetFirewallRule -Name sshd -DisplayName 'OpenSSH Server' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22
Get-NetFirewallRule | Where-Object DisplayName -Like '*ssh*'
```
- set PowerShell as default SSH shell
```
Set-ItemProperty "HKLM:\Software\Microsoft\Powershell\1\ShellIds" -Name ConsolePrompting -Value $true
New-ItemProperty -Path HKLM:\SOFTWARE\OpenSSH -Name DefaultShell -Value "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -PropertyType String -Force
```
- add `charlotte.croce-adm` to the **Remote Management Users** groups
- Add/uncomment the following lines in C:\ProgramData\ssh\sshd_config
  - `StrictModes no` is sometimes needed on Windows systems because Windows permissions don't map perfectly to the UNIX-style permissions that OpenSSH expects
```
AllowUsers charlotte\charlotte.croce-adm
StrictModes no
```
## Ansible Setup
### Inventory Setup
- add windows machines to `inventory.txt`
```
[windows]
mgmt01-charlotte
wks01-charlotte
[windows:vars]
ansible_shell_type=powershell
```
- create ansible.cfg in ansible directory, to skip host key checking
```
[defaults]
host_key_checking = false
```
- test connection
```
ansible windows -i inventory.txt -m win_ping -u charlotte.croce-adm@charlotte.local --ask-pass
```

## Software deployment using win_chocolatey
- create playbook `roles/windows_software.yml`
```
- name: install windows applications
  hosts: windows
  tasks:
    - name: install firefox and 7zip
      win_chocolatey:
        name:
        - firefox
        - 7zip
        state: present
```
- run playbook
```
ansible-playbook -i inventory.txt roles/windows_software.yml -u charlotte.croce-adm@charlotte.local --ask-pass
```
- If you encounter .NET Framework errors, install version 4.8 (in my case I needed version 4.8, it will probably be a different version in the future)
```
Invoke-WebRequest -Uri "https://go.microsoft.com/fwlink/?linkid=2088631" -OutFile "C:\dotNetFx48.exe"
Start-Process -FilePath "C:\dotNetFx48.exe" -ArgumentList "/quiet /norestart" -Wait
Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full" -Name Release # verify installation
```
> [!Note]
> Installation may take several minutes. System restart required after installation.

- list packages installed with chocolatey
```
'C:\ProgramData\chocolatey\bin\choco.exe' list
```

