Skip to content

Commit 049a5af

Browse files
shazronJesse MacFadyen
authored andcommitted
feat: ACNA-3271 - publish audit logs (#863)
1 parent 7320997 commit 049a5af

14 files changed

Lines changed: 1227 additions & 662 deletions

File tree

jest.config.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ module.exports = {
2727
global: {
2828
branches: 100,
2929
lines: 100,
30-
statements: 100
30+
statements: 100,
31+
functions: 100
3132
}
3233
}
3334
}

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@
66
"bugs": "https://github.com/adobe/aio-cli-plugin-app/issues",
77
"dependencies": {
88
"@adobe/aio-cli-lib-app-config": "^4.0.3",
9-
"@adobe/aio-cli-lib-console": "^5",
9+
"@adobe/aio-cli-lib-console": "^5.0.3",
1010
"@adobe/aio-lib-core-config": "^5",
1111
"@adobe/aio-lib-core-logging": "^3",
1212
"@adobe/aio-lib-core-networking": "^5",
1313
"@adobe/aio-lib-env": "^3",
1414
"@adobe/aio-lib-ims": "^7",
15-
"@adobe/aio-lib-runtime": "^7.1.0",
15+
"@adobe/aio-lib-runtime": "^7.1.2",
1616
"@adobe/aio-lib-templates": "^3",
1717
"@adobe/aio-lib-web": "^7",
1818
"@adobe/generator-aio-app": "^9",

src/commands/app/config/get/log-forwarding.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,16 @@ governing permissions and limitations under the License.
1111

1212
const BaseCommand = require('../../../../BaseCommand')
1313
const LogForwarding = require('../../../../lib/log-forwarding')
14+
const { setRuntimeApiHostAndAuthHandler } = require('../../../../lib/auth-helper')
1415

1516
class LogForwardingCommand extends BaseCommand {
1617
async run () {
17-
const lf = await LogForwarding.init((await this.getFullConfig()).aio)
18+
let aioConfig = (await this.getFullConfig()).aio
19+
// TODO: remove this check once the deploy service is enabled by default
20+
if (process.env.IS_DEPLOY_SERVICE_ENABLED === 'true') {
21+
aioConfig = setRuntimeApiHostAndAuthHandler(aioConfig)
22+
}
23+
const lf = await LogForwarding.init(aioConfig)
1824

1925
const localConfig = lf.getLocalConfig()
2026
const serverConfig = await lf.getServerConfig()

src/commands/app/config/get/log-forwarding/errors.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ governing permissions and limitations under the License.
1212
const BaseCommand = require('../../../../../BaseCommand')
1313
const rtLib = require('@adobe/aio-lib-runtime')
1414
const ora = require('ora')
15+
const { setRuntimeApiHostAndAuthHandler } = require('../../../../../lib/auth-helper')
1516

1617
class ErrorsCommand extends BaseCommand {
1718
async run () {
@@ -30,7 +31,13 @@ class ErrorsCommand extends BaseCommand {
3031
}
3132

3233
async getLogForwarding () {
33-
const runtimeConfig = (await this.getFullConfig()).aio.runtime
34+
let aioConfig = (await this.getFullConfig()).aio
35+
// TODO: remove this check once the deploy service is enabled by default
36+
if (process.env.IS_DEPLOY_SERVICE_ENABLED === 'true') {
37+
aioConfig = setRuntimeApiHostAndAuthHandler(aioConfig)
38+
}
39+
40+
const runtimeConfig = aioConfig.runtime
3441
rtLib.utils.checkOpenWhiskCredentials({ ow: runtimeConfig })
3542
const rt = await rtLib.init({
3643
...runtimeConfig,

src/commands/app/deploy.js

Lines changed: 47 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ const BaseCommand = require('../../BaseCommand')
1818
const BuildCommand = require('./build')
1919
const webLib = require('@adobe/aio-lib-web')
2020
const { Flags } = require('@oclif/core')
21-
const { runInProcess, buildExtensionPointPayloadWoMetadata, buildExcShellViewExtensionMetadata, getCliInfo } = require('../../lib/app-helper')
21+
const { runInProcess, buildExtensionPointPayloadWoMetadata, buildExcShellViewExtensionMetadata, getCliInfo, getFilesCountWithExtension } = require('../../lib/app-helper')
2222
const rtLib = require('@adobe/aio-lib-runtime')
2323
const LogForwarding = require('../../lib/log-forwarding')
24-
const { sendAuditLogs, getAuditLogEvent, getFilesCountWithExtension } = require('../../lib/audit-logger')
24+
const { sendAppAssetsDeployedAuditLog, sendAppDeployAuditLog } = require('../../lib/audit-logger')
2525
const { setRuntimeApiHostAndAuthHandler } = require('../../lib/auth-helper')
2626
const logActions = require('../../lib/log-actions')
2727

@@ -53,15 +53,43 @@ class Deploy extends BuildCommand {
5353
const spinner = ora()
5454

5555
try {
56-
const aioConfig = (await this.getFullConfig()).aio
56+
const { aio: aioConfig, packagejson: packageJson } = await this.getFullConfig()
5757
const cliDetails = await getCliInfo(flags.publish)
58+
const appInfo = {
59+
name: packageJson.name,
60+
version: packageJson.version,
61+
project: aioConfig?.project,
62+
runtimeNamespace: aioConfig?.runtime?.namespace
63+
}
64+
65+
if (cliDetails?.accessToken) {
66+
try {
67+
// send audit log at start (don't wait for deployment to finish)
68+
await sendAppDeployAuditLog({
69+
accessToken: cliDetails?.accessToken,
70+
cliCommandFlags: flags,
71+
appInfo,
72+
env: cliDetails.env
73+
})
74+
} catch (error) {
75+
if (flags.verbose) {
76+
this.warn('Error: Audit Log Service Error: Failed to send audit log event for deployment.')
77+
this.warn(error.message)
78+
}
79+
}
80+
}
5881

5982
// 1. update log forwarding configuration
6083
// note: it is possible that .aio file does not exist, which means there is no local lg config
6184
if (aioConfig?.project?.workspace && flags['log-forwarding-update'] && flags.actions) {
6285
spinner.start('Updating log forwarding configuration')
6386
try {
64-
const lf = await LogForwarding.init(aioConfig)
87+
let lfConfig = aioConfig
88+
if (process.env.IS_DEPLOY_SERVICE_ENABLED === 'true') {
89+
lfConfig = setRuntimeApiHostAndAuthHandler(aioConfig)
90+
}
91+
92+
const lf = await LogForwarding.init(lfConfig)
6593
if (lf.isLocalConfigChanged()) {
6694
const lfConfig = lf.getLocalConfigWithSecrets()
6795
if (lfConfig.isDefined()) {
@@ -101,22 +129,24 @@ class Deploy extends BuildCommand {
101129
// - break into smaller pieces deploy, allowing to first deploy all actions then all web assets
102130
for (let i = 0; i < keys.length; ++i) {
103131
const k = keys[i]
104-
const v = setRuntimeApiHostAndAuthHandler(values[i])
132+
const v = process.env.IS_DEPLOY_SERVICE_ENABLED === 'true' ? setRuntimeApiHostAndAuthHandler(values[i]) : values[i]
105133

106134
await this.deploySingleConfig(k, v, flags, spinner)
107-
if (v.app.hasFrontend && flags['web-assets']) {
135+
if (cliDetails?.accessToken && v.app.hasFrontend && flags['web-assets']) {
108136
const opItems = getFilesCountWithExtension(v.web.distProd)
109-
const assetDeployedLogEvent = getAuditLogEvent(flags, aioConfig.project, 'AB_APP_ASSETS_DEPLOYED')
110-
if (assetDeployedLogEvent && cliDetails?.accessToken) {
111-
assetDeployedLogEvent.data.opItems = opItems
112-
try {
113-
// only send logs in case of web-assets deployment
114-
await sendAuditLogs(cliDetails.accessToken, assetDeployedLogEvent, cliDetails.env)
115-
} catch (error) {
116-
if (flags.verbose) {
117-
this.warn('Error: Audit Log Service Error: Failed to send audit log event for deployment.')
118-
this.warn(error.message)
119-
}
137+
try {
138+
// only send logs in case of web-assets deployment
139+
await sendAppAssetsDeployedAuditLog({
140+
accessToken: cliDetails?.accessToken,
141+
cliCommandFlags: flags,
142+
opItems,
143+
appInfo,
144+
env: cliDetails.env
145+
})
146+
} catch (error) {
147+
if (flags.verbose) {
148+
this.warn('Error: Audit Log Service Error: Failed to send audit log event for deployment.')
149+
this.warn(error.message)
120150
}
121151
}
122152
}

src/commands/app/undeploy.js

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const BaseCommand = require('../../BaseCommand')
1919
const webLib = require('@adobe/aio-lib-web')
2020
const { runInProcess, buildExtensionPointPayloadWoMetadata, getCliInfo } = require('../../lib/app-helper')
2121
const rtLib = require('@adobe/aio-lib-runtime')
22-
const { sendAuditLogs, getAuditLogEvent } = require('../../lib/audit-logger')
22+
const { sendAppAssetsUndeployedAuditLog, sendAppUndeployAuditLog } = require('../../lib/audit-logger')
2323
const { setRuntimeApiHostAndAuthHandler } = require('../../lib/auth-helper')
2424

2525
class Undeploy extends BaseCommand {
@@ -51,20 +51,47 @@ class Undeploy extends BaseCommand {
5151

5252
const spinner = ora()
5353
try {
54-
const aioConfig = (await this.getFullConfig()).aio
54+
const { aio: aioConfig, packagejson: packageJson } = await this.getFullConfig()
5555
const cliDetails = await getCliInfo(flags.unpublish)
56+
const appInfo = {
57+
name: packageJson.name,
58+
version: packageJson.version,
59+
project: aioConfig?.project,
60+
runtimeNamespace: aioConfig?.runtime?.namespace
61+
}
62+
63+
if (cliDetails?.accessToken) {
64+
try {
65+
// send audit log at start (don't wait for deployment to finish)
66+
await sendAppUndeployAuditLog({
67+
accessToken: cliDetails?.accessToken,
68+
cliCommandFlags: flags,
69+
appInfo,
70+
env: cliDetails.env
71+
})
72+
} catch (error) {
73+
if (flags.verbose) {
74+
this.warn('Error: Audit Log Service Error: Failed to send audit log event for deployment.')
75+
this.warn(error.message)
76+
}
77+
}
78+
}
5679

5780
for (let i = 0; i < keys.length; ++i) {
5881
const k = keys[i]
5982
// TODO: remove this check once the deploy service is enabled by default
6083
const v = process.env.IS_DEPLOY_SERVICE_ENABLED === 'true' ? setRuntimeApiHostAndAuthHandler(values[i]) : values[i]
6184

6285
await this.undeployOneExt(k, v, flags, spinner)
63-
const assetUndeployLogEvent = getAuditLogEvent(flags, aioConfig.project, 'AB_APP_ASSETS_UNDEPLOYED')
64-
// send logs for case of web-assets undeployment
65-
if (assetUndeployLogEvent && cliDetails?.accessToken) {
86+
if (cliDetails?.accessToken) {
87+
// send logs for case of web-assets undeployment
6688
try {
67-
await sendAuditLogs(cliDetails.accessToken, assetUndeployLogEvent, cliDetails.env)
89+
await sendAppAssetsUndeployedAuditLog({
90+
accessToken: cliDetails?.accessToken,
91+
cliCommandFlags: flags,
92+
appInfo,
93+
env: cliDetails.env
94+
})
6895
} catch (error) {
6996
this.warn('Warning: Audit Log Service Error: Failed to send audit log event for un-deployment.')
7097
}

src/lib/app-helper.js

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ governing permissions and limitations under the License.
1111

1212
const execa = require('execa')
1313
const fs = require('fs-extra')
14-
const path = require('path')
14+
const path = require('node:path')
1515
const which = require('which')
1616
const aioLogger = require('@adobe/aio-lib-core-logging')('@adobe/aio-cli-plugin-app:lib-app-helper', { provider: 'debug' })
1717
const { getToken, context } = require('@adobe/aio-lib-ims')
@@ -473,6 +473,67 @@ function getObjectValue (obj, key) {
473473
return keys.filter(o => o.trim()).reduce((o, i) => o && getObjectProp(o, i), obj)
474474
}
475475

476+
/**
477+
* Counts files by extension in a directory
478+
*
479+
* @param {string} directory Path to assets directory
480+
* @returns {Array<string>} Array of formatted log messages
481+
*/
482+
function getFilesCountWithExtension (directory) {
483+
const log = []
484+
485+
if (!fs.existsSync(directory)) {
486+
throw new Error(`Error: Directory ${directory} does not exist.`)
487+
}
488+
489+
const files = fs.readdirSync(directory, { recursive: true })
490+
if (files.length === 0) {
491+
throw new Error(`Error: No files found in directory ${directory}.`)
492+
}
493+
494+
const fileTypeCounts = {}
495+
files.forEach(file => {
496+
const ext = path.extname(file).toLowerCase() || 'no extension'
497+
if (fileTypeCounts[ext]) {
498+
fileTypeCounts[ext]++
499+
} else {
500+
fileTypeCounts[ext] = 1
501+
}
502+
})
503+
504+
Object.keys(fileTypeCounts).forEach(ext => {
505+
const count = fileTypeCounts[ext]
506+
let description
507+
switch (ext) {
508+
case '.js':
509+
description = 'Javascript file(s)'
510+
break
511+
case '.css':
512+
description = 'CSS file(s)'
513+
break
514+
case '.html':
515+
description = 'HTML page(s)'
516+
break
517+
case '.png':
518+
case '.jpg':
519+
case '.jpeg':
520+
case '.gif':
521+
case '.svg':
522+
case '.webp':
523+
description = `${ext} image(s)`
524+
break
525+
case 'no extension':
526+
description = 'file(s) without extension'
527+
break
528+
default:
529+
description = `${ext} file(s)`
530+
}
531+
log.push(`${count} ${description}\n`)
532+
})
533+
534+
return log
535+
}
536+
476537
module.exports = {
477538
getObjectValue,
478539
getObjectProp,
@@ -496,5 +557,6 @@ module.exports = {
496557
buildExtensionPointPayloadWoMetadata,
497558
buildExcShellViewExtensionMetadata,
498559
atLeastOne,
499-
deleteUserConfig
560+
deleteUserConfig,
561+
getFilesCountWithExtension
500562
}

0 commit comments

Comments
 (0)