Demisto Lock
Locking mechanism that prevents concurrent execution of different tasks.
Utilities · Cortex Lock
Details
| ID | Demisto Lock |
|---|---|
| Provider | Palo Alto Networks |
| Category | Utilities |
| From Version | 5.0.0 |
| Supported Modules | Agentix Cortex Cloud Cloud Runtime Security Cloud Posture Security XSIAM EDR |
README
Overview
Demisto Lock is a mechanism that enables users to prevent concurrent execution of tasks. This is a native integration, which does not require configuration.
Commands
You can execute these commands from the Cortex XSOAR CLI, as part of an automation, or in a playbook. After you successfully execute a command, a DBot message appears in the War Room with the command details.
- Get a lock: demisto-lock-get
- Show lock information: demisto-lock-info
- Release a lock: demisto-lock-release
- Release all locks: demisto-lock-release-all
Get a lock
Gets a specific lock. If the lock doesn't exist, it creates one. If the lock is already in use, the command waits until the lock is released or until timeout is reached. If timeout is reached and the lock hasn't been released, the command fails to get the lock.
Base Command
demisto-lock-get
Input
| Parameter | Description |
| name | Lock name. When omitted, the default is Default. |
| info | Additional information about the lock |
| timeout | Timeout to wait for the lock to be released |
Show lock information
Retreives information for a specified lock.
Base Command
demisto-lock-info
Input
| Parameter | Description |
| name | Name of lock to retrieve information for. When omitted, the default is Default. |
Release a lock
Release a specified lock.
Base Command
demisto-lock-release
Input
| Parameter | Description |
| name | Name of lock to release. When omitted, the default is Default. |
Release all locks
Release a specified lock.
Base Command
demisto-lock-release-all
Input
There is no input for this command.
Troubleshooting
If you use multiple locks which might be set in parallel, it is recommended to enable the Sync integration cache (Available from Cortex XSOAR 6.2.0).
Configuration parameters
timeout— Default timeout (seconds) for wait on locks to be released (required)polling_interval— Polling intervalsync— Sync integration cache
Commands (4)
-
demisto-lock-getGets a specific lock. If the lock doesn't exist, it creates one. If the lock is already in use, the command waits until the lock is released or until timeout is reached. If timeout is reached and the lock hasn't been released, the command fails to get the lock.
-
demisto-lock-infoShow information on locks.
-
demisto-lock-releaseRelease a lock.
-
demisto-lock-release-allRelease all locks.
function guid() { function s4() { return Math.floor((1 + Math.random()) * 0x10000) .toString(16) .substring(1); } return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4(); } var sync = params.sync; function setLock(guid, info, version) { if (sync) { mergeVersionedIntegrationContext({newContext : {[lockName] : {guid: guid, info: info}}, version : version}); } else { var integrationContext = getIntegrationContext() || {}; integrationContext[lockName] = {guid: guid, info: info}; setIntegrationContext(integrationContext); } } function getLock() { if (sync) { var versionedIntegrationContext = getVersionedIntegrationContext(true, true) || {}; var integrationContext = versionedIntegrationContext.context; if (!integrationContext[lockName]) { integrationContext[lockName] = {}; } return [integrationContext[lockName], versionedIntegrationContext.version]; } else { var integrationContext = getIntegrationContext() || {}; if (!integrationContext[lockName]) { integrationContext[lockName] = {}; } return [integrationContext[lockName], null]; } } function attemptToAcquireLock(guid, lockInfo, version) { logDebug("Attempting to acquire lock"); try { setLock(guid, lockInfo, version); } catch (err) { logDebug(err.message); } } var lockName = args.name || 'Default'; switch (command) { case 'test-module': return 'ok'; case 'demisto-lock-get': var lockTimeout = args.timeout || params.timeout || 600; var lockInfo = 'Locked by incident #' + incidents[0].id + '.'; lockInfo += (args.info) ? ' Additional info: ' + args.info : ''; var pollingInterval = args.polling_interval || params.polling_interval || '20'; var guid = args.guid || guid(); var time = 0; var lock, lock_candidate, version, versionString; if (isDemistoVersionGE('8.0.0')) { // XSOAR 8 lock implementation with polling. logDebug('Running on XSOAR version 8'); // check if a lock already exists in the integration context [lock, version] = getLock(); versionString = version; if (typeof version === "object") { versionString = JSON.stringify(version); } logDebug('Task guid: ' + guid + ' | Current lock is: ' + JSON.stringify(lock) + ', version: ' + versionString); // if no lock found, try to acquire a new lock if (!lock.guid) { attemptToAcquireLock(guid, lockInfo, version) lock_candidate = getLock(); } // stopping condition - the lock is acquired successfully if (lock_candidate && lock_candidate[0].guid === guid) { var md = '### Demisto Locking Mechanism\n'; md += 'Lock acquired successfully\n'; md += 'GUID: ' + guid; logDebug(md) return { ContentsFormat: formats.markdown, Type: entryTypes.note, Contents: md }; } else { // polling condition - the lock acquire attempt failed (another lock already exist) var timeout_err_msg = 'Timeout waiting for lock\n'; timeout_err_msg += 'Lock name: ' + lockName + '\n'; timeout_err_msg += 'Lock info: ' + lock.info + '\n'; logDebug(timeout_err_msg) return { Type: entryTypes.note, Contents: 'Lock was not acquired, Polling.', PollingCommand: 'demisto-lock-get', NextRun: pollingInterval, PollingArgs: { name: lockName, info: args.info, timeout: args.timeout, polling_interval: pollingInterval ,guid: guid, timeout_err_msg: timeout_err_msg }, Timeout: String(lockTimeout) } } } else { // XSOAR 6 lock implementation without polling. logDebug('Running on XSOAR version 6'); do { [lock, version] = getLock(); if (lock.guid === guid) { break; } if (!lock.guid) { try { setLock(guid, lockInfo, version); } catch (err) { logDebug(err.message) } } wait(1); } while (time++ < lockTimeout); [lock, version] = getLock(); if (lock.guid === guid) { var md = '### Demisto Locking Mechanism\n'; md += 'Lock acquired successfully\n'; md += 'GUID: ' + guid; return { ContentsFormat: formats.markdown, Type: entryTypes.note, Contents: md }; } else { var md = 'Timeout waiting for lock\n'; md += 'Lock name: ' + lockName + '\n'; md += 'Lock info: ' + lock.info + '\n'; return { ContentsFormat: formats.text, Type: entryTypes.error, Contents: md }; } break; } case 'demisto-lock-release': logDebug('Releasing lock lockName: ' + lockName); if(sync) { mergeVersionedIntegrationContext({newContext : {[lockName] : 'remove'}, retries : 5}); } else { integrationContext = getVersionedIntegrationContext(sync); delete integrationContext[lockName]; setVersionedIntegrationContext(integrationContext, sync); } [lock, version] = getLock(); logDebug('Current lock is: ' + JSON.stringify(lock) + ', version: ' + JSON.stringify(version)); var md = '### Demisto Locking Mechanism\n'; md += 'Lock released successfully'; return { ContentsFormat: formats.markdown, Type: entryTypes.note, Contents: md } ; case 'demisto-lock-release-all': setVersionedIntegrationContext({}, sync); var md = '### Demisto Locking Mechanism\n'; md += 'All locks released successfully'; return { ContentsFormat: formats.markdown, Type: entryTypes.note, Contents: md } ; case 'demisto-lock-info': integrationContext = getVersionedIntegrationContext(sync); var obj = []; var res; var md = '### Demisto Locking Mechanism\n'; var locks = (lockName === 'Default') ? Object.keys(integrationContext) : [lockName]; locks.forEach(function(lock){ md += 'Lock name: ' + lock + ' - '; if (integrationContext[lock] && integrationContext[lock].guid) { md += 'Locked.\n'; md += '- GUID: ' + integrationContext[lock].guid + '\n'; md += '- Info: ' + integrationContext[lock].info + '\n\n'; obj.push({lock: lock, state: integrationContext[lock]}); } else { md += 'Not locked\n\n'; } }); return { ContentsFormat: formats.json, Type: entryTypes.note, Contents: obj, HumanReadable: md } ; default: var md = 'Unknown command ' + command; return { ContentsFormat: formats.text, Type: entryTypes.error, Contents: md }; }