@j-schreiber/sf-cli-security-audit 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commands/org/scan/user-perms.d.ts +20 -0
- package/lib/commands/org/scan/user-perms.js +88 -0
- package/lib/commands/org/scan/user-perms.js.map +1 -0
- package/lib/libs/conf-init/auditConfig.js +2 -1
- package/lib/libs/conf-init/auditConfig.js.map +1 -1
- package/lib/libs/core/constants.d.ts +1 -0
- package/lib/libs/core/constants.js +4 -0
- package/lib/libs/core/constants.js.map +1 -1
- package/lib/libs/core/file-mgmt/auditConfigFileManager.d.ts +1 -0
- package/lib/libs/core/file-mgmt/auditConfigFileManager.js +49 -4
- package/lib/libs/core/file-mgmt/auditConfigFileManager.js.map +1 -1
- package/lib/libs/core/mdapi/mdapiRetriever.d.ts +2 -0
- package/lib/libs/core/mdapi/mdapiRetriever.js +7 -0
- package/lib/libs/core/mdapi/mdapiRetriever.js.map +1 -1
- package/lib/libs/core/mdapi/metadataRegistryEntry.d.ts +2 -1
- package/lib/libs/core/mdapi/metadataRegistryEntry.js +17 -2
- package/lib/libs/core/mdapi/metadataRegistryEntry.js.map +1 -1
- package/lib/libs/core/mdapi/namedMetadataType.js +7 -2
- package/lib/libs/core/mdapi/namedMetadataType.js.map +1 -1
- package/lib/libs/core/mdapi/singletonMetadataType.js +4 -2
- package/lib/libs/core/mdapi/singletonMetadataType.js.map +1 -1
- package/lib/libs/core/utils.d.ts +2 -0
- package/lib/libs/core/utils.js +6 -0
- package/lib/libs/core/utils.js.map +1 -1
- package/lib/libs/quick-scan/types.d.ts +17 -0
- package/lib/libs/quick-scan/types.js +2 -0
- package/lib/libs/quick-scan/types.js.map +1 -0
- package/lib/libs/quick-scan/userPermissionScanner.d.ts +22 -0
- package/lib/libs/quick-scan/userPermissionScanner.js +75 -0
- package/lib/libs/quick-scan/userPermissionScanner.js.map +1 -0
- package/messages/org.audit.run.md +12 -0
- package/messages/org.scan.user-perms.md +31 -0
- package/oclif.manifest.json +79 -1
- package/package.json +1 -1
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { SfCommand } from '@salesforce/sf-plugins-core';
|
|
2
|
+
import { QuickScanResult } from '../../../libs/quick-scan/types.js';
|
|
3
|
+
import { EntityScanStatus } from '../../../libs/quick-scan/userPermissionScanner.js';
|
|
4
|
+
export type OrgUserPermScanResult = QuickScanResult;
|
|
5
|
+
export default class OrgUserPermScan extends SfCommand<OrgUserPermScanResult> {
|
|
6
|
+
static readonly summary: string;
|
|
7
|
+
static readonly description: string;
|
|
8
|
+
static readonly examples: string[];
|
|
9
|
+
static readonly flags: {
|
|
10
|
+
name: import("@oclif/core/interfaces").OptionFlag<string[], import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
'target-org': import("@oclif/core/interfaces").OptionFlag<import("@salesforce/core").Org, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
'api-version': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
};
|
|
14
|
+
run(): Promise<OrgUserPermScanResult>;
|
|
15
|
+
private reportProgress;
|
|
16
|
+
private print;
|
|
17
|
+
private printSummary;
|
|
18
|
+
private printPermissionResults;
|
|
19
|
+
}
|
|
20
|
+
export declare function isEntityStatus(cls: unknown): cls is EntityScanStatus;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
|
|
2
|
+
import { Messages } from '@salesforce/core';
|
|
3
|
+
import UserPermissionScanner from '../../../libs/quick-scan/userPermissionScanner.js';
|
|
4
|
+
import { capitalize } from '../../../libs/core/utils.js';
|
|
5
|
+
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
|
|
6
|
+
const messages = Messages.loadMessages('@j-schreiber/sf-cli-security-audit', 'org.scan.user-perms');
|
|
7
|
+
export default class OrgUserPermScan extends SfCommand {
|
|
8
|
+
static summary = messages.getMessage('summary');
|
|
9
|
+
static description = messages.getMessage('description');
|
|
10
|
+
static examples = messages.getMessages('examples');
|
|
11
|
+
static flags = {
|
|
12
|
+
name: Flags.string({
|
|
13
|
+
summary: messages.getMessage('flags.name.summary'),
|
|
14
|
+
description: messages.getMessage('flags.name.description'),
|
|
15
|
+
char: 'n',
|
|
16
|
+
multiple: true,
|
|
17
|
+
required: true,
|
|
18
|
+
}),
|
|
19
|
+
'target-org': Flags.requiredOrg({
|
|
20
|
+
summary: messages.getMessage('flags.target-org.summary'),
|
|
21
|
+
char: 'o',
|
|
22
|
+
required: true,
|
|
23
|
+
}),
|
|
24
|
+
'api-version': Flags.orgApiVersion(),
|
|
25
|
+
};
|
|
26
|
+
async run() {
|
|
27
|
+
const { flags } = await this.parse(OrgUserPermScan);
|
|
28
|
+
const scanner = new UserPermissionScanner();
|
|
29
|
+
scanner.on('progress', this.reportProgress);
|
|
30
|
+
const result = await scanner.quickScan({
|
|
31
|
+
targetOrg: flags['target-org'].getConnection(flags['api-version']),
|
|
32
|
+
permissions: flags.name,
|
|
33
|
+
});
|
|
34
|
+
this.print(result);
|
|
35
|
+
return result;
|
|
36
|
+
}
|
|
37
|
+
reportProgress = (event) => {
|
|
38
|
+
if (event.status === 'Pending') {
|
|
39
|
+
this.spinner.start('Scanning');
|
|
40
|
+
}
|
|
41
|
+
const counters = [];
|
|
42
|
+
Object.entries(event).forEach(([propName, entityStatus]) => {
|
|
43
|
+
if (isEntityStatus(entityStatus)) {
|
|
44
|
+
counters.push(`${capitalize(propName)} (${entityStatus.resolved}/${entityStatus.total})`);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
this.spinner.status = counters.join(' | ');
|
|
48
|
+
if (event.status === 'Completed') {
|
|
49
|
+
this.spinner.stop();
|
|
50
|
+
this.logSuccess(messages.getMessage('success.profiles-count', [event.profiles.total]));
|
|
51
|
+
this.logSuccess(messages.getMessage('success.permissionsets-count', [event.permissionSets.total]));
|
|
52
|
+
this.log();
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
print(result) {
|
|
56
|
+
this.printSummary(result);
|
|
57
|
+
Object.entries(result.permissions).forEach(([permName, permResult]) => {
|
|
58
|
+
this.printPermissionResults(permName, permResult);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
printSummary(result) {
|
|
62
|
+
const data = [];
|
|
63
|
+
Object.entries(result.permissions).forEach(([permissionName, permResult]) => {
|
|
64
|
+
data.push({
|
|
65
|
+
permissionName,
|
|
66
|
+
profiles: permResult.profiles.length,
|
|
67
|
+
permissionSets: permResult.permissionSets.length,
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
this.table({ data, title: '=== Summary ===', titleOptions: { bold: true } });
|
|
71
|
+
}
|
|
72
|
+
printPermissionResults(permissionName, result) {
|
|
73
|
+
const data = [];
|
|
74
|
+
result.profiles.forEach((entityName) => {
|
|
75
|
+
data.push({ entityName, type: 'Profile' });
|
|
76
|
+
});
|
|
77
|
+
result.permissionSets.forEach((entityName) => {
|
|
78
|
+
data.push({ entityName, type: 'Permission Set' });
|
|
79
|
+
});
|
|
80
|
+
if (data.length > 0) {
|
|
81
|
+
this.table({ data, title: permissionName, titleOptions: { underline: true } });
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
export function isEntityStatus(cls) {
|
|
86
|
+
return cls.total !== undefined && cls.resolved !== undefined;
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=user-perms.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-perms.js","sourceRoot":"","sources":["../../../../src/commands/org/scan/user-perms.ts"],"names":[],"mappings":"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"}
|
|
@@ -22,7 +22,8 @@ export default class AuditConfig {
|
|
|
22
22
|
conf.policies.Profiles = { content: await initProfiles(targetCon) };
|
|
23
23
|
conf.policies.PermissionSets = { content: await initPermissionSets(targetCon) };
|
|
24
24
|
conf.policies.ConnectedApps = { content: initConnectedApps() };
|
|
25
|
-
|
|
25
|
+
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
|
|
26
|
+
if (opts?.targetDir || opts?.targetDir === '') {
|
|
26
27
|
DefaultFileManager.save(opts.targetDir, conf);
|
|
27
28
|
}
|
|
28
29
|
return conf;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auditConfig.js","sourceRoot":"","sources":["../../../src/libs/conf-init/auditConfig.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,6CAA6C,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAC5F,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAiBzF;;;GAGG;AACH,MAAM,CAAC,OAAO,OAAO,WAAW;IAC9B;;;;;OAKG;IACI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAqB,EAAE,IAAuB;QACrE,MAAM,IAAI,GAAmB,EAAE,eAAe,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;QACnE,IAAI,CAAC,eAAe,CAAC,eAAe,GAAG,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC;QACvG,MAAM,WAAW,GAAG,MAAM,qBAAqB,CAAC,SAAS,CAAC,CAAC;QAC3D,IAAI,WAAW,EAAE,CAAC;YAChB,IAAI,CAAC,eAAe,CAAC,iBAAiB,GAAG,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;QACpE,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,QAAQ,GAAG,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC,SAAS,CAAC,EAAE,CAAC;QACpE,IAAI,CAAC,QAAQ,CAAC,cAAc,GAAG,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC,SAAS,CAAC,EAAE,CAAC;QAChF,IAAI,CAAC,QAAQ,CAAC,aAAa,GAAG,EAAE,OAAO,EAAE,iBAAiB,EAAE,EAAE,CAAC;QAC/D,IAAI,IAAI,EAAE,SAAS,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"auditConfig.js","sourceRoot":"","sources":["../../../src/libs/conf-init/auditConfig.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,6CAA6C,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAC5F,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAiBzF;;;GAGG;AACH,MAAM,CAAC,OAAO,OAAO,WAAW;IAC9B;;;;;OAKG;IACI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAqB,EAAE,IAAuB;QACrE,MAAM,IAAI,GAAmB,EAAE,eAAe,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;QACnE,IAAI,CAAC,eAAe,CAAC,eAAe,GAAG,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC;QACvG,MAAM,WAAW,GAAG,MAAM,qBAAqB,CAAC,SAAS,CAAC,CAAC;QAC3D,IAAI,WAAW,EAAE,CAAC;YAChB,IAAI,CAAC,eAAe,CAAC,iBAAiB,GAAG,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;QACpE,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,QAAQ,GAAG,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC,SAAS,CAAC,EAAE,CAAC;QACpE,IAAI,CAAC,QAAQ,CAAC,cAAc,GAAG,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC,SAAS,CAAC,EAAE,CAAC;QAChF,IAAI,CAAC,QAAQ,CAAC,aAAa,GAAG,EAAE,OAAO,EAAE,iBAAiB,EAAE,EAAE,CAAC;QAC/D,wEAAwE;QACxE,IAAI,IAAI,EAAE,SAAS,IAAI,IAAI,EAAE,SAAS,KAAK,EAAE,EAAE,CAAC;YAC9C,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAChD,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;OAIG;IACI,MAAM,CAAC,IAAI,CAAC,SAAiB;QAClC,OAAO,kBAAkB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAC7C,CAAC;CACF"}
|
|
@@ -3,3 +3,4 @@ export declare const PROFILES_QUERY = "SELECT Profile.Name,Profile.UserType,IsCu
|
|
|
3
3
|
export declare const PERMISSION_SETS_QUERY = "SELECT Name,Label,IsCustom,NamespacePrefix FROM PermissionSet WHERE IsOwnedByProfile = FALSE AND NamespacePrefix = NULL";
|
|
4
4
|
export declare const CONNECTED_APPS_QUERY = "SELECT Name,OptionsAllowAdminApprovedUsersOnly FROM ConnectedApplication";
|
|
5
5
|
export declare const OAUTH_TOKEN_QUERY = "SELECT User.Username,UseCount,AppName FROM OauthToken";
|
|
6
|
+
export declare const RETRIEVE_CACHE: string;
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
// QUERIES
|
|
1
3
|
export const CUSTOM_PERMS_QUERY = 'SELECT Id,MasterLabel,DeveloperName FROM CustomPermission';
|
|
2
4
|
export const PROFILES_QUERY = 'SELECT Profile.Name,Profile.UserType,IsCustom FROM PermissionSet WHERE IsOwnedByProfile = TRUE';
|
|
3
5
|
export const PERMISSION_SETS_QUERY = 'SELECT Name,Label,IsCustom,NamespacePrefix FROM PermissionSet WHERE IsOwnedByProfile = FALSE AND NamespacePrefix = NULL';
|
|
4
6
|
export const CONNECTED_APPS_QUERY = 'SELECT Name,OptionsAllowAdminApprovedUsersOnly FROM ConnectedApplication';
|
|
5
7
|
export const OAUTH_TOKEN_QUERY = 'SELECT User.Username,UseCount,AppName FROM OauthToken';
|
|
8
|
+
// PATHS
|
|
9
|
+
export const RETRIEVE_CACHE = path.join('.jsc', 'retrieves');
|
|
6
10
|
//# sourceMappingURL=constants.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/libs/core/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,kBAAkB,GAAG,2DAA2D,CAAC;AAC9F,MAAM,CAAC,MAAM,cAAc,GACzB,gGAAgG,CAAC;AACnG,MAAM,CAAC,MAAM,qBAAqB,GAChC,yHAAyH,CAAC;AAC5H,MAAM,CAAC,MAAM,oBAAoB,GAAG,0EAA0E,CAAC;AAC/G,MAAM,CAAC,MAAM,iBAAiB,GAAG,uDAAuD,CAAC"}
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/libs/core/constants.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,UAAU;AACV,MAAM,CAAC,MAAM,kBAAkB,GAAG,2DAA2D,CAAC;AAC9F,MAAM,CAAC,MAAM,cAAc,GACzB,gGAAgG,CAAC;AACnG,MAAM,CAAC,MAAM,qBAAqB,GAChC,yHAAyH,CAAC;AAC5H,MAAM,CAAC,MAAM,oBAAoB,GAAG,0EAA0E,CAAC;AAC/G,MAAM,CAAC,MAAM,iBAAiB,GAAG,uDAAuD,CAAC;AAEzF,QAAQ;AACR,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC"}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import fs from 'node:fs';
|
|
3
3
|
import yaml from 'js-yaml';
|
|
4
|
-
import {
|
|
4
|
+
import { Messages } from '@salesforce/core';
|
|
5
|
+
import { capitalize, isEmpty, uncapitalize } from '../utils.js';
|
|
5
6
|
import { PermissionsConfigFileSchema, PermSetsPolicyFileSchema, PolicyFileSchema, ProfilesPolicyFileSchema, } from './schema.js';
|
|
7
|
+
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
|
|
8
|
+
const messages = Messages.loadMessages('@j-schreiber/sf-cli-security-audit', 'org.audit.run');
|
|
6
9
|
/**
|
|
7
10
|
* Loads an audit run config with the default file manager
|
|
8
11
|
*
|
|
@@ -32,9 +35,15 @@ export default class AuditConfigFileManager {
|
|
|
32
35
|
policies: {
|
|
33
36
|
profiles: {
|
|
34
37
|
schema: ProfilesPolicyFileSchema,
|
|
38
|
+
dependencies: [
|
|
39
|
+
{ path: ['classifications', 'userPermissions'], errorName: 'UserPermClassificationRequiredForProfiles' },
|
|
40
|
+
],
|
|
35
41
|
},
|
|
36
42
|
permissionSets: {
|
|
37
43
|
schema: PermSetsPolicyFileSchema,
|
|
44
|
+
dependencies: [
|
|
45
|
+
{ path: ['classifications', 'userPermissions'], errorName: 'UserPermClassificationRequiredForPermSets' },
|
|
46
|
+
],
|
|
38
47
|
},
|
|
39
48
|
connectedApps: {
|
|
40
49
|
schema: PolicyFileSchema,
|
|
@@ -60,7 +69,10 @@ export default class AuditConfigFileManager {
|
|
|
60
69
|
parse(dirPath) {
|
|
61
70
|
const classifications = this.parseSubdir(dirPath, 'classifications');
|
|
62
71
|
const policies = capitalizeKeys(this.parseSubdir(dirPath, 'policies'));
|
|
63
|
-
|
|
72
|
+
const conf = { classifications, policies };
|
|
73
|
+
assertIsMinimalConfig(conf, dirPath);
|
|
74
|
+
this.validateDependencies(conf);
|
|
75
|
+
return conf;
|
|
64
76
|
}
|
|
65
77
|
/**
|
|
66
78
|
* Writes a full audit config to disk. If the config was not
|
|
@@ -94,7 +106,7 @@ export default class AuditConfigFileManager {
|
|
|
94
106
|
return;
|
|
95
107
|
}
|
|
96
108
|
Object.entries(configFiles).forEach(([fileKey, confFile]) => {
|
|
97
|
-
const uncapitalizedKey =
|
|
109
|
+
const uncapitalizedKey = uncapitalize(fileKey);
|
|
98
110
|
const fileDef = dirConf[uncapitalizedKey];
|
|
99
111
|
if (fileDef && !isEmpty(confFile.content)) {
|
|
100
112
|
// eslint-disable-next-line no-param-reassign
|
|
@@ -103,11 +115,44 @@ export default class AuditConfigFileManager {
|
|
|
103
115
|
}
|
|
104
116
|
});
|
|
105
117
|
}
|
|
118
|
+
validateDependencies(conf) {
|
|
119
|
+
Object.keys(conf.policies).forEach((policyName) => {
|
|
120
|
+
const policyDef = this.directoryStructure.policies[uncapitalize(policyName)];
|
|
121
|
+
if (policyDef?.dependencies) {
|
|
122
|
+
policyDef.dependencies.forEach((dependency) => {
|
|
123
|
+
if (!dependencyExists(dependency.path, conf)) {
|
|
124
|
+
throw messages.createError(dependency.errorName);
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
}
|
|
106
130
|
}
|
|
107
131
|
function capitalizeKeys(object) {
|
|
108
132
|
const newObj = {};
|
|
109
|
-
Object.keys(object).forEach((key) => (newObj[
|
|
133
|
+
Object.keys(object).forEach((key) => (newObj[capitalize(key)] = object[key]));
|
|
110
134
|
return newObj;
|
|
111
135
|
}
|
|
136
|
+
function dependencyExists(fullPath, rootNode) {
|
|
137
|
+
const dep = traverseDependencyPath(fullPath, rootNode);
|
|
138
|
+
return Boolean(dep);
|
|
139
|
+
}
|
|
140
|
+
function traverseDependencyPath(remainingPath, rootNode) {
|
|
141
|
+
if (remainingPath.length >= 2) {
|
|
142
|
+
return traverseDependencyPath(remainingPath.slice(1), rootNode[remainingPath[0]]);
|
|
143
|
+
}
|
|
144
|
+
else if (remainingPath.length === 0) {
|
|
145
|
+
return undefined;
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
return rootNode[remainingPath[0]];
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
function assertIsMinimalConfig(conf, dirPath) {
|
|
152
|
+
if (Object.keys(conf.policies).length === 0) {
|
|
153
|
+
const formattedDirPath = !dirPath || dirPath.length === 0 ? '<root-dir>' : dirPath;
|
|
154
|
+
throw messages.createError('NoAuditConfigFound', [formattedDirPath]);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
112
157
|
export const DefaultFileManager = new AuditConfigFileManager();
|
|
113
158
|
//# sourceMappingURL=auditConfigFileManager.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auditConfigFileManager.js","sourceRoot":"","sources":["../../../../src/libs/core/file-mgmt/auditConfigFileManager.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,SAAS,CAAC;AAE3B,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"auditConfigFileManager.js","sourceRoot":"","sources":["../../../../src/libs/core/file-mgmt/auditConfigFileManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,8 +5,10 @@ import SingletonMetadata from './singletonMetadataType.js';
|
|
|
5
5
|
import NamedMetadataQueryable from './namedMetadataToolingQueryable.js';
|
|
6
6
|
export default class MDAPI {
|
|
7
7
|
private connection;
|
|
8
|
+
private static retrievers;
|
|
8
9
|
private cache;
|
|
9
10
|
constructor(connection: Connection);
|
|
11
|
+
static create(connection: Connection): MDAPI;
|
|
10
12
|
/**
|
|
11
13
|
* Resolves one of the pre-configured metadata types and returns
|
|
12
14
|
* a map of resolved names and entire XML content of source file body.
|
|
@@ -4,11 +4,18 @@ import SingletonMetadata from './singletonMetadataType.js';
|
|
|
4
4
|
import NamedMetadataQueryable from './namedMetadataToolingQueryable.js';
|
|
5
5
|
export default class MDAPI {
|
|
6
6
|
connection;
|
|
7
|
+
static retrievers = new Map();
|
|
7
8
|
cache;
|
|
8
9
|
constructor(connection) {
|
|
9
10
|
this.connection = connection;
|
|
10
11
|
this.cache = new MetadataCache();
|
|
11
12
|
}
|
|
13
|
+
static create(connection) {
|
|
14
|
+
if (!this.retrievers.has(connection.instanceUrl)) {
|
|
15
|
+
this.retrievers.set(connection.instanceUrl, new MDAPI(connection));
|
|
16
|
+
}
|
|
17
|
+
return this.retrievers.get(connection.instanceUrl);
|
|
18
|
+
}
|
|
12
19
|
/**
|
|
13
20
|
* Resolves one of the pre-configured metadata types and returns
|
|
14
21
|
* a map of resolved names and entire XML content of source file body.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mdapiRetriever.js","sourceRoot":"","sources":["../../../../src/libs/core/mdapi/mdapiRetriever.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAO5C,OAAO,aAAa,MAAM,wBAAwB,CAAC;AACnD,OAAO,iBAAiB,MAAM,4BAA4B,CAAC;AAC3D,OAAO,sBAAsB,MAAM,oCAAoC,CAAC;AAExE,MAAM,CAAC,OAAO,OAAO,KAAK;
|
|
1
|
+
{"version":3,"file":"mdapiRetriever.js","sourceRoot":"","sources":["../../../../src/libs/core/mdapi/mdapiRetriever.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAO5C,OAAO,aAAa,MAAM,wBAAwB,CAAC;AACnD,OAAO,iBAAiB,MAAM,4BAA4B,CAAC;AAC3D,OAAO,sBAAsB,MAAM,oCAAoC,CAAC;AAExE,MAAM,CAAC,OAAO,OAAO,KAAK;IAIG;IAHnB,MAAM,CAAC,UAAU,GAAG,IAAI,GAAG,EAAiB,CAAC;IAC7C,KAAK,CAAgB;IAE7B,YAA2B,UAAsB;QAAtB,eAAU,GAAV,UAAU,CAAY;QAC/C,IAAI,CAAC,KAAK,GAAG,IAAI,aAAa,EAAE,CAAC;IACnC,CAAC;IAEM,MAAM,CAAC,MAAM,CAAC,UAAsB;QACzC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YACjD,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,WAAW,EAAE,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC;QACrE,CAAC;QACD,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,WAAW,CAAE,CAAC;IACtD,CAAC;IAED;;;;;;;OAOG;IACI,KAAK,CAAC,OAAO,CAClB,QAAW,EACX,cAAwB;QAExB,MAAM,SAAS,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;QAC/C,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC;QAChE,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,MAAM,eAAe,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;YAC7E,IAAI,CAAC,YAAY,CAAC,eAAe,CAAC,CAAC;YACnC,OAAO;gBACL,GAAG,MAAM;gBACT,GAAG,eAAe;aACI,CAAC;QAC3B,CAAC;QACD,OAAO,MAA6B,CAAC;IACvC,CAAC;IAED;;;;;;OAMG;IACI,KAAK,CAAC,gBAAgB,CAC3B,QAAW;QAEX,MAAM,SAAS,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QAC9C,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC5D,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,MAAM,eAAe,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACjE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;YAC1C,OAAO,eAA0C,CAAC;QACpD,CAAC;QACD,OAAO,MAAM,CAAC,QAAQ,CAA4B,CAAC;IACrD,CAAC;IAEO,YAAY,CAAC,OAAiC;QACpD,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE;YACjD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAC/B,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,WAAW,CAAC,cAAwB;QAC1C,MAAM,UAAU,GAAG,EAAE,CAAC;QACtB,MAAM,MAAM,GAA6B,EAAE,CAAC;QAC5C,KAAK,MAAM,KAAK,IAAI,cAAc,EAAE,CAAC;YACnC,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC/B,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC1C,CAAC;iBAAM,CAAC;gBACN,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;QACD,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;IAChC,CAAC;;AAGH,MAAM,aAAa;IACT,UAAU,GAA6B,EAAE,CAAC;IAE3C,QAAQ,CAAC,OAAe;QAC7B,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,SAAS,IAAI,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;IACrF,CAAC;IAEM,KAAK,CAAC,OAAe;QAC1B,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,qDAAqD,GAAG,OAAO,CAAC,CAAC;QACnF,CAAC;QACD,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IAClC,CAAC;IAEM,GAAG,CAAC,OAAe,EAAE,OAAiB;QAC3C,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IACrC,CAAC;CACF;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,aAAa,EAAE,IAAI,aAAa,CAAoC;QAClE,YAAY,EAAE,eAAe;QAC7B,YAAY,EAAE,eAAe;QAC7B,MAAM,EAAE,IAAI,SAAS,CAAC;YACpB,OAAO,EAAE,CAAC,KAAK,EAAW,EAAE,CAC1B,CAAC,iBAAiB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,eAAe,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;SAChG,CAAC;QACF,kBAAkB,EAAE,CAAC,WAAW,EAAiB,EAAE,CAAC,CAAC;YACnD,GAAG,WAAW;YACd,eAAe,EAAE,WAAW,CAAC,eAAe,IAAI,EAAE;YAClD,iBAAiB,EAAE,WAAW,CAAC,iBAAiB,IAAI,EAAE;YACtD,aAAa,EAAE,WAAW,CAAC,aAAa,IAAI,EAAE;SAC/C,CAAC;KACH,CAAC;IACF,OAAO,EAAE,IAAI,sBAAsB,CAAwB;QACzD,UAAU,EAAE,SAAS;QACrB,SAAS,EAAE,MAAM;QACjB,kBAAkB,EAAE,CAAC,WAAW,EAAmB,EAAE,CAAC,CAAC;YACrD,GAAG,WAAW;YACd,eAAe,EAAE,WAAW,CAAC,eAAe,IAAI,EAAE;YAClD,iBAAiB,EAAE,WAAW,CAAC,iBAAiB,IAAI,EAAE;YACtD,aAAa,EAAE,WAAW,CAAC,aAAa,IAAI,EAAE;SAC/C,CAAC;KACH,CAAC;CACH,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,oBAAoB,EAAE,IAAI,iBAAiB,CAAkD;QAC3F,YAAY,EAAE,sBAAsB;QACpC,YAAY,EAAE,cAAc;QAC5B,YAAY,EAAE,UAAU;KACzB,CAAC;CACH,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { PathLike } from 'node:fs';
|
|
2
2
|
import { XMLParser } from 'fast-xml-parser';
|
|
3
|
-
import { ComponentSet, RetrieveResult } from '@salesforce/source-deploy-retrieve';
|
|
3
|
+
import { ComponentSet, FileResponse, RetrieveResult } from '@salesforce/source-deploy-retrieve';
|
|
4
4
|
import { Connection } from '@salesforce/core';
|
|
5
5
|
export type MetadataRegistryEntryOpts<Type, Key extends keyof Type> = {
|
|
6
6
|
/**
|
|
@@ -37,3 +37,4 @@ export default abstract class MetadataRegistryEntry<Type, Key extends keyof Type
|
|
|
37
37
|
parse(fullFilePath: PathLike): Type[Key];
|
|
38
38
|
}
|
|
39
39
|
export declare function retrieve(compSet: ComponentSet, con: Connection): Promise<RetrieveResult>;
|
|
40
|
+
export declare function cleanRetrieveDir(files: FileResponse[]): void;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { readFileSync } from 'node:fs';
|
|
1
|
+
import { readFileSync, rmSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
2
3
|
import { XMLParser } from 'fast-xml-parser';
|
|
4
|
+
import { RETRIEVE_CACHE } from '../constants.js';
|
|
3
5
|
export default class MetadataRegistryEntry {
|
|
4
6
|
opts;
|
|
5
7
|
parser;
|
|
@@ -23,9 +25,22 @@ export default class MetadataRegistryEntry {
|
|
|
23
25
|
export async function retrieve(compSet, con) {
|
|
24
26
|
const retrieveRequest = await compSet.retrieve({
|
|
25
27
|
usernameOrConnection: con,
|
|
26
|
-
output:
|
|
28
|
+
output: RETRIEVE_CACHE,
|
|
27
29
|
});
|
|
28
30
|
const retrieveResult = await retrieveRequest.pollStatus();
|
|
29
31
|
return retrieveResult;
|
|
30
32
|
}
|
|
33
|
+
export function cleanRetrieveDir(files) {
|
|
34
|
+
const dirNames = new Set();
|
|
35
|
+
files.forEach((file) => {
|
|
36
|
+
if (file.filePath) {
|
|
37
|
+
const dirName = path.dirname(path.normalize(file.filePath));
|
|
38
|
+
const parts = dirName.split(path.sep).filter((dirPart) => dirPart.startsWith('metadataPackage_'));
|
|
39
|
+
parts.forEach((mdPart) => dirNames.add(mdPart));
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
dirNames.forEach((dir) => {
|
|
43
|
+
rmSync(path.join(RETRIEVE_CACHE, dir), { recursive: true });
|
|
44
|
+
});
|
|
45
|
+
}
|
|
31
46
|
//# sourceMappingURL=metadataRegistryEntry.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadataRegistryEntry.js","sourceRoot":"","sources":["../../../../src/libs/core/mdapi/metadataRegistryEntry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,YAAY,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"metadataRegistryEntry.js","sourceRoot":"","sources":["../../../../src/libs/core/mdapi/metadataRegistryEntry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,YAAY,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACzD,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AA8BjD,MAAM,CAAC,OAAO,OAAgB,qBAAqB;IAKtB;IAJpB,MAAM,CAAY;IAClB,YAAY,CAAS;IACrB,YAAY,CAAM;IAEzB,YAA2B,IAA0C;QAA1C,SAAI,GAAJ,IAAI,CAAsC;QACnE,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC;QAC3C,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAClD,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC;IAC7C,CAAC;IAEM,KAAK,CAAC,YAAsB;QACjC,MAAM,WAAW,GAAG,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QACxD,MAAM,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAS,CAAC;QAC7D,IAAI,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC;YACjC,OAAO,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;QACxE,CAAC;QACD,OAAO,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC1C,CAAC;CACF;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,OAAqB,EAAE,GAAe;IACnE,MAAM,eAAe,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC;QAC7C,oBAAoB,EAAE,GAAG;QACzB,MAAM,EAAE,cAAc;KACvB,CAAC,CAAC;IACH,MAAM,cAAc,GAAG,MAAM,eAAe,CAAC,UAAU,EAAE,CAAC;IAC1D,OAAO,cAAc,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAqB;IACpD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;IACnC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QACrB,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;YAC5D,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,kBAAkB,CAAC,CAAC,CAAC;YAClG,KAAK,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;QAClD,CAAC;IACH,CAAC,CAAC,CAAC;IACH,QAAQ,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;QACvB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,GAAG,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ComponentSet } from '@salesforce/source-deploy-retrieve';
|
|
2
|
-
import MetadataRegistryEntry, { retrieve } from './metadataRegistryEntry.js';
|
|
2
|
+
import MetadataRegistryEntry, { cleanRetrieveDir, retrieve, } from './metadataRegistryEntry.js';
|
|
3
3
|
/**
|
|
4
4
|
* The entry is a typical named metadata that is organized in a dedicated source folder
|
|
5
5
|
* where all entities have the same format. The components are retrieved and organized
|
|
@@ -20,13 +20,18 @@ export default class NamedMetadata extends MetadataRegistryEntry {
|
|
|
20
20
|
async resolve(con, componentNames) {
|
|
21
21
|
const cmpSet = new ComponentSet(componentNames.map((cname) => ({ type: this.retrieveType, fullName: cname })));
|
|
22
22
|
const retrieveResult = await retrieve(cmpSet, con);
|
|
23
|
-
|
|
23
|
+
const resolvedFiles = this.parseSourceFiles(retrieveResult.components, componentNames);
|
|
24
|
+
cleanRetrieveDir(retrieveResult.getFileResponses());
|
|
25
|
+
return resolvedFiles;
|
|
24
26
|
}
|
|
25
27
|
parseSourceFiles(componentSet, retrievedNames) {
|
|
26
28
|
const cmps = componentSet.getSourceComponents().toArray();
|
|
27
29
|
const result = {};
|
|
28
30
|
cmps.forEach((sourceComponent) => {
|
|
29
31
|
if (sourceComponent.xml && retrievedNames.includes(sourceComponent.name)) {
|
|
32
|
+
// the available method parseXmlSync on source component does not
|
|
33
|
+
// resolve the "rootNodeProblem" from XML. Therefore, we implement
|
|
34
|
+
// our own method to parse and return the "inner xml".
|
|
30
35
|
result[sourceComponent.name] = this.parse(sourceComponent.xml);
|
|
31
36
|
}
|
|
32
37
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"namedMetadataType.js","sourceRoot":"","sources":["../../../../src/libs/core/mdapi/namedMetadataType.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,qBAAqB,EAAE,
|
|
1
|
+
{"version":3,"file":"namedMetadataType.js","sourceRoot":"","sources":["../../../../src/libs/core/mdapi/namedMetadataType.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,qBAAqB,EAAE,EAC5B,gBAAgB,EAEhB,QAAQ,GACT,MAAM,4BAA4B,CAAC;AAEpC;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,aAA4C,SAAQ,qBAAgC;IACvG,YAAmB,IAA0C;QAC3D,KAAK,CAAC,IAAI,CAAC,CAAC;IACd,CAAC;IACD;;;;;;;OAOG;IACI,KAAK,CAAC,OAAO,CAAC,GAAe,EAAE,cAAwB;QAC5D,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;QAC/G,MAAM,cAAc,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QACnD,MAAM,aAAa,GAAG,IAAI,CAAC,gBAAgB,CAAC,cAAc,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;QACvF,gBAAgB,CAAC,cAAc,CAAC,gBAAgB,EAAE,CAAC,CAAC;QACpD,OAAO,aAAa,CAAC;IACvB,CAAC;IAEO,gBAAgB,CAAC,YAA0B,EAAE,cAAwB;QAC3E,MAAM,IAAI,GAAG,YAAY,CAAC,mBAAmB,EAAE,CAAC,OAAO,EAAE,CAAC;QAC1D,MAAM,MAAM,GAA8B,EAAE,CAAC;QAC7C,IAAI,CAAC,OAAO,CAAC,CAAC,eAAe,EAAE,EAAE;YAC/B,IAAI,eAAe,CAAC,GAAG,IAAI,cAAc,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;gBACzE,iEAAiE;gBACjE,kEAAkE;gBAClE,sDAAsD;gBACtD,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;YACjE,CAAC;QACH,CAAC,CAAC,CAAC;QACH,OAAO,MAAM,CAAC;IAChB,CAAC;CACF"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ComponentSet } from '@salesforce/source-deploy-retrieve';
|
|
2
|
-
import MetadataRegistryEntry, { retrieve } from './metadataRegistryEntry.js';
|
|
2
|
+
import MetadataRegistryEntry, { cleanRetrieveDir, retrieve, } from './metadataRegistryEntry.js';
|
|
3
3
|
/**
|
|
4
4
|
* The entry is a type that only has one single instance on the org, such as
|
|
5
5
|
* a Setting. The component is typically retrieved by a more generic name and
|
|
@@ -22,7 +22,9 @@ export default class SingletonMetadata extends MetadataRegistryEntry {
|
|
|
22
22
|
async resolve(con) {
|
|
23
23
|
const cmpSet = new ComponentSet([{ type: this.retrieveType, fullName: this.retrieveName }]);
|
|
24
24
|
const retrieveResult = await retrieve(cmpSet, con);
|
|
25
|
-
|
|
25
|
+
const resolvedCmp = this.parseSourceFile(retrieveResult.components);
|
|
26
|
+
cleanRetrieveDir(retrieveResult.getFileResponses());
|
|
27
|
+
return resolvedCmp;
|
|
26
28
|
}
|
|
27
29
|
parseSourceFile(componentSet) {
|
|
28
30
|
const cmps = componentSet.getSourceComponents({ type: this.retrieveType, fullName: this.retrieveName }).toArray();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"singletonMetadataType.js","sourceRoot":"","sources":["../../../../src/libs/core/mdapi/singletonMetadataType.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,qBAAqB,EAAE,
|
|
1
|
+
{"version":3,"file":"singletonMetadataType.js","sourceRoot":"","sources":["../../../../src/libs/core/mdapi/singletonMetadataType.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,qBAAqB,EAAE,EAC5B,gBAAgB,EAEhB,QAAQ,GACT,MAAM,4BAA4B,CAAC;AAEpC;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,iBAAgD,SAAQ,qBAAgC;IACpG,YAAY,CAAS;IAC5B,YAAmB,IAA0C;QAC3D,KAAK,CAAC,IAAI,CAAC,CAAC;QACZ,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,IAAI,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACrE,CAAC;IAED;;;;;;;OAOG;IACI,KAAK,CAAC,OAAO,CAAC,GAAe;QAClC,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC;QAC5F,MAAM,cAAc,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QACnD,MAAM,WAAW,GAAG,IAAI,CAAC,eAAe,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;QACpE,gBAAgB,CAAC,cAAc,CAAC,gBAAgB,EAAE,CAAC,CAAC;QACpD,OAAO,WAAW,CAAC;IACrB,CAAC;IAEO,eAAe,CAAC,YAA0B;QAChD,MAAM,IAAI,GAAG,YAAY,CAAC,mBAAmB,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;QAClH,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;YACnC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACjC,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,kCAAkC,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC;IAC1E,CAAC;CACF"}
|
package/lib/libs/core/utils.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export declare function isEmpty(anything?: unknown): boolean;
|
|
2
2
|
export declare function isNullish(anything: unknown): boolean;
|
|
3
|
+
export declare function capitalize(anyString: string): string;
|
|
4
|
+
export declare function uncapitalize(anyString: string): string;
|
|
3
5
|
export type Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>;
|
package/lib/libs/core/utils.js
CHANGED
|
@@ -10,4 +10,10 @@ export function isEmpty(anything) {
|
|
|
10
10
|
export function isNullish(anything) {
|
|
11
11
|
return !(Boolean(anything) && anything !== null);
|
|
12
12
|
}
|
|
13
|
+
export function capitalize(anyString) {
|
|
14
|
+
return `${anyString[0].toUpperCase()}${anyString.slice(1)}`;
|
|
15
|
+
}
|
|
16
|
+
export function uncapitalize(anyString) {
|
|
17
|
+
return `${anyString[0].toLowerCase()}${anyString.slice(1)}`;
|
|
18
|
+
}
|
|
13
19
|
//# sourceMappingURL=utils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/libs/core/utils.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,OAAO,CAAC,QAAkB;IACxC,IAAI,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACjC,OAAO,MAAM,CAAC,OAAO,CAAC,QAAS,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;IAChD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,QAAiB;IACzC,OAAO,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,QAAQ,KAAK,IAAI,CAAC,CAAC;AACnD,CAAC"}
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/libs/core/utils.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,OAAO,CAAC,QAAkB;IACxC,IAAI,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACjC,OAAO,MAAM,CAAC,OAAO,CAAC,QAAS,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;IAChD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,QAAiB;IACzC,OAAO,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,QAAQ,KAAK,IAAI,CAAC,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,SAAiB;IAC1C,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AAC9D,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,SAAiB;IAC5C,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AAC9D,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Connection } from '@salesforce/core';
|
|
2
|
+
export type QuickScanResult = {
|
|
3
|
+
permissions: QuickScanPermissionResult;
|
|
4
|
+
scannedProfiles: string[];
|
|
5
|
+
scannedPermissionSets: string[];
|
|
6
|
+
};
|
|
7
|
+
export type QuickScanPermissionResult = {
|
|
8
|
+
[permissionName: string]: PermissionScanResult;
|
|
9
|
+
};
|
|
10
|
+
export type PermissionScanResult = {
|
|
11
|
+
profiles: string[];
|
|
12
|
+
permissionSets: string[];
|
|
13
|
+
};
|
|
14
|
+
export type QuickScanOptions = {
|
|
15
|
+
targetOrg: Connection;
|
|
16
|
+
permissions: string[];
|
|
17
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/libs/quick-scan/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import { QuickScanOptions, QuickScanResult } from './types.js';
|
|
3
|
+
export type ScanStatusEvent = {
|
|
4
|
+
profiles: EntityScanStatus;
|
|
5
|
+
permissionSets: EntityScanStatus;
|
|
6
|
+
users: EntityScanStatus;
|
|
7
|
+
status: 'Pending' | 'In Progress' | 'Completed';
|
|
8
|
+
};
|
|
9
|
+
export type EntityScanStatus = {
|
|
10
|
+
total?: number;
|
|
11
|
+
resolved?: number;
|
|
12
|
+
status?: string;
|
|
13
|
+
};
|
|
14
|
+
export default class UserPermissionScanner extends EventEmitter {
|
|
15
|
+
private status;
|
|
16
|
+
constructor();
|
|
17
|
+
quickScan(opts: QuickScanOptions): Promise<QuickScanResult>;
|
|
18
|
+
private resolveEntities;
|
|
19
|
+
private resolveProfiles;
|
|
20
|
+
private resolvePermissionSets;
|
|
21
|
+
private emitProgress;
|
|
22
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import MDAPI from '../core/mdapi/mdapiRetriever.js';
|
|
3
|
+
import { PERMISSION_SETS_QUERY, PROFILES_QUERY } from '../core/constants.js';
|
|
4
|
+
export default class UserPermissionScanner extends EventEmitter {
|
|
5
|
+
status = {
|
|
6
|
+
profiles: {},
|
|
7
|
+
permissionSets: {},
|
|
8
|
+
users: {},
|
|
9
|
+
status: 'Pending',
|
|
10
|
+
};
|
|
11
|
+
constructor() {
|
|
12
|
+
super();
|
|
13
|
+
}
|
|
14
|
+
async quickScan(opts) {
|
|
15
|
+
this.emitProgress({ status: 'Pending' });
|
|
16
|
+
const scannedEntities = await this.resolveEntities(opts.targetOrg);
|
|
17
|
+
const scanResult = {
|
|
18
|
+
permissions: {},
|
|
19
|
+
scannedProfiles: Object.keys(scannedEntities.profiles),
|
|
20
|
+
scannedPermissionSets: Object.keys(scannedEntities.permissionSets),
|
|
21
|
+
};
|
|
22
|
+
opts.permissions.forEach((permName) => {
|
|
23
|
+
const profiles = findGrantingEntities(permName, scannedEntities.profiles);
|
|
24
|
+
const permissionSets = findGrantingEntities(permName, scannedEntities.permissionSets);
|
|
25
|
+
scanResult.permissions[permName] = { permissionSets, profiles };
|
|
26
|
+
});
|
|
27
|
+
this.emitProgress({ status: 'Completed' });
|
|
28
|
+
return scanResult;
|
|
29
|
+
}
|
|
30
|
+
async resolveEntities(targetOrg) {
|
|
31
|
+
const promises = [];
|
|
32
|
+
this.emitProgress({ status: 'In Progress' });
|
|
33
|
+
promises.push(this.resolveProfiles(targetOrg));
|
|
34
|
+
promises.push(this.resolvePermissionSets(targetOrg));
|
|
35
|
+
const resolvedEntities = await Promise.all(promises);
|
|
36
|
+
return {
|
|
37
|
+
profiles: resolvedEntities[0],
|
|
38
|
+
permissionSets: resolvedEntities[1],
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
async resolveProfiles(targetOrg) {
|
|
42
|
+
const profiles = await targetOrg.query(PROFILES_QUERY);
|
|
43
|
+
this.emitProgress({ profiles: { total: profiles.records.length, resolved: 0 } });
|
|
44
|
+
const mdapi = MDAPI.create(targetOrg);
|
|
45
|
+
const resolved = await mdapi.resolve('Profile', profiles.records.map((permsetRecord) => permsetRecord.Profile.Name));
|
|
46
|
+
this.emitProgress({ profiles: { resolved: Object.keys(resolved).length } });
|
|
47
|
+
return resolved;
|
|
48
|
+
}
|
|
49
|
+
async resolvePermissionSets(targetOrg) {
|
|
50
|
+
const permSets = await targetOrg.query(PERMISSION_SETS_QUERY);
|
|
51
|
+
this.emitProgress({ permissionSets: { total: permSets.records.length, resolved: 0 } });
|
|
52
|
+
const mdapi = MDAPI.create(targetOrg);
|
|
53
|
+
const resolved = await mdapi.resolve('PermissionSet', permSets.records.map((permsetRecord) => permsetRecord.Name));
|
|
54
|
+
this.emitProgress({ permissionSets: { resolved: Object.keys(resolved).length } });
|
|
55
|
+
return resolved;
|
|
56
|
+
}
|
|
57
|
+
emitProgress(update) {
|
|
58
|
+
this.status.profiles = { ...this.status.profiles, ...update.profiles };
|
|
59
|
+
this.status.permissionSets = { ...this.status.permissionSets, ...update.permissionSets };
|
|
60
|
+
this.status.users = { ...this.status.users, ...update.users };
|
|
61
|
+
this.status.status = update.status ?? this.status.status;
|
|
62
|
+
this.emit('progress', structuredClone(this.status));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function findGrantingEntities(permName, resolvedEntities) {
|
|
66
|
+
const entities = new Set();
|
|
67
|
+
Object.entries(resolvedEntities).forEach(([entityName, metadata]) => {
|
|
68
|
+
const userPerms = metadata.userPermissions.map((userPerm) => userPerm.name);
|
|
69
|
+
if (userPerms.includes(permName)) {
|
|
70
|
+
entities.add(entityName);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
return Array.from(entities);
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=userPermissionScanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"userPermissionScanner.js","sourceRoot":"","sources":["../../../src/libs/quick-scan/userPermissionScanner.ts"],"names":[],"mappings":"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"}
|
|
@@ -35,3 +35,15 @@ At least one policy is not compliant. Review details below.
|
|
|
35
35
|
# info.report-file-location
|
|
36
36
|
|
|
37
37
|
Full report was written to: %s.
|
|
38
|
+
|
|
39
|
+
# NoAuditConfigFound
|
|
40
|
+
|
|
41
|
+
The target directory %s is empty or no valid audit config was found. A valid audit config must contain at least one policy.
|
|
42
|
+
|
|
43
|
+
# UserPermClassificationRequiredForProfiles
|
|
44
|
+
|
|
45
|
+
The "Profiles" policy requires at least userPermissions to be initialised, but none were found at the target directory.
|
|
46
|
+
|
|
47
|
+
# UserPermClassificationRequiredForPermSets
|
|
48
|
+
|
|
49
|
+
The "Permission Sets" policy requires at least userPermissions to be initialised, but none were found at the target directory.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# summary
|
|
2
|
+
|
|
3
|
+
Performs a quick scan to check permission sets and profiles for user permissions.
|
|
4
|
+
|
|
5
|
+
# description
|
|
6
|
+
|
|
7
|
+
The quick scan does not need an audit config and does not create reports. The target org is scanned "in memory" and simply outputs information, where the searched user permissions
|
|
8
|
+
|
|
9
|
+
# flags.name.summary
|
|
10
|
+
|
|
11
|
+
One or more permissions to be scanned.
|
|
12
|
+
|
|
13
|
+
# flags.name.description
|
|
14
|
+
|
|
15
|
+
You can specify any valid user permission on your org, such as "AuthorApex", "CustomizeApplication" or "ViewSetup". If you are unsure what permissions are available on your org, initialise a new audit config and check the created userPermissions.yml.
|
|
16
|
+
|
|
17
|
+
# flags.target-org.summary
|
|
18
|
+
|
|
19
|
+
The target org to scan.
|
|
20
|
+
|
|
21
|
+
# examples
|
|
22
|
+
|
|
23
|
+
- <%= config.bin %> <%= command.id %>
|
|
24
|
+
|
|
25
|
+
# success.profiles-count
|
|
26
|
+
|
|
27
|
+
Scanned %s profiles.
|
|
28
|
+
|
|
29
|
+
# success.permissionsets-count
|
|
30
|
+
|
|
31
|
+
Scanned %s permission sets.
|
package/oclif.manifest.json
CHANGED
|
@@ -171,7 +171,85 @@
|
|
|
171
171
|
"run:org:audit",
|
|
172
172
|
"run:audit:org"
|
|
173
173
|
]
|
|
174
|
+
},
|
|
175
|
+
"org:scan:user-perms": {
|
|
176
|
+
"aliases": [],
|
|
177
|
+
"args": {},
|
|
178
|
+
"description": "The quick scan does not need an audit config and does not create reports. The target org is scanned \"in memory\" and simply outputs information, where the searched user permissions",
|
|
179
|
+
"examples": [
|
|
180
|
+
"<%= config.bin %> <%= command.id %>"
|
|
181
|
+
],
|
|
182
|
+
"flags": {
|
|
183
|
+
"json": {
|
|
184
|
+
"description": "Format output as json.",
|
|
185
|
+
"helpGroup": "GLOBAL",
|
|
186
|
+
"name": "json",
|
|
187
|
+
"allowNo": false,
|
|
188
|
+
"type": "boolean"
|
|
189
|
+
},
|
|
190
|
+
"flags-dir": {
|
|
191
|
+
"helpGroup": "GLOBAL",
|
|
192
|
+
"name": "flags-dir",
|
|
193
|
+
"summary": "Import flag values from a directory.",
|
|
194
|
+
"hasDynamicHelp": false,
|
|
195
|
+
"multiple": false,
|
|
196
|
+
"type": "option"
|
|
197
|
+
},
|
|
198
|
+
"name": {
|
|
199
|
+
"char": "n",
|
|
200
|
+
"description": "You can specify any valid user permission on your org, such as \"AuthorApex\", \"CustomizeApplication\" or \"ViewSetup\". If you are unsure what permissions are available on your org, initialise a new audit config and check the created userPermissions.yml.",
|
|
201
|
+
"name": "name",
|
|
202
|
+
"required": true,
|
|
203
|
+
"summary": "One or more permissions to be scanned.",
|
|
204
|
+
"hasDynamicHelp": false,
|
|
205
|
+
"multiple": true,
|
|
206
|
+
"type": "option"
|
|
207
|
+
},
|
|
208
|
+
"target-org": {
|
|
209
|
+
"char": "o",
|
|
210
|
+
"name": "target-org",
|
|
211
|
+
"noCacheDefault": true,
|
|
212
|
+
"required": true,
|
|
213
|
+
"summary": "The target org to scan.",
|
|
214
|
+
"hasDynamicHelp": true,
|
|
215
|
+
"multiple": false,
|
|
216
|
+
"type": "option"
|
|
217
|
+
},
|
|
218
|
+
"api-version": {
|
|
219
|
+
"description": "Override the api version used for api requests made by this command",
|
|
220
|
+
"name": "api-version",
|
|
221
|
+
"hasDynamicHelp": false,
|
|
222
|
+
"multiple": false,
|
|
223
|
+
"type": "option"
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
"hasDynamicHelp": true,
|
|
227
|
+
"hiddenAliases": [],
|
|
228
|
+
"id": "org:scan:user-perms",
|
|
229
|
+
"pluginAlias": "@j-schreiber/sf-cli-security-audit",
|
|
230
|
+
"pluginName": "@j-schreiber/sf-cli-security-audit",
|
|
231
|
+
"pluginType": "core",
|
|
232
|
+
"strict": true,
|
|
233
|
+
"summary": "Performs a quick scan to check permission sets and profiles for user permissions.",
|
|
234
|
+
"enableJsonFlag": true,
|
|
235
|
+
"isESM": true,
|
|
236
|
+
"relativePath": [
|
|
237
|
+
"lib",
|
|
238
|
+
"commands",
|
|
239
|
+
"org",
|
|
240
|
+
"scan",
|
|
241
|
+
"user-perms.js"
|
|
242
|
+
],
|
|
243
|
+
"aliasPermutations": [],
|
|
244
|
+
"permutations": [
|
|
245
|
+
"org:scan:user-perms",
|
|
246
|
+
"scan:org:user-perms",
|
|
247
|
+
"scan:user-perms:org",
|
|
248
|
+
"org:user-perms:scan",
|
|
249
|
+
"user-perms:org:scan",
|
|
250
|
+
"user-perms:scan:org"
|
|
251
|
+
]
|
|
174
252
|
}
|
|
175
253
|
},
|
|
176
|
-
"version": "0.
|
|
254
|
+
"version": "0.6.0"
|
|
177
255
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@j-schreiber/sf-cli-security-audit",
|
|
3
3
|
"description": "Salesforce CLI plugin to automate highly configurable security audits",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.6.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "https",
|
|
7
7
|
"url": "https://github.com/j-schreiber/js-sf-cli-security-audit"
|