ISE Posture Conditions

Posture Compliance Flow

Script Conditions

ISE Service conditions don’t support Linux. Use Script conditions:

pr_Linux_ClamAV_Running

#!/bin/bash
if systemctl is-active --quiet clamav-daemon 2>/dev/null; then
    exit 0
elif systemctl is-active --quiet clamd@scan 2>/dev/null; then
    exit 0
else
    exit 1
fi

pr_Linux_ClamAV_Definitions

#!/bin/bash
DAILY_CVD="/var/lib/clamav/daily.cvd"
MAX_AGE_DAYS=7

if [[ -f "$DAILY_CVD" ]]; then
    FILE_AGE_SECS=$(($(date +%s) - $(stat -c %Y "$DAILY_CVD")))
    MAX_AGE_SECS=$((MAX_AGE_DAYS * 86400))
    [[ $FILE_AGE_SECS -lt $MAX_AGE_SECS ]] && exit 0
fi
exit 1

pr_Linux_UFW_Active

#!/bin/bash
if ufw status 2>/dev/null | grep -q "Status: active"; then
    exit 0
fi
exit 1

ISE GUI: Create Script Conditions

Step 1: Navigate to Posture Conditions

  1. Navigate to: Work Centers → Posture → Policy Elements → Conditions → Script

  2. Click Add

Step 2: Create ClamAV Running Condition

Field Value

Name

pr_Linux_ClamAV_Running

Description

Checks if ClamAV daemon is running on Linux

Operating System

Linux All

Script Type

Shell

Script

(paste script from above)

Click Submit

Step 3: Create ClamAV Definitions Condition

Field Value

Name

pr_Linux_ClamAV_Definitions

Description

Checks if ClamAV definitions are updated within 7 days

Operating System

Linux All

Script Type

Shell

Script

(paste script from above)

Click Submit

Step 4: Create UFW Active Condition

Field Value

Name

pr_Linux_UFW_Active

Description

Checks if UFW firewall is active

Operating System

Linux All

Script Type

Shell

Script

(paste script from above)

Click Submit

ISE GUI: Create Posture Requirements

Step 1: Navigate to Requirements

  1. Navigate to: Work Centers → Posture → Policy Elements → Requirements

  2. Click Add

Step 2: Create ClamAV Service Requirement

Field Value

Name

Linux_ClamAV_Service

Operating System

Linux All

Compliance Module

4.x or later

Posture Type

AnyConnect

Conditions

pr_Linux_ClamAV_Running

Remediation Actions

Message Text Only

Message

ClamAV service is not running. Please start clamav-daemon.

Click Save

Step 3: Create ClamAV Definitions Requirement

Field Value

Name

Linux_ClamAV_Definitions

Operating System

Linux All

Compliance Module

4.x or later

Posture Type

AnyConnect

Conditions

pr_Linux_ClamAV_Definitions

Remediation Actions

Message Text Only

Message

ClamAV definitions are out of date. Run freshclam to update.

Click Save

Step 4: Create UFW Firewall Requirement

Field Value

Name

Linux_UFW_Firewall

Operating System

Linux All

Compliance Module

4.x or later

Posture Type

AnyConnect

Conditions

pr_Linux_UFW_Active

Remediation Actions

Message Text Only

Message

UFW firewall is not active. Run: sudo ufw enable

Click Save

ISE GUI: Create Posture Policy

Step 1: Navigate to Posture Policy

  1. Navigate to: Work Centers → Posture → Posture Policy

  2. Click Insert new policy (or Edit existing)

Step 2: Create Linux Posture Policy

Field Value

Rule Name

Linux_Posture_Policy

Identity Groups

Any

Operating Systems

Linux All

Compliance Module

4.x or later

Posture Type

AnyConnect

Requirements

Linux_ClamAV_Service, Linux_ClamAV_Definitions, Linux_UFW_Firewall

All requirements must pass for device to be marked Compliant. If ANY requirement fails, device is marked NonCompliant.

Click Save

Integration with Authorization Policy

The posture policy integrates with authorization rules created in Authorization Policy:

Posture Status Authorization Rule Result

Compliant

Linux_Posture_Compliant

Full network access (DACL_SECURE_FULL)

NonCompliant

Linux_Posture_NonCompliant

Quarantine (DACL_QUARANTINE)

Unknown

Linux_Posture_Unknown

Redirect to posture portal for assessment

Posture Flow

  1. Client authenticates via EAP-TLS

  2. ISE assigns Linux_Posture_Unknown profile (posture redirect)

  3. AnyConnect runs posture assessment scripts

  4. ISE receives posture results

  5. CoA (Change of Authorization) triggers re-authorization

  6. Client receives appropriate profile based on compliance

netapi Automation

The netapi ise CLI provides commands to manage network access conditions programmatically.

Load Credentials

dsource d000 dev/network

List Network Access Conditions

# List all network access conditions
netapi ise get-conditions

# List only posture (Session) conditions
netapi ise get-conditions --dict Session

# JSON output for scripting
netapi ise get-conditions --dict Session -f json

Example output:

                    Network Access Conditions (Session)
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━┓
┃ Name                       ┃ Dictionary┃ Attribute     ┃ Operator ┃ Value        ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━┩
│ Compliance_Unknown_Devices │ Session  │ PostureStatus │ equals   │ Unknown      │
│ Non_Compliant_Devices      │ Session  │ PostureStatus │ equals   │ NonCompliant │
│ Compliant_Devices          │ Session  │ PostureStatus │ equals   │ Compliant    │
└────────────────────────────┴──────────┴───────────────┴──────────┴──────────────┘

Create Posture Conditions

# Create condition for compliant endpoints
netapi ise create-posture-condition "Linux_Posture_Compliant" \
    --attr PostureStatus --value Compliant

# Create condition for non-compliant endpoints
netapi ise create-posture-condition "Linux_Posture_NonCompliant" \
    --attr PostureStatus --value NonCompliant

# Create condition for unknown posture status
netapi ise create-posture-condition "Linux_Posture_Unknown" \
    --attr PostureStatus --value Unknown

# Dry run to preview without creating
netapi ise create-posture-condition "Test_Condition" --dry-run

Get Condition Details

netapi ise get-condition "Compliant_Devices"
netapi ise get-condition "Compliant_Devices" -f json

Delete Conditions

# With confirmation prompt
netapi ise delete-condition "Test_Condition"

# Skip confirmation
netapi ise delete-condition "Test_Condition" --force

Discover Available Dictionaries

# List all available dictionaries
netapi ise get-dictionaries

# Get details of Session dictionary (contains PostureStatus)
netapi ise get-dictionary Session

Check Posture Status for Endpoint

# Get session details including posture status
netapi ise mnt session "C8:5B:76:C6:59:62" -f json | \
  jq '{mac: .calling_station_id, posture: .posture_status, profile: .selected_authz_profiles}'

Generic Condition Creation

For conditions using other dictionaries:

# Create RADIUS condition
netapi ise create-condition "Wireless_802.11" \
    --dict "Radius" \
    --attr "NAS-Port-Type" \
    --value "Wireless - IEEE 802.11"

# Create Network Access condition
netapi ise create-condition "EAP_TLS_Auth" \
    --dict "Network Access" \
    --attr "EapAuthentication" \
    --value "EAP-TLS"

Verification

Via ISE GUI

  1. Navigate to: Operations → RADIUS → Live Logs

  2. Find session for Linux device

  3. Check PostureStatus column:

    • Compliant: All requirements passed

    • NonCompliant: One or more requirements failed

    • Unknown: Posture not yet assessed

Via Client

# Check if posture agent received policy
journalctl -u anyconnect-iseposture --since "1 hour ago"

# Manual check of conditions
systemctl is-active clamav-daemon && echo "ClamAV: OK" || echo "ClamAV: FAIL"
ufw status | grep -q "Status: active" && echo "UFW: OK" || echo "UFW: FAIL"

Troubleshooting

Posture Status Stays Unknown

Cause: AnyConnect posture module not running or not receiving policy.

Fix: 1. Verify AnyConnect ISE Posture module installed 2. Check /opt/cisco/anyconnect/iseposture/ exists 3. Verify ISE PSN is reachable on port 8905 4. Check DACL allows traffic to ISE on 8443/8905

Script Condition Fails Unexpectedly

Cause: Script returns non-zero exit code.

Debug:

# Test script manually
/opt/cisco/anyconnect/iseposture/scripts/pr_Linux_ClamAV_Running.sh
echo "Exit code: $?"

CoA Not Triggering

Cause: Switch/WLC not configured for CoA or blocked by firewall.

Fix: 1. Verify NAD has CoA configured (UDP 1700 or 3799) 2. Check ISE can reach NAD for CoA 3. Verify RADIUS accounting is enabled