C3 AI Documentation Home

Using Config Auditing to debug cluster issues

Config Auditing reveals which configs was changed, what changes were made, when the modification occurred, and who made the changes. Auditing provides traceability, accountability, and recoverability.

Config Auditing simplifies:

  • debugging issues caused by configuration changes (cyber forensics)
  • restoring a config that was incorrectly modified or deleted
  • identify users improperly changing configs

Overview

For every Config operation such as setConfig, Config.AuditLog is created and upserted, unless it is explicitly excluded from auditing. Each Config.AuditLog contains fields such as the Config#type, root Action, User#id, etc.

Set up

Enable/Disable auditing

To enable or disable auditing for the entire cluster, run the following as Cluster Admin. To disable for specific apps or configs, see "Excluding certain config operations from auditing"

JavaScript
// enable
Config.AuditLogConfig.inst().enable(); // Sets the path to write auditing data using the current app's default FileSystem

// disable
Config.AuditLogConfig.inst().disable();

Common queries and usages

NOTE: The partition key for the Config.AuditLog table is ConfigType. This means filtering for configType is faster than filtering for other fields, and in fact specifying the configType for each query is currently required. See KvStore.Filesystem.

Config.AuditLog operations are restricted to Cluster Admin only.

  1. Find all changes made to a specific config

    JavaScript
    Config.AuditLog.fetch(Filter.eq('configType', 'myConfigType'));
  2. Find a change to type made by a specific user

    JavaScript
    Config.AuditLog.fetch(Filter.eq('configType', 'myConfigType').and().eq('userId', 'myUserId'));
  3. Find changes across multiple types made by a specific user

    JavaScript
    configTypes = ["configType0", "configType1", "configType2"]
    result = []
    for (let i = 0; i < configTypes.length; i++) {
      result.push.apply(result, Config.AuditLog.fetch(Filter.eq('configType', configTypes[i]).and().eq('userId', 'myUserId')).objs);
    }
    • Note again that the configType is still required because of it is the partition key

Excluding certain config operations from auditing

JavaScript
Config.AuditLogConfig.builder()
     .excludeTypes(["CryptoPrivateKey"]) // excludes all config operations on `CryptoPrivateKey`s
     .excludeAllNonPlatformTypes(false) // excludes all config operations on non-platform types
     .excludeUserIds(["exampleuserid"]) // excludes all config operations by user with ID `exampleuserid`
     .excludeAppIds(["cluster1-env1-app1"]) // excludes all config operations run on the app with ID `cluster1-env1-app1`
     .build().setConfig()
Was this page helpful?