Installing AWX on AlmaLinux 9

I ran into some issues installing AWX on AlmaLinux 9 on Proxmox (I had the same issues with Alma 8.7). This also applies to RockyLinux 9.

I was installing AWX via Rancher following https://github.com/ansible/awx-operator#basic-install. I made it all the way to the section where you create the awx-demo.yaml, add it to your kustomization.yaml and build via kustomize build . | kubectl apply -f -. From there I was receiving errors such as “unable to determine if virtual resource”,”gvk”:”apps/v1″ and the build would ultimately fail out.

In order to make it past that error I found a found a few posts which suggested changing the CPU type from “Default (kvm64)” to Host. This sets the VM to match the CPU of the host.

***If you are running HyperV, there is a similar option, see the final post in this Google Group conversation: https://groups.google.com/g/awx-project/c/4tmP0TlRODU.***

After resetting the CPU type, rebooting the vm and re-running the kustomize build, I was able to make it quite a bit further. The logs looked like there were no issues, then towards the end the script once again failed. This time I was seeing the following error: “awx unable to retrieve the complete list of server APIs: metrics.k8s.io/v1beta1:”. The Pod itself was also down with a CrashLoopBackOff error. From there I found the following link which was able to get me past all of my installation issues: https://stackoverflow.com/questions/62442679/could-not-get-apiversions-from-kubernetes-unable-to-retrieve-the-complete-list

I ran: kubectl api-resources which listed the resources and metrics.k8s.io/v1beta1 was in fact down.

Next I ran: kubectl delete apiservice/v1beta1.metrics.k8s.io

From there I re-ran the kustomize build command and awx installation completed successfully after the installation. I did have to open the firewall ports in Alma to allow my browser to access AWX.

Steps to Install AWX:

#Install Rancher
curl -sfL https://get.k3s.io | sh -

#Install Kustomize
curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh"  | bash

#Move Kustomize binary
mv kustomize /usr/local/bin/

#Goto AWX Readme and follow along from there:
# https://github.com/ansible/awx-operator#basic-install

Feel free to contact me if you have any comments or questions

Disabling Inactive Domain User and Computer Accounts in Active Directory with Ansible

In my last article I wrote about having Ansible run several audit requests including: “We need a list of all inactive user accounts” as well as “We need a list of inactive computer accounts”. Now that we have those listed, we can let Ansible clean those up. I preferred to create a new playbook for these tasks. First it will list the Users and Computers it will be handling first, next it will disable the account, followed by moving it to either the Inactive_Users or Inactive_Computers OU. I never delete the accounts as we prefer to disable, then move them.

Below is my ansible playbook “fix_AD_Inactive-Users-AND-Computers-90days.yml”

---
- hosts: pdc
  gather_facts: no
  tasks:
     - name: copy file to windows
       win_copy:
          src: files/fix_inactive_usr.ps1
          dest: c:\it\fix_inactive_usr.ps1

     - name: copy file to windows
       win_copy:
          src: files/fix_inactive_pc.ps1
          dest: c:\it\fix_inactive_pc.ps1

     - name: Fix inactive users - 90 days
       win_shell: c:\it\fix_inactive_usr.ps1
       register: inactive_usr

     - debug: var=inactive_usr.stdout_lines

     - name: Fix inactive computers - 90 days
       win_shell: c:\it\fix_inactive_pc.ps1
       register: inactive_computer

     - debug: var=inactive_computer.stdout_lines

Below is the code for “fix_inactive_usr.ps1”

$date = (get-date).AddDays(-90)

$USR = (Get-ADUser -Filter {LastLogonDate -lt $date} -Property Enabled | Where-Object {$_.Enabled -like "true"} | Select DistinguishedName).DistinguishedName
echo $USR
ForEach ($Item in $USR){
   Disable-ADAccount $Item
   Move-ADObject -Identity $Item -TargetPath "OU=Disabled_Accounts,DC=contoso,DC=com"
   }

Please note in the PowerShell scripts above and below, you will need to change “DC=contoso,DC=com” to reflect your actual domain

Below is the code for “fix_inactive_pc.ps1”

# Specify inactivity range value below
$DaysInactive = 90
# $time variable converts $DaysInactive to LastLogonTimeStamp property format for the -Filter switch to work

$time = (Get-Date).Adddays(-($DaysInactive))

# Identify inactive computer accounts

$PC = (Get-ADComputer -Filter {LastLogonTimeStamp -lt $time} -Property Enabled | Where-Object {$_.Enabled -like "true"} | Select DistinguishedName).DistinguishedName
echo $PC
ForEach ($Item in $PC){
   Disable-ADAccount $Item
   Move-ADObject -Identity $Item -TargetPath "OU=Disabled_Computers,DC=contoso,DC=com"
   }

Audit Active Directory with Ansible

Everyone loves an audit right? We have to deal with audits quite a bit and that requires remedial tasks like “We need a list of AD user accounts that have been locked out”, “We need a list of all inactive user accounts”, “We need a list of inactive computer accounts”, “We need a list of all members of Domain Admins group” as well as “We need a list of all AD accounts”. All of these requirements can easily be scripted with PowerShell. Since I love to automate things and I would rather not run these commands separately, I figured I would just create an Ansible script to run all request at the same time. that way I could logon once, select my Ansible playbook and let it run and I don’t even need to logon to the DC to run theses tasks. I can sit back and let Ansible deal with this.

This simple Ansible playbook uses 3 PowerShell commands and 2 PowerShell scripts that I’m sure most Windows Administrators are familiar with.

---
- hosts: pdc
  gather_facts: no
  tasks:
     - name: copy audit_AD_inactive_users.ps1 to Windows
       win_copy:
          src: files/audit_AD_inactive_users.ps1
          dest: c:\cit\audit_AD_inactive_users.ps1

     - name: copy audit_AD_inactive_computers.ps1 to Windows
       win_copy:
          src: files/audit_AD_inactive_computers.ps1
          dest: c:\cit\audit_AD_inactive_computers.ps1

     - name: Run Audit for Locked-Out Accounts
       win_shell: Search-AdAccount -LockedOut | select Name, LockedOut,LastLogonDate,distinguishedName
       register: lockedoutaccounts

     - debug: var=lockedoutaccounts.stdout_lines

     - name: Run Audit of inactive users - 90 days
       win_shell: c:\cit\audit_AD_inactive_users.ps1
       register: inactive_users

     - debug: var=inactive_users.stdout_lines

     - name: Run Audit of inactive computers - 90 days
       win_shell: c:\cit\audit_AD_inactive_computers.ps1
       register: inactive_computers

     - debug: var=inactive_computers.stdout_lines

     - name: Run Audit for members of Domain Admins group
       win_shell: Get-ADGroupMember -Identity 'Domain Admins' | Select-Object name, objectClass,distinguishedName
       register: dom_admin_users

     - debug: var=dom_admin_users.stdout_lines

     - name: Run Audit for all domain users
       win_shell: Get-ADUser -Filter * -SearchBase "dc=contoso,dc=com" | select Name, objectClass,distinguishedName
       register: all_dom_users

     - debug: var=all_dom_users.stdout_lines

Not bad right? Ansible Rocks! The only complaint I may see is I’m not outputting the results to a CSV file, but if you run this script often, you shouldn’t need the fancy format.

Below is the first PowerShell script “audit_AD_inactive_users.ps1”

$date = (get-date).AddDays(-90)

Get-ADUser -Filter {LastLogonDate -lt $date} -Property Enabled | Where-Object {$_.Enabled -like “true”} | Select Name, SamAccountName, DistinguishedName

Below is the second PowerShell script “audit_AD_inactive_computers.ps1”

# Specify inactivity range value below
$DaysInactive = 90
# $time variable converts $DaysInactive to LastLogonTimeStamp property format for the -Filter switch to work

$time = (Get-Date).Adddays(-($DaysInactive))

# Identify inactive computer accounts

Get-ADComputer -Filter {LastLogonTimeStamp -lt $time} -ResultPageSize 2000 -resultSetSize $null -Properties Name, OperatingSystem, SamAccountName, DistinguishedName, LastLogonDate | Select DNSHostName, LastLogonDate, DistinguishedName

Using Ansible to track down exact port on switch a mac address is connected to

 I have a group of switches that users keep asking me to locate mac address for in order to trace down the exact port and edit that port to assign it in new VLAN. Rather than logging into each switch and tracking down the switch where the mac resides, I created a basic ansible playbook to help me with this. This has been a huge time saver. Hopefully this can help someone else (It helps if your switch ports have descriptions):

---

- name: Find mac address in sec-switches

  hosts: sec-switch

  gather_facts: false

  connection: local

  vars_prompt:

     - name: mac

       prompt: What is the mac address?

       private: no

  tasks:

    -

      name: debugging

      ansible.builtin.debug:

        msg: 'Searching for {{ mac }}'

    -

      name: search

      ios_command:

        commands:

          - "show mac address-table | include {{ mac }}"

      register: printout

    - set_fact:

        intf: |

          {{printout.stdout_lines[0] |

            map('regex_replace','^(?:[^ ]*\ ){12}([^ ]*)') |

            list }}

    -

      name: show int desc

      ios_command:

        commands:

          - "sh interfaces description | inc {{ intf[0].strip() }}"

      register: printout2

    - name: View output

      debug:

        var: printout2

<Snippet of output>

ok: [switch9] => {

    “printout2”: {

        “changed”: false,

        “failed”: false,

        “stdout”: [

            “Gi1/0/42                       up             up       SEG 12 “

        ],

        “stdout_lines”: [

            [

                “Gi1/0/42                       up             up      SEG1 2”

            ]

        ]

    }

}

ok: [switch20] => {

    “printout2”: {

        “changed”: false,

        “failed”: false,

        “stdout”: [

            “Gi1/0/25                       up             up       UPLINK”

        ],

        “stdout_lines”: [

            [

                “Gi1/0/25                       up             up       UPLINK”

Special shout out to rajthecomputerguy, who helped me by suggesting:

Use strip() method to get rid of whitespace debug: var: intf[0].strip() 

Ansible Automation: Gather list of all services on windows servers and clients

I had another audit request to gather all services on windows servers in an environment of about 70+ servers. I knew doing this through Ansible would be allot faster than going to each server individually. In the end it took less than 5 minutes to gather the services on 70+ servers.

When running the script I usually tee the output to text:

IE: ansible-playbook Audit_win_list_all_services.yml | tee /tmp/audit/Windows_services.txt

Here is my playbook:

Audit_win_list_all_services.yml

Ansible Automation: Gather list of all software installed on windows servers and clients

I had a request to gather all software installed on windows servers in an environment of about 70+ servers. I knew doing this through Ansible would be allot faster than going to each server individually. In the end it took less than 5 minutes to gather the installed software on 70+ servers.

I had seen a few playbooks online from other Ansible Admins doing this via Win32_Product, but I have seen warnings about using Win_32Product causing problems.

So after reading this article, I created the following playbook (I initially used a normal debug statement, but the output had allot of unnecessary info, so I split the output by newline and printed that list):

Below is my playbook:

win_list_all_programs.yml