Skip to content

EntraID Secrets Renewal Automation

Overzicht

Deze Ansible playbook hernieuwt secrets en certificaten voor EntraID App Registrations, getriggerd via Ivanti ITSM taken. De automatisering is ontworpen voor proactieve credential lifecycle management, waarbij verlopende secrets en certificaten tijdig worden vernieuwd voordat ze expireren. Dit voorkomt downtime in geautomatiseerde processen en services die afhankelijk zijn van deze credentials.

De playbook ondersteunt twee credential types: - Secrets: Eenvoudige wachtwoorden met 365 dagen geldigheid - Certificaten: X.509 certificaten gegenereerd via PKI infrastructure met self-service rotation (addKey API)


High-Level Flow

  1. Ivanti Task Processing: Ontvang en verwerk Ivanti Service Request Task met AppID en SecretType parameters
  2. EntraID Credentials Ophalen: Authenticatie credentials ophalen uit Passwordstate voor de juiste tenant
  3. App Registration Info Lookup: Application details ophalen via Microsoft Graph API
  4. Tenant Switching: Indien onderwijs tenant, switch naar andere Azure subscription en tenant
  5. Credential Type Routing:
  6. Voor Secrets: Nieuwe password genereren via Azure RM module
  7. Voor Certificaten: Volledig PKI workflow met certificate generation en addKey API
  8. Passwordstate Update: Nieuwe credential opslaan in Passwordstate met metadata
  9. Task Completion: Ivanti task afsluiten met status en notities

Sequence Diagram

sequenceDiagram
    participant Scan as Scanning Playbook
    participant Ivanti as Ivanti ITSM
    participant Ansible as Ansible Tower
    participant PWS as Passwordstate
    participant Azure as EntraID/Graph API
    participant PKI as PKI Infrastructure

    Note over Scan,Ivanti: Scheduled scanning identifies expiring credentials
    Scan->>Ivanti: Create Service Request Task<br/>(AppID, SecretType, Days)

    Note over Ivanti,Ansible: Renewal automation triggered
    Ivanti->>Ansible: Task available for processing
    Ansible->>Ivanti: Retrieve Task details (verwerk_task)
    Ivanti-->>Ansible: Task info (AppID, SecretType)

    Ansible->>PWS: Get EntraID API credentials
    PWS-->>Ansible: Graph API credentials

    Ansible->>Azure: Get App Registration info
    Azure-->>Ansible: App details (app_id, object_id, display_name)

    alt Secret Renewal
        Ansible->>PWS: Check Passwordstate entry exists
        PWS-->>Ansible: Entry found (or not)

        alt Entry exists
            Ansible->>Azure: Create new password (azure_rm_adpassword)
            Azure-->>Ansible: New secret value + metadata
            Ansible->>PWS: Update Passwordstate entry
            PWS-->>Ansible: Update success
            Ansible->>Ivanti: Close task (success)
        else Entry not found
            Ansible->>Ivanti: Assign to Systeemsoftware + Add Note
            Ivanti-->>Ansible: Task assigned
        end

    else Certificate Renewal
        Ansible->>PWS: Get PKI credentials
        PWS-->>Ansible: PKI service account

        Ansible->>PWS: Check certificate entry exists
        PWS-->>Ansible: Certificate entry + GenericField7 JSON

        alt Onderwijs tenant special handling
            Ansible->>PWS: Check for alternative cert name<br/>(without _OND suffix)
            PWS-->>Ansible: Alternative cert found
            Ansible->>Ivanti: Assign to Systeemsoftware<br/>(manual upload required)
        end

        Ansible->>PWS: Get OLD certificate PFX document
        PWS-->>Ansible: PFX file + password

        Ansible->>PKI: Generate NEW certificate<br/>(pki_certificate role)
        PKI-->>Ansible: New PFX file + PublicKey

        Note over Ansible: Self-service rotation with addKey API
        Ansible->>Ansible: Generate client_assertion JWT<br/>(OLD certificate)
        Ansible->>Azure: Get access token<br/>(certificate authentication)
        Azure-->>Ansible: Access token

        Ansible->>Ansible: Generate PoP token<br/>(Proof-of-Possession)
        Ansible->>Azure: POST /applications/{id}/addKey<br/>(New cert + PoP token)

        alt addKey Success
            Azure-->>Ansible: Certificate added (200 OK)
            Ansible->>PWS: Update certificate entry<br/>(new PFX document)
            Ansible->>Ivanti: Close task (success)
        else addKey Failure
            Azure-->>Ansible: Error response
            Ansible->>Ivanti: Assign to Systeemsoftware + Add Note
        end
    end

Components

1. Ivanti ITSM Integration

  • Collection: d09.ivanti_itsm
  • Roles/Modules:
  • verwerk_task: Retrieve task details from Service Request (pws_list_id: 8620)
  • assign_task: Assign failed tasks to Systeemsoftware team
  • add_note: Add status updates to tasks (success/failure)
  • close_task: Close successfully completed tasks

Task Input Parameters (servicereq_params): - AppID: EntraID Application (Client) ID to renew credentials for - SecretType: Type van credential (Secret of Certificaat/Cert)

2. Passwordstate Integration

  • Collection: d09.passwordstate
  • Password Lists:
  • 8620: Systeem Accounts (PKI credentials, Ansible credentials)
  • 6691: Certificaten > EntraID ServicePrincipal Certificaten
  • 7651: Systeem_EntraID_AppReg_PR (production secrets)
  • 8633: Systeem_Azure_OND_Admin (onderwijs secrets)

Key Operations: - Retrieve EntraID API credentials (Sys_Azure_AppRegs_PR / Sys_Azure_OND_Admin) - Retrieve PKI service account (sys_srvaapwin_pki) - Check Passwordstate entry exists for App Registration - Update Passwordstate with new secret/certificate values - Retrieve and upload PFX documents

3. EntraID / Microsoft Graph API

  • Collection: azure.azcollection
  • Modules:
  • azure_rm_adapplication_info: Retrieve App Registration details
  • azure_rm_adpassword: Create new secret for App Registration

Manual API Calls: - Certificate Authentication: POST /oauth2/v2.0/token with client_assertion JWT - addKey API: POST /applications/{id}/addKey with Proof-of-Possession token

4. PKI Certificate Generation

  • Role: d09.certificates.pki_certificate
  • Target System: srvaapwinpr01.gentgrp.gent.be (Windows PKI server)
  • Default Template: _D09-CA2-SHA256-EntraID
  • Output: New PFX file with certificate + private key uploaded to Passwordstate

5. Tenant Configuration

Production Tenant (default): - Tenant ID: {{ azure_tenant }} - Subscription ID: Default subscription - Passwordstate List: 7651 (Systeem_EntraID_AppReg_PR)

Onderwijs Tenant (onderwijs flag set): - Tenant ID: Switched via conditional - Subscription ID: Switched via conditional
- Passwordstate List: 8633 (Systeem_Azure_OND_Admin) - Special handling voor certificaten (naam zonder _OND suffix)


Renewal Process Details

Secret Renewal (Secrets)

  1. Passwordstate Validation: Check of Passwordstate entry bestaat voor App Registration naam
  2. Azure RM Password Creation:
  3. Module: azure.azcollection.azure_rm_adpassword
  4. Validity: 365 dagen (days_secret_valid variable)
  5. Output: secret_value, key_id, end_date
  6. Passwordstate Update: Update GenericField6 met JSON metadata:
    {
      "AppID": "12345678-1234-1234-1234-123456789abc",
      "KeyID": "abcdef12-3456-7890-abcd-ef1234567890",
      "EndDate": "2025-12-31"
    }
    
  7. Task Closure: Ivanti task sluiten met resolution note

Failure Handling: - Als Passwordstate entry niet bestaat → Assign to Systeemsoftware - Bij Azure RM fouten → Rescue block vangt error op

Certificate Renewal (Certificaten)

  1. PKI Credentials: Ophalen service account (sys_srvaapwin_pki) uit Passwordstate list 8620
  2. Certificate Entry Validation: Check Passwordstate entry in list 6691
  3. Title format: Certificaat {AppDisplayName}
  4. GenericField7 bevat JSON met certificaat metadata (UsedTemplate)
  5. Onderwijs Special Handling:
  6. Check voor alternatieve certificaat entry zonder _OND suffix
  7. Als gevonden → Assign to Systeemsoftware (manual upload required)
  8. OLD Certificate Retrieval:
  9. Query SQL database voor PFX DocumentID via win_powershell (SQL query)
  10. Download OLD PFX document uit Passwordstate
  11. NEW Certificate Generation:
  12. Role: d09.certificates.pki_certificate
  13. Template uit GenericField7 of default _D09-CA2-SHA256-EntraID
  14. Output: Nieuwe PFX file geupload naar Passwordstate
  15. Self-Service Rotation (addKey API):
  16. Step 1: Generate client_assertion JWT met OLD certificate
    • Script: generate_jwt_token.py (TOKEN_TYPE=client_assertion)
    • Claims: aud, iss, sub, jti, exp
  17. Step 2: Get access token via certificate authentication
    • Endpoint: POST /oauth2/v2.0/token
    • Body: client_id, client_assertion, grant_type=client_credentials
  18. Step 3: Generate Proof-of-Possession (PoP) token
    • Script: generate_jwt_token.py (TOKEN_TYPE=pop)
    • Claims: sub, iss (beide object_id), aud=00000002-0000-0000-c000-000000000000
  19. Step 4: Call addKey API
    • Endpoint: POST /applications/{object_id}/addKey
    • Headers: Authorization: Bearer {access_token}
    • Body: keyCredential (new cert public key) + proof (PoP token)
  20. Success/Failure Handling:
  21. Success (200 OK): Update Passwordstate + Close task
  22. Failure: Assign to Systeemsoftware + Add error note

Failure Scenarios: - Passwordstate entry niet gevonden → Assign to Systeemsoftware - Alternatieve EDU cert gevonden → Manual upload required - addKey API fout (bijv. PoP validation failed) → Assign to Systeemsoftware


Error Handling

Rescue Block

  • Vangt alle errors tijdens secret/certificate renewal proces
  • Set secret_renewal.success = false
  • Set noteError met error details

Always Block (Cleanup/Finalization)

Executed regardless of success/failure: 1. Set success flag: secret_renewal_success = true (only if renewal succeeded) 2. Extract error message: Set noteError from secret_renewal.error 3. Add failure note: If secret_renewal_success == false, add note to Ivanti task 4. Assign to team: If failed, assign task to Systeemsoftware for manual intervention 5. Close task: If successful, close Ivanti task with resolution


Python Script Requirements

generate_jwt_token.py

Purpose: Generate JWT tokens voor EntraID certificate authentication

Token Types:

  1. client_assertion (Client Authentication JWT):
  2. Environment variables: TOKEN_TYPE, PFX_PATH, PFX_PASSWORD, TENANT_ID, CLIENT_ID
  3. Claims: aud, iss, sub (CLIENT_ID), jti, exp
  4. Signing: Privésleutel uit OLD PFX file
  5. Usage: Authenticate App Registration met certificate

  6. pop (Proof-of-Possession Token):

  7. Environment variables: TOKEN_TYPE, PFX_PATH, PFX_PASSWORD, TENANT_ID, SUB_ID, ISS_ID, AUD
  8. Claims: sub (object_id), iss (object_id), aud (Graph API resource: 00000002-0000-0000-c000-000000000000), jti, exp
  9. Signing: Privésleutel uit OLD PFX file
  10. Usage: Prove ownership van OLD certificate voor addKey API authorization

Script Location: Must be accessible from Ansible control node (localhost delegation)


Ivanti Integration Details

Input (Service Request Task Parameters)

task_info.servicereq_params:
  AppID: "12345678-1234-1234-1234-123456789abc"
  SecretType: "Secret"  # or "Certificaat" / "Cert"

Output Actions

Success Scenario: - Close Task: d09.ivanti_itsm.close_task - Resolved by: Ansible API user - Resolution: "Secret/Certificate renewed successfully for {AppDisplayName}" - Time spent: 1 minuut

Failure Scenario: - Assign Task: d09.ivanti_itsm.assign_task → Systeemsoftware team - Add Note: d09.ivanti_itsm.add_note - Subject: "Secret/Certificaat renewal failed" - Body: Error details (Passwordstate entry not found, addKey failure, etc.) - Category: Status Update - Time spent: 1 minuut


Benefits

  1. Proactieve Credential Management: Voorkomt service downtime door automatische renewal voordat credentials expireren
  2. Self-Service Certificate Rotation: addKey API elimineert handmatige interventie voor certificaat renewal
  3. Multi-Tenant Support: Seamless ondersteuning voor production én onderwijs tenants
  4. Passwordstate Integration: Centrale credential storage met automatische updates
  5. Ivanti Workflow: Volledige traceability via Service Request Tasks met status updates
  6. Error Handling: Robuuste rescue/always blocks zorgen voor proper task status updates bij failures
  7. Security: Certificate-based authentication (client_assertion + PoP tokens) voor Graph API calls
  8. Audit Trail: Alle acties gelogd in Ivanti met timestamps en team assignments