Check Oauth2 token lifetime in rhaap description

When an Oauth2 API token is created in rhaap it has a default lifetime of 365 days, this cannot be overwritten or updated. So a token created in rhaap will expire and become obsolete.
When using these tokens actively (and you will), you will forget they are there and they will expire! This may cause unwanted outage, because playbooks won't run, collections can't download and more possible errors, depending on where you are using these tokens.

In this document, I will only show the most important (for me), that is the token that I create during the configuration as code base pipeline run. This creates a token that is actively used in the configuration of automation platform (Ansible Galaxy/Automation Hub API Token) used by the organizations. This token is also used in the distributed ansible.cfg that is downloadable from the webserver. So there can be many dependencies to this token.

So what I did to check and alert this:
- I created an alertmanager instance in my network
- Alertmanager can send alerts to a telegram bot account
- Created a playbook to check the token and send the alert
- Added this task as schedule to the configuration as code of rhaap

After these steps, I get an alert if the token expires within 30 days on my phone (or any other alertmanager target) wich tells me to run the base configuration as code to create a new version of the token and upload a new version of ansible.cfg to the webserver.
I could even create an EDA rulebook to run the configuration as code for me (self healing).

The playbook/project

This check consists of just this one simple playbook with a few variables defined into the playbook itself.

It will need a few values that must be passed to the playbook, using a credential or as extra variables (as these are sensitive variables passing them as a credential is preferred/mandatory).

Variables:
alertmanager_url: "http://alertmanager.[your-domain]:9093"
The url where your instance of the alertmanager can be reached to post the alert to.

token_description: "ansible_cfg_token"
The desciption of the token to find in rhaap (this must be unique!).

expire_alert_days: 30
The minimal number of days the token has to be valid for, is it smaller or equal, an alert will be sent.

The play will further need a credential to be able to login to the API and list the token. This must at least be an account with sufficient rights to read the token specified (preferably an admin account).
The credential needs to have the following fields:
- aap_hostname The fqdn of the gateway host
- aap_username The username for the admin account
- aap_password The password for the admin account

The playbook:

---
- name: Check and renew ansible.cfg API token
  hosts: "{{ instance | default('localhost') }}"
  connection: local
  gather_subset:
    - min
  vars:
    # Change this to your Alertmanager instance URL
    alertmanager_url: "http://alertmanager.[your-domain]:9093"
    token_description: "ansible_cfg_token"
    expire_alert_days: 30

  tasks:
    # Generate a hub token to use for the galaxy credentials in controller
    # This token is not echoed, so for use in ansible.cfg, you must use a new account
    # and create a token for that account after configuration.
    - name: Gateway | Read the current token
      ansible.builtin.uri:
        url: "https://{{ aap_hostname }}/api/gateway/v1/tokens/?description={{ token_description }}"
        user: "{{ aap_username }}"
        password: "{{ aap_password }}"
        force_basic_auth: true
        method: GET
        body_format: json
        validate_certs: false
      register: _ansible_cfg_token
      no_log: true

    - name: Set time facts for calculating remaining lifetime
      ansible.builtin.set_fact:
        expires_epoch: "{{ (_ansible_cfg_token.json.results[0].expires | to_datetime('%Y-%m-%dT%H:%M:%S.%fZ')).strftime('%s') | int }}"
        current_epoch: "{{ ansible_date_time.epoch | int }}"

    - name: Calculate token lifetime remaining in days
      ansible.builtin.set_fact:
        token_life: "{{ ((expires_epoch - current_epoch) / 86400) | int }}"

    - name: Post firing alert to Alertmanager API v2
      ansible.builtin.uri:
        url: "{{ alertmanager_url }}/api/v2/alerts"
        method: POST
        status_code: 200
        body_format: json
        headers:
          Content-Type: "application/json"
        body:
          - labels:
              alertname: "Token-Ansible-Expiry-Notice"
              severity: "critical"
              instance: "{{ aap_hostname }}"
              job: "rhaap_check_token"
            annotations:
              summary: "Ansible.cfg token expires in {{ token_life }} days."
              description: "Please run the 'base config' configuration as code."
            generatorURL: "https://{{ aap_hostname }}"
            startsAt: "{{ now(utc=true).isoformat() }}Z"
      register: alert_response
      when: token_life <= expire_alert_days

    - name: Print API response status
      ansible.builtin.debug:
        msg: "Alert sent successfully! Status code: {{ alert_response.status }}"
      when: alert_response.status is defined

In configuration as code

Project: Add this into the file: group_vars/dev/controller_projects.yaml

controller_projects_dev:

  - name: prj_check_rhaap_ansible_token
    description: Check the lifetime for token
    organization: [your org]
    scm_type: git
    scm_url: [your path to the project]/rhaap-check-api-token.git
    scm_credential: gitlab
    scm_branch: master
    scm_clean: false
    scm_delete_on_update: false
    scm_update_on_launch: true
    scm_update_cache_timeout: 0
    allow_override: false
    timeout: 0

Job_template: Add this to the file: group_vars/dev/controller_templates.yaml

controller_templates_dev:

  - name: check_rhaap_ansible_token
    description:
    organization: MGT
    project: prj_check_rhaap_ansible_token
    inventory: Default_inventory
    playbook: main.yml
    job_type: run
    fact_caching_enabled: false
    credentials:
      - aap_credential
    concurrent_jobs_enabled: false
    ask_scm_branch_on_launch: false
    ask_tags_on_launch: false
    ask_verbosity_on_launch: false
    ask_variables_on_launch: false
    execution_environment: ee_default 1-5
    survey_enabled: false
    survey_spec: {}

Schedule: Add this to the file: group_vars/dev/controller_schedules.yaml

controller_schedules_dev:

  - name: Check ansible token
    description: Check the ansible token lifetime
    unified_job_template: check_rhaap_ansible_token
    rrule: "DTSTART;TZID=Europe/Amsterdam:20260812T090000 RRULE:FREQ=DAILY;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR,SA,SU"

When the configurationas code for this organization is run, the project, job_template and schedule are added to the controller.
If your alertmanager is setup correctly, you will get an alert when the token is about to expire.