Auditing enables Tenant Administrators monitor and review user actions, identify potential security risks, adhere to compliance standards, gain insight into user behavior, and troubleshoot issues. The Tenant Administrator uses the Cisco AppDynamics Query Service API with the Unified Query Language (UQL) to query audit logs. 

Common Audit Use Cases

Tenant Administrators can use auditing to perform the tasks below. The list is far from exhaustive.

  • View audit history for end users for customer support.
  • Generate weekly audit reports for all administrative changes made to management. 
  • Compare end-user behavior over the past six months.
  • Search for all actions performed by end users within the last 24 hours. 
  • Submit annual audit reports of administrators to the Audit team. 
  • Analyze an audit event for troubleshooting. 
  • Provide audit reports to the internal Security team for all users who have logged in via their personal devices.

Requirements

To use auditing, you will need to do the following:

Limitations

The Auditing feature has the following limitations:

  • Tenant-level audit events only (Account-level audit events are unavailable.)
  • Audit events are available only through the Cisco AppDynamics Query Service API. (The UI is unavailable.)
  • Audit events are stored for 30 days. (The retention period is not configurable.)

Query Audit Records

Auditing is available via a REST API that uses a Unified Query Language (UQL), a Cisco AppDynamics domain-specific language used to observe data in Cisco AppDynamics. Some of its features are:

UQL Primer

Unified Query Language (UQL) is a domain-specific and declarative language used to query data. To query data, you append UQL statements to the Cisco AppDynamics Query Service API. The syntax of UQL is similar to SQL in that you form statements in blocks, fetching fields from data sources and adding filters if needed.

Before making audit queries with UQL, let's look at a simple UQL query and brief description:

UQL QueryExplanation

fetch id, attributes("service.name") from entities(apm:service)

  1. fetch block defines MELT or state data to be returned
  2. Return ID of selected entities
  3. Return attribute service.name of selected entities
  4. from block defines the topology context of the query - entities and associations
  5. Get data for entities of type apm:service

Audit Object

You can access audit events through the audit object audit:record.

FETCH events(audit:record)
CODE

Resource Types

The resource types describe the original source of the audit events. For example, the user_principal is a source for a certain subset of the available audit events.

Resource TypeDescription
user_principal

Logged-in users interact with the Cisco Cloud Observability and click UI components that in turn make calls to APIs.

agent_principal

Cisco AppDynamics software (e.g., agents or collectors) is installed in the customer's environment and makes calls to APIs. 

service_principal

Tenant Administrators create Service Principals from the Cisco AppDynamics Accounts Portal and use the Service Principal credentials to make calls to APIs.

tokenThe access token of the principal that authorizes REST calls.
apiThe API that is being called.

Audit Events 

 The following table describes the supported values and what each combination represents:

Valid Resource Type(s)

Event Type

Description

agent_principal, service_principal createdA new agent principal or service principal has been created.
updatedAn agent principal or service principal has been updated.
deletedAn agent principal or service principal has been deleted.
secret_rotatedA client secret for an agent principal or a service principal has been rotated.
secret_revokedThe client secret for an agent principal or a service principal has been revoked.
api authorizedA principal has been successfully authorized to access an API.
unauthorizedA principal's request to access an API was denied.
user_principaltenant_assignedA user is assigned to a tenant.
tenant_removedA user is removed from a tenant
user_principal, service_principalrole_changedThe role of a user or service principal has changed.

Auditing Basics with UQL

You can fetch all of the audit events with this simple query, shown as a query statement and in a call to the Cisco AppDynamics Query Service API:

FETCH events(audit:record){attributes} SINCE -1d
SQL
curl -X POST https://<customer_tenant>.observe.appdynamics.com/monitoring/v1/query/execute \
-H 'Authorization: Bearer {accessToken}' \
-d '{
  "query": "FETCH events(audit:record){attributes} SINCE -1d"
}'
CODE

Example Auditing Queries

You following examples show you how to use UQL and the Cisco AppDynamics Query Service API to query common audit events.

New and Removed Users

The query below returns the audit records for users who were created or removed in the last 10 days.

FETCH events(audit:record)[attributes('audit.record.type') IN ['created', 'deleted']]{attributes} SINCE -10d
CODE
curl -X POST https://<customer_tenant>.observe.appdynamics.com/monitoring/v1/query/execute \
-H 'Authorization: Bearer {accessToken}' \
-d '{
  "query": "FETCH events(audit:record)[attributes('audit.record.type') IN ['created', 'deleted']]{attributes} SINCE -10d"
}'
CODE

Users Added to or Removed from a Tenant

The query below returns the audit records for users who were added or removed from a tenant in the last 10 days.

FETCH events(audit:record)[attributes('audit.record.type') IN ['tenant_assigned', 'tenant_removed']]{attributes} SINCE -10d
CODE
curl -X POST https://<customer_tenant>.observe.appdynamics.com/monitoring/v1/query/execute \
-H 'Authorization: Bearer {accessToken}' \
-d '{
  "query": "FETCH events(audit:record)[attributes('audit.record.type') IN ['tenant_assigned', 'tenant_removed']]{attributes} SINCE -10d"
}'
CODE

Changed Roles

The query below returns the audit records for users who changed roles in the last 30 days.

FETCH events(audit:record)[attributes('audit.record.type') IN ['role_changed']]{attributes} SINCE -30d
CODE
curl -X POST https://<customer_tenant>.observe.appdynamics.com/monitoring/v1/query/execute \
-H 'Authorization: Bearer {accessToken}' \
-d '{
  "query": "FETCH events(audit:record)[attributes('audit.record.type') IN ['role_changed']]{attributes} SINCE -10d"
}'
CODE

View Changes to Agent or Service Principals

This query returns the audit records where agent or service principals that were updated in the last 30 days.

FETCH events(audit:record)[attributes('audit.record.type') IN ['updated'] &&  attributes('audit.record.principal.properties.id') IN ['agent', 'service']]{attributes}  SINCE -30d
CODE
curl -X POST https://<customer_tenant>.observe.appdynamics.com/monitoring/v1/query/execute \
-H 'Authorization: Bearer {accessToken}' \
-d '{
  "query": "FETCH events(audit:record)[attributes('audit.record.type') IN ['updated'] &&  attributes('audit.record.principal.properties.id') IN ['agent', 'service']]{attributes}  SINCE -30d"
}'
SQL

Rejected Access Attempts

This query returns the audit records of rejected access attempts in the last 30 days.

FETCH events(audit:record)[attributes('audit.record.type') IN ['unauthorized', 'login_failed', 'token_denied', 'secret_revoked]]{attributes} SINCE -30d
CODE
curl -X POST https://<customer_tenant>.observe.appdynamics.com/monitoring/v1/query/execute \
-H 'Authorization: Bearer {accessToken}' \
-d '{
  "query": "FETCH events(audit:record)[attributes('audit.record.type') IN ['unauthorized', 'login_failed', 'token_denied', 'secret_revoked]]{attributes} SINCE -30d"
}'
SQL