@j-schreiber/sf-cli-security-audit 0.2.0 → 0.4.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/README.md +10 -2
- package/lib/commands/org/audit/init.d.ts +17 -0
- package/lib/commands/org/audit/init.js +61 -0
- package/lib/commands/org/audit/init.js.map +1 -0
- package/lib/commands/org/audit/run.d.ts +22 -0
- package/lib/commands/org/audit/run.js +113 -0
- package/lib/commands/org/audit/run.js.map +1 -0
- package/lib/libs/audit/types.d.ts +154 -0
- package/lib/libs/audit/types.js +2 -0
- package/lib/libs/audit/types.js.map +1 -0
- package/lib/libs/config/audit-run/auditConfigFileManager.d.ts +26 -0
- package/lib/libs/config/audit-run/auditConfigFileManager.js +98 -0
- package/lib/libs/config/audit-run/auditConfigFileManager.js.map +1 -0
- package/lib/libs/config/audit-run/schema.d.ts +100 -0
- package/lib/libs/config/audit-run/schema.js +45 -0
- package/lib/libs/config/audit-run/schema.js.map +1 -0
- package/lib/libs/config/defaultPolicyClassification.d.ts +2 -0
- package/lib/libs/config/defaultPolicyClassification.js +63 -0
- package/lib/libs/config/defaultPolicyClassification.js.map +1 -0
- package/lib/libs/config/queries.d.ts +5 -0
- package/lib/libs/config/queries.js +6 -0
- package/lib/libs/config/queries.js.map +1 -0
- package/lib/libs/config/registries/connectedApps.d.ts +5 -0
- package/lib/libs/config/registries/connectedApps.js +13 -0
- package/lib/libs/config/registries/connectedApps.js.map +1 -0
- package/lib/libs/config/registries/permissionSets.d.ts +5 -0
- package/lib/libs/config/registries/permissionSets.js +11 -0
- package/lib/libs/config/registries/permissionSets.js.map +1 -0
- package/lib/libs/config/registries/profiles.d.ts +5 -0
- package/lib/libs/config/registries/profiles.js +13 -0
- package/lib/libs/config/registries/profiles.js.map +1 -0
- package/lib/libs/config/registries/ruleRegistry.d.ts +29 -0
- package/lib/libs/config/registries/ruleRegistry.js +48 -0
- package/lib/libs/config/registries/ruleRegistry.js.map +1 -0
- package/lib/libs/config/registries/types.d.ts +7 -0
- package/lib/libs/config/registries/types.js +2 -0
- package/lib/libs/config/registries/types.js.map +1 -0
- package/lib/libs/mdapiRetriever.d.ts +18 -0
- package/lib/libs/mdapiRetriever.js +60 -0
- package/lib/libs/mdapiRetriever.js.map +1 -0
- package/lib/libs/policies/auditRun.d.ts +36 -0
- package/lib/libs/policies/auditRun.js +92 -0
- package/lib/libs/policies/auditRun.js.map +1 -0
- package/lib/libs/policies/connectedAppPolicy.d.ts +18 -0
- package/lib/libs/policies/connectedAppPolicy.js +78 -0
- package/lib/libs/policies/connectedAppPolicy.js.map +1 -0
- package/lib/libs/policies/initialisation/auditConfig.d.ts +27 -0
- package/lib/libs/policies/initialisation/auditConfig.js +41 -0
- package/lib/libs/policies/initialisation/auditConfig.js.map +1 -0
- package/lib/libs/policies/initialisation/permissionsClassification.d.ts +17 -0
- package/lib/libs/policies/initialisation/permissionsClassification.js +71 -0
- package/lib/libs/policies/initialisation/permissionsClassification.js.map +1 -0
- package/lib/libs/policies/initialisation/policyConfigs.d.ts +25 -0
- package/lib/libs/policies/initialisation/policyConfigs.js +67 -0
- package/lib/libs/policies/initialisation/policyConfigs.js.map +1 -0
- package/lib/libs/policies/interfaces/policyRuleInterfaces.d.ts +30 -0
- package/lib/libs/policies/interfaces/policyRuleInterfaces.js +2 -0
- package/lib/libs/policies/interfaces/policyRuleInterfaces.js.map +1 -0
- package/lib/libs/policies/permissionSetPolicy.d.ts +17 -0
- package/lib/libs/policies/permissionSetPolicy.js +61 -0
- package/lib/libs/policies/permissionSetPolicy.js.map +1 -0
- package/lib/libs/policies/policy.d.ts +32 -0
- package/lib/libs/policies/policy.js +95 -0
- package/lib/libs/policies/policy.js.map +1 -0
- package/lib/libs/policies/profilePolicy.d.ts +17 -0
- package/lib/libs/policies/profilePolicy.js +71 -0
- package/lib/libs/policies/profilePolicy.js.map +1 -0
- package/lib/libs/policies/rules/allUsedAppsUnderManagement.d.ts +7 -0
- package/lib/libs/policies/rules/allUsedAppsUnderManagement.js +23 -0
- package/lib/libs/policies/rules/allUsedAppsUnderManagement.js.map +1 -0
- package/lib/libs/policies/rules/enforceCustomPermsClassificationOnProfiles.d.ts +7 -0
- package/lib/libs/policies/rules/enforceCustomPermsClassificationOnProfiles.js +51 -0
- package/lib/libs/policies/rules/enforceCustomPermsClassificationOnProfiles.js.map +1 -0
- package/lib/libs/policies/rules/enforceUserPermsClassificationOnPermSets.d.ts +7 -0
- package/lib/libs/policies/rules/enforceUserPermsClassificationOnPermSets.js +51 -0
- package/lib/libs/policies/rules/enforceUserPermsClassificationOnPermSets.js.map +1 -0
- package/lib/libs/policies/rules/enforceUserPermsClassificationOnProfiles.d.ts +7 -0
- package/lib/libs/policies/rules/enforceUserPermsClassificationOnProfiles.js +53 -0
- package/lib/libs/policies/rules/enforceUserPermsClassificationOnProfiles.js.map +1 -0
- package/lib/libs/policies/rules/noUserCanSelfAuthorize.d.ts +7 -0
- package/lib/libs/policies/rules/noUserCanSelfAuthorize.js +31 -0
- package/lib/libs/policies/rules/noUserCanSelfAuthorize.js.map +1 -0
- package/lib/libs/policies/rules/policyRule.d.ts +16 -0
- package/lib/libs/policies/rules/policyRule.js +29 -0
- package/lib/libs/policies/rules/policyRule.js.map +1 -0
- package/lib/libs/policies/salesforceStandardTypes.d.ts +39 -0
- package/lib/libs/policies/salesforceStandardTypes.js +2 -0
- package/lib/libs/policies/salesforceStandardTypes.js.map +1 -0
- package/lib/libs/policies/types.d.ts +36 -0
- package/lib/libs/policies/types.js +45 -0
- package/lib/libs/policies/types.js.map +1 -0
- package/lib/libs/utils.d.ts +3 -0
- package/lib/libs/utils.js +13 -0
- package/lib/libs/utils.js.map +1 -0
- package/lib/ux/auditRunMultiStage.d.ts +65 -0
- package/lib/ux/auditRunMultiStage.js +117 -0
- package/lib/ux/auditRunMultiStage.js.map +1 -0
- package/messages/org.audit.init.md +1 -1
- package/messages/org.audit.run.md +0 -4
- package/messages/policies.general.md +12 -0
- package/messages/rules.connectedApps.md +11 -0
- package/oclif.manifest.json +159 -2
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -2,17 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
> This plugin is still in beta and under active development. Command signatures may be subject to change.
|
|
4
4
|
|
|
5
|
+
For an in-depth documentation that goes beyond command signatures and explains the core concepts, design decisions, and a variety of use cases [see our Wiki](https://github.com/j-schreiber/js-sf-cli-security-audit/wiki).
|
|
6
|
+
|
|
5
7
|
# Installation
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
To build from source, follow these steps
|
|
8
10
|
|
|
9
11
|
```bash
|
|
10
|
-
git clone https
|
|
12
|
+
git clone https://github.com/j-schreiber/js-sf-cli-security-audit
|
|
11
13
|
mkdir sf-cli-security-audit
|
|
12
14
|
yarn && yarn build
|
|
13
15
|
sf plugins link .
|
|
14
16
|
```
|
|
15
17
|
|
|
18
|
+
To install the latest version from NPM
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
sf plugins install @j-schreiber/sf-cli-security-audit
|
|
22
|
+
```
|
|
23
|
+
|
|
16
24
|
# Contribute
|
|
17
25
|
|
|
18
26
|
Contributers are welcome! Please reach out on [Linkedin](https://www.linkedin.com/in/jannis-schreiber/) or via [Email](mailto:info@lietzau-consulting.de).
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { SfCommand } from '@salesforce/sf-plugins-core';
|
|
2
|
+
import { AuditRunConfig } from '../../../libs/config/audit-run/schema.js';
|
|
3
|
+
export type OrgAuditInitResult = AuditRunConfig;
|
|
4
|
+
export default class OrgAuditInit extends SfCommand<OrgAuditInitResult> {
|
|
5
|
+
static readonly summary: string;
|
|
6
|
+
static readonly description: string;
|
|
7
|
+
static readonly examples: string[];
|
|
8
|
+
static readonly flags: {
|
|
9
|
+
'target-org': import("@oclif/core/interfaces").OptionFlag<import("@salesforce/core").Org, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
'output-dir': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
'api-version': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
};
|
|
13
|
+
run(): Promise<OrgAuditInitResult>;
|
|
14
|
+
private printResults;
|
|
15
|
+
private printClassifications;
|
|
16
|
+
private printPolicies;
|
|
17
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
|
|
2
|
+
import { Messages } from '@salesforce/core';
|
|
3
|
+
import AuditConfig from '../../../libs/policies/initialisation/auditConfig.js';
|
|
4
|
+
import { isPermissionsConfig, isPolicyConfig, } from '../../../libs/config/audit-run/schema.js';
|
|
5
|
+
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
|
|
6
|
+
const messages = Messages.loadMessages('@j-schreiber/sf-cli-security-audit', 'org.audit.init');
|
|
7
|
+
export default class OrgAuditInit extends SfCommand {
|
|
8
|
+
static summary = messages.getMessage('summary');
|
|
9
|
+
static description = messages.getMessage('description');
|
|
10
|
+
static examples = messages.getMessages('examples');
|
|
11
|
+
static flags = {
|
|
12
|
+
'target-org': Flags.requiredOrg({
|
|
13
|
+
summary: messages.getMessage('flags.target-org.summary'),
|
|
14
|
+
char: 'o',
|
|
15
|
+
required: true,
|
|
16
|
+
}),
|
|
17
|
+
'output-dir': Flags.directory({
|
|
18
|
+
required: false,
|
|
19
|
+
char: 'd',
|
|
20
|
+
summary: messages.getMessage('flags.output-dir.summary'),
|
|
21
|
+
default: '',
|
|
22
|
+
}),
|
|
23
|
+
'api-version': Flags.orgApiVersion(),
|
|
24
|
+
};
|
|
25
|
+
async run() {
|
|
26
|
+
const { flags } = await this.parse(OrgAuditInit);
|
|
27
|
+
const auditConfig = await AuditConfig.init(flags['target-org'].getConnection(flags['api-version']), {
|
|
28
|
+
targetDir: flags['output-dir'],
|
|
29
|
+
});
|
|
30
|
+
this.printResults(auditConfig);
|
|
31
|
+
return auditConfig;
|
|
32
|
+
}
|
|
33
|
+
printResults(config) {
|
|
34
|
+
this.printClassifications(config.classifications);
|
|
35
|
+
this.printPolicies(config.policies);
|
|
36
|
+
}
|
|
37
|
+
printClassifications(classifications) {
|
|
38
|
+
Object.values(classifications).forEach((def) => {
|
|
39
|
+
if (isPermissionsConfig(def)) {
|
|
40
|
+
const perms = def.content.permissions ? Object.entries(def.content.permissions) : [];
|
|
41
|
+
if (perms.length > 0) {
|
|
42
|
+
this.logSuccess(messages.getMessage('success.perm-classification-summary', [perms.length ?? 0, def.filePath]));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
printPolicies(policies) {
|
|
48
|
+
Object.entries(policies).forEach(([name, def]) => {
|
|
49
|
+
if (isPolicyConfig(def)) {
|
|
50
|
+
if (def.filePath) {
|
|
51
|
+
this.logSuccess(messages.getMessage('success.policy-summary', [
|
|
52
|
+
name,
|
|
53
|
+
Object.keys(def.content.rules).length ?? 0,
|
|
54
|
+
def.filePath,
|
|
55
|
+
]));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../../src/commands/org/audit/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,WAAW,MAAM,sDAAsD,CAAC;AAC/E,OAAO,EAIL,mBAAmB,EACnB,cAAc,GACf,MAAM,0CAA0C,CAAC;AAElD,QAAQ,CAAC,kCAAkC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC7D,MAAM,QAAQ,GAAG,QAAQ,CAAC,YAAY,CAAC,oCAAoC,EAAE,gBAAgB,CAAC,CAAC;AAI/F,MAAM,CAAC,OAAO,OAAO,YAAa,SAAQ,SAA6B;IAC9D,MAAM,CAAU,OAAO,GAAG,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IACzD,MAAM,CAAU,WAAW,GAAG,QAAQ,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;IACjE,MAAM,CAAU,QAAQ,GAAG,QAAQ,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;IAE5D,MAAM,CAAU,KAAK,GAAG;QAC7B,YAAY,EAAE,KAAK,CAAC,WAAW,CAAC;YAC9B,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,0BAA0B,CAAC;YACxD,IAAI,EAAE,GAAG;YACT,QAAQ,EAAE,IAAI;SACf,CAAC;QACF,YAAY,EAAE,KAAK,CAAC,SAAS,CAAC;YAC5B,QAAQ,EAAE,KAAK;YACf,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,0BAA0B,CAAC;YACxD,OAAO,EAAE,EAAE;SACZ,CAAC;QACF,aAAa,EAAE,KAAK,CAAC,aAAa,EAAE;KACrC,CAAC;IAEK,KAAK,CAAC,GAAG;QACd,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QACjD,MAAM,WAAW,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,EAAE;YAClG,SAAS,EAAE,KAAK,CAAC,YAAY,CAAC;SAC/B,CAAC,CAAC;QACH,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;QAC/B,OAAO,WAAW,CAAC;IACrB,CAAC;IAEO,YAAY,CAAC,MAAsB;QACzC,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;QAClD,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACtC,CAAC;IAEO,oBAAoB,CAAC,eAA8C;QACzE,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;YAC7C,IAAI,mBAAmB,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC7B,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBACrF,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACrB,IAAI,CAAC,UAAU,CACb,QAAQ,CAAC,UAAU,CAAC,qCAAqC,EAAE,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAC9F,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,aAAa,CAAC,QAAgC;QACpD,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE;YAC/C,IAAI,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC;gBACxB,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;oBACjB,IAAI,CAAC,UAAU,CACb,QAAQ,CAAC,UAAU,CAAC,wBAAwB,EAAE;wBAC5C,IAAI;wBACJ,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,MAAM,IAAI,CAAC;wBAC1C,GAAG,CAAC,QAAQ;qBACb,CAAC,CACH,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Interfaces } from '@oclif/core';
|
|
2
|
+
import { SfCommand } from '@salesforce/sf-plugins-core';
|
|
3
|
+
import { AuditResult } from '../../../libs/audit/types.js';
|
|
4
|
+
export type OrgAuditRunResult = AuditResult & {
|
|
5
|
+
filePath: string;
|
|
6
|
+
};
|
|
7
|
+
export default class OrgAuditRun extends SfCommand<OrgAuditRunResult> {
|
|
8
|
+
static readonly summary: string;
|
|
9
|
+
static readonly description: string;
|
|
10
|
+
static readonly examples: string[];
|
|
11
|
+
static readonly flags: {
|
|
12
|
+
'target-org': Interfaces.OptionFlag<import("@salesforce/core").Org, Interfaces.CustomOptions>;
|
|
13
|
+
'source-dir': Interfaces.OptionFlag<string, Interfaces.CustomOptions>;
|
|
14
|
+
'api-version': Interfaces.OptionFlag<string | undefined, Interfaces.CustomOptions>;
|
|
15
|
+
};
|
|
16
|
+
run(): Promise<OrgAuditRunResult>;
|
|
17
|
+
private printResults;
|
|
18
|
+
private printPoliciesSummary;
|
|
19
|
+
private printExecutedRulesSummary;
|
|
20
|
+
private printRuleViolations;
|
|
21
|
+
private writeReport;
|
|
22
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { writeFileSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { SfCommand, Flags, StandardColors } from '@salesforce/sf-plugins-core';
|
|
4
|
+
import { Messages } from '@salesforce/core';
|
|
5
|
+
import { startAuditRun } from '../../../libs/policies/auditRun.js';
|
|
6
|
+
import AuditRunMultiStageOutput from '../../../ux/auditRunMultiStage.js';
|
|
7
|
+
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
|
|
8
|
+
const messages = Messages.loadMessages('@j-schreiber/sf-cli-security-audit', 'org.audit.run');
|
|
9
|
+
export default class OrgAuditRun extends SfCommand {
|
|
10
|
+
static summary = messages.getMessage('summary');
|
|
11
|
+
static description = messages.getMessage('description');
|
|
12
|
+
static examples = messages.getMessages('examples');
|
|
13
|
+
static flags = {
|
|
14
|
+
'target-org': Flags.requiredOrg({
|
|
15
|
+
summary: messages.getMessage('flags.target-org.summary'),
|
|
16
|
+
char: 'o',
|
|
17
|
+
required: true,
|
|
18
|
+
}),
|
|
19
|
+
'source-dir': Flags.directory({
|
|
20
|
+
required: false,
|
|
21
|
+
char: 'd',
|
|
22
|
+
summary: messages.getMessage('flags.source-dir.summary'),
|
|
23
|
+
default: '',
|
|
24
|
+
}),
|
|
25
|
+
'api-version': Flags.orgApiVersion(),
|
|
26
|
+
};
|
|
27
|
+
async run() {
|
|
28
|
+
const { flags } = await this.parse(OrgAuditRun);
|
|
29
|
+
const stageOutput = AuditRunMultiStageOutput.create({
|
|
30
|
+
directoryRootPath: flags['source-dir'],
|
|
31
|
+
targetOrg: flags['target-org'].getUsername() ?? flags['target-org'].getOrgId(),
|
|
32
|
+
jsonEnabled: flags.json,
|
|
33
|
+
});
|
|
34
|
+
stageOutput.start();
|
|
35
|
+
const auditRun = startAuditRun(flags['source-dir']);
|
|
36
|
+
stageOutput.startPolicyResolve(auditRun);
|
|
37
|
+
await auditRun.resolve(flags['target-org'].getConnection(flags['api-version']));
|
|
38
|
+
stageOutput.startRuleExecution();
|
|
39
|
+
const partialResult = await auditRun.execute(flags['target-org'].getConnection(flags['api-version']));
|
|
40
|
+
const result = { orgId: flags['target-org'].getOrgId(), ...partialResult };
|
|
41
|
+
stageOutput.finish();
|
|
42
|
+
this.printResults(result);
|
|
43
|
+
const filePath = this.writeReport(result, flags);
|
|
44
|
+
return { ...result, filePath };
|
|
45
|
+
}
|
|
46
|
+
printResults(result) {
|
|
47
|
+
this.printPoliciesSummary(result);
|
|
48
|
+
Object.entries(result.policies).forEach(([policyName, policyDetails]) => {
|
|
49
|
+
this.printExecutedRulesSummary(policyName, policyDetails);
|
|
50
|
+
this.printRuleViolations(policyDetails.executedRules);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
printPoliciesSummary(result) {
|
|
54
|
+
const polSummaries = transposePoliciesToTable(result);
|
|
55
|
+
if (result.isCompliant) {
|
|
56
|
+
this.logSuccess(messages.getMessage('success.all-policies-compliant'));
|
|
57
|
+
this.log('');
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
this.log(StandardColors.error(messages.getMessage('summary-non-compliant')));
|
|
61
|
+
this.log('');
|
|
62
|
+
}
|
|
63
|
+
this.table({ data: polSummaries, title: '=== Summary ===', titleOptions: { bold: true } });
|
|
64
|
+
}
|
|
65
|
+
printExecutedRulesSummary(policyName, policyDetails) {
|
|
66
|
+
const rulesSummary = transposeExecutedPolicyRules(policyDetails);
|
|
67
|
+
if (rulesSummary.length > 0) {
|
|
68
|
+
this.table({
|
|
69
|
+
data: rulesSummary,
|
|
70
|
+
title: `--- Executed Rules for ${policyName} ---`,
|
|
71
|
+
titleOptions: { underline: true },
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
printRuleViolations(executedRules) {
|
|
76
|
+
Object.values(executedRules)
|
|
77
|
+
.filter((ruleDetails) => !ruleDetails.isCompliant)
|
|
78
|
+
.forEach((uncompliantRule) => {
|
|
79
|
+
this.table({ data: uncompliantRule.violations, title: `Violations for ${uncompliantRule.ruleName}` });
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
writeReport(result, flags) {
|
|
83
|
+
const fileName = `report_${flags['target-org'].getOrgId()}_${Date.now()}.json`;
|
|
84
|
+
const fullPath = path.join(flags['source-dir'], fileName);
|
|
85
|
+
writeFileSync(fullPath, JSON.stringify(result, null, 2));
|
|
86
|
+
this.info(messages.getMessage('info.report-file-location', [fullPath]));
|
|
87
|
+
return fullPath;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function transposePoliciesToTable(result) {
|
|
91
|
+
return Object.entries(result.policies).map(([policyName, policyDetails]) => {
|
|
92
|
+
const rulesExecuted = policyDetails?.executedRules ? Object.keys(policyDetails.executedRules).length : 0;
|
|
93
|
+
return {
|
|
94
|
+
policy: policyName,
|
|
95
|
+
isCompliant: policyDetails.isCompliant,
|
|
96
|
+
rulesExecuted,
|
|
97
|
+
auditedEntities: policyDetails.auditedEntities?.length ?? 0,
|
|
98
|
+
ignoredEntities: policyDetails.ignoredEntities?.length ?? 0,
|
|
99
|
+
};
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
function transposeExecutedPolicyRules(result) {
|
|
103
|
+
return Object.entries(result.executedRules).map(([ruleName, ruleDetails]) => ({
|
|
104
|
+
rule: ruleName,
|
|
105
|
+
isCompliant: ruleDetails.isCompliant,
|
|
106
|
+
compliantEntities: ruleDetails.compliantEntities?.length ?? 0,
|
|
107
|
+
violatedEntities: ruleDetails.violatedEntities?.length ?? 0,
|
|
108
|
+
violations: ruleDetails.violations.length,
|
|
109
|
+
warnings: ruleDetails.warnings.length,
|
|
110
|
+
errors: ruleDetails.errors.length,
|
|
111
|
+
}));
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../../../src/commands/org/audit/run.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A single violation from a policy rule execution.
|
|
3
|
+
*/
|
|
4
|
+
export type PolicyRuleViolation = RuleComponentMessage & {
|
|
5
|
+
/**
|
|
6
|
+
* Optional descriptive message that explains how to fix the violation.
|
|
7
|
+
*/
|
|
8
|
+
hint?: string;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* A muted violation with additional information why it was muted
|
|
12
|
+
*/
|
|
13
|
+
export type PolicyRuleViolationMute = PolicyRuleViolation & {
|
|
14
|
+
/**
|
|
15
|
+
* Descriptive reason from allow-config why this violation is muted.
|
|
16
|
+
*/
|
|
17
|
+
reason: string;
|
|
18
|
+
/**
|
|
19
|
+
* Path to the config file that allowed this violation for reference.
|
|
20
|
+
*/
|
|
21
|
+
allowListEntryPath?: string;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Details about s config entity of a policy (such as a profile, perm set, user)
|
|
25
|
+
* that did not resolve successfully. This may be because the entity does not exist
|
|
26
|
+
* on the target org or because it is not registered.
|
|
27
|
+
*/
|
|
28
|
+
export type EntityResolveError = {
|
|
29
|
+
/**
|
|
30
|
+
* Identifier of the entity, e.g. profile name, username, rule, policy, etc
|
|
31
|
+
*/
|
|
32
|
+
name: string;
|
|
33
|
+
/**
|
|
34
|
+
* Message that explains, why the entity was not successfully resolved
|
|
35
|
+
*/
|
|
36
|
+
message: string;
|
|
37
|
+
};
|
|
38
|
+
export type RuleComponentMessage = {
|
|
39
|
+
/**
|
|
40
|
+
* Path to a component. This can be a developer name of a connected app,
|
|
41
|
+
* permission set name or the permission within a profile.
|
|
42
|
+
*/
|
|
43
|
+
identifier: string | string[];
|
|
44
|
+
/**
|
|
45
|
+
* Descriptive message of the error, warning or violation.
|
|
46
|
+
*/
|
|
47
|
+
message: string;
|
|
48
|
+
};
|
|
49
|
+
export type PolicyRuleSkipResult = {
|
|
50
|
+
/**
|
|
51
|
+
* Identifier of the rule, as it is configured in the policy.yml.
|
|
52
|
+
*/
|
|
53
|
+
name: string;
|
|
54
|
+
/**
|
|
55
|
+
* Descriptive message why the rule was skipped.
|
|
56
|
+
*/
|
|
57
|
+
skipReason: string;
|
|
58
|
+
};
|
|
59
|
+
export type PolicyRuleExecutionResult = {
|
|
60
|
+
/**
|
|
61
|
+
* Identifier of the rule, as it is configured in the policy.yml.
|
|
62
|
+
*/
|
|
63
|
+
ruleName: string;
|
|
64
|
+
/**
|
|
65
|
+
* Short-hand accessor, if an execution had at least one violation.
|
|
66
|
+
*/
|
|
67
|
+
isCompliant: boolean;
|
|
68
|
+
/**
|
|
69
|
+
* All violations of the rule that were reported.
|
|
70
|
+
*/
|
|
71
|
+
violations: PolicyRuleViolation[];
|
|
72
|
+
/**
|
|
73
|
+
* Identifiers of compliant entities. An entity is compliant, if it has
|
|
74
|
+
* zero violations.
|
|
75
|
+
*/
|
|
76
|
+
compliantEntities: string[];
|
|
77
|
+
/**
|
|
78
|
+
* Identifiers of violated entities. Each entity may have several violations,
|
|
79
|
+
* depending on the analysis depth of the rule.
|
|
80
|
+
*/
|
|
81
|
+
violatedEntities: string[];
|
|
82
|
+
/**
|
|
83
|
+
* Violations that were identified, but were muted by a matching allow-list.
|
|
84
|
+
* Muted violations do not affect compliance.
|
|
85
|
+
*/
|
|
86
|
+
mutedViolations: PolicyRuleViolationMute[];
|
|
87
|
+
/**
|
|
88
|
+
* Components of a rule that were not successfully processed and returned errors from the org
|
|
89
|
+
*/
|
|
90
|
+
errors: RuleComponentMessage[];
|
|
91
|
+
/**
|
|
92
|
+
* Components that were not auditable, but did not hinder the execution of the audit
|
|
93
|
+
* Such as permissions on the org that are not classified.
|
|
94
|
+
*/
|
|
95
|
+
warnings: RuleComponentMessage[];
|
|
96
|
+
};
|
|
97
|
+
export type AuditPolicyResult = {
|
|
98
|
+
/**
|
|
99
|
+
* Flag that indicates, if the policy was executed.
|
|
100
|
+
*/
|
|
101
|
+
enabled: boolean;
|
|
102
|
+
/**
|
|
103
|
+
* All executed rules were compliant.
|
|
104
|
+
*/
|
|
105
|
+
isCompliant: boolean;
|
|
106
|
+
/**
|
|
107
|
+
* Record of rules that were executed. Rules are mapped by their name.
|
|
108
|
+
*/
|
|
109
|
+
executedRules: {
|
|
110
|
+
[ruleName: string]: PolicyRuleExecutionResult;
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* List of rules that exist for the policy that were not executed.
|
|
114
|
+
*/
|
|
115
|
+
skippedRules: PolicyRuleSkipResult[];
|
|
116
|
+
/**
|
|
117
|
+
* If the policy was not enabled, a brief message that explains why.
|
|
118
|
+
*/
|
|
119
|
+
disabledReason?: string;
|
|
120
|
+
/**
|
|
121
|
+
* Path to the config file that was processed for this audit.
|
|
122
|
+
*/
|
|
123
|
+
configPath?: string;
|
|
124
|
+
/**
|
|
125
|
+
* A full list of audited entities. Use together with violations to see, which
|
|
126
|
+
* entities were not compliant.
|
|
127
|
+
*/
|
|
128
|
+
auditedEntities: string[];
|
|
129
|
+
/**
|
|
130
|
+
* Full list of entities that were present in the config file, but could not
|
|
131
|
+
* be resolved for this org.
|
|
132
|
+
*/
|
|
133
|
+
ignoredEntities: EntityResolveError[];
|
|
134
|
+
};
|
|
135
|
+
export type AuditResult = {
|
|
136
|
+
/**
|
|
137
|
+
* All executed policies were compliant.
|
|
138
|
+
*/
|
|
139
|
+
isCompliant: boolean;
|
|
140
|
+
/**
|
|
141
|
+
* Id of the audited org.
|
|
142
|
+
*/
|
|
143
|
+
orgId: string;
|
|
144
|
+
/**
|
|
145
|
+
* ISO date time of the audit
|
|
146
|
+
*/
|
|
147
|
+
auditDate: string;
|
|
148
|
+
/**
|
|
149
|
+
* Record map of all modules (policies) that were run.
|
|
150
|
+
*/
|
|
151
|
+
policies: {
|
|
152
|
+
[moduleName: string]: AuditPolicyResult;
|
|
153
|
+
};
|
|
154
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/libs/audit/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { AuditRunConfig } from './schema.js';
|
|
2
|
+
export declare const loadAuditConfig: (dirPath: string) => AuditRunConfig;
|
|
3
|
+
export declare const saveAuditConfig: (dirPath: string, conf: AuditRunConfig) => void;
|
|
4
|
+
export default class AuditConfigFileManager {
|
|
5
|
+
private directoryStructure;
|
|
6
|
+
constructor();
|
|
7
|
+
/**
|
|
8
|
+
* Parses a directory path for policy and classification files
|
|
9
|
+
* and initialises an audit config from file contents.
|
|
10
|
+
*
|
|
11
|
+
* @param dirPath
|
|
12
|
+
* @returns
|
|
13
|
+
*/
|
|
14
|
+
parse(dirPath: string): AuditRunConfig;
|
|
15
|
+
/**
|
|
16
|
+
* Writes a full audit config to disk. If the config was not
|
|
17
|
+
* saved yet, initialises filePath on each element.
|
|
18
|
+
*
|
|
19
|
+
* @param dirPath
|
|
20
|
+
* @param subdirName
|
|
21
|
+
* @returns
|
|
22
|
+
*/
|
|
23
|
+
save(targetDirPath: string, conf: AuditRunConfig): void;
|
|
24
|
+
private parseSubdir;
|
|
25
|
+
private writeSubdir;
|
|
26
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import yaml from 'js-yaml';
|
|
4
|
+
import { isEmpty } from '../../utils.js';
|
|
5
|
+
import { PermissionsConfigFileSchema, PermSetsPolicyFileSchema, PolicyFileSchema, ProfilesPolicyFileSchema, } from './schema.js';
|
|
6
|
+
export const loadAuditConfig = (dirPath) => {
|
|
7
|
+
const fileManager = new AuditConfigFileManager();
|
|
8
|
+
return fileManager.parse(dirPath);
|
|
9
|
+
};
|
|
10
|
+
export const saveAuditConfig = (dirPath, conf) => {
|
|
11
|
+
const fileManager = new AuditConfigFileManager();
|
|
12
|
+
fileManager.save(dirPath, conf);
|
|
13
|
+
};
|
|
14
|
+
export default class AuditConfigFileManager {
|
|
15
|
+
directoryStructure;
|
|
16
|
+
constructor() {
|
|
17
|
+
this.directoryStructure = {
|
|
18
|
+
policies: {
|
|
19
|
+
profiles: {
|
|
20
|
+
schema: ProfilesPolicyFileSchema,
|
|
21
|
+
},
|
|
22
|
+
permissionSets: {
|
|
23
|
+
schema: PermSetsPolicyFileSchema,
|
|
24
|
+
},
|
|
25
|
+
connectedApps: {
|
|
26
|
+
schema: PolicyFileSchema,
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
classifications: {
|
|
30
|
+
userPermissions: {
|
|
31
|
+
schema: PermissionsConfigFileSchema,
|
|
32
|
+
},
|
|
33
|
+
customPermissions: {
|
|
34
|
+
schema: PermissionsConfigFileSchema,
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Parses a directory path for policy and classification files
|
|
41
|
+
* and initialises an audit config from file contents.
|
|
42
|
+
*
|
|
43
|
+
* @param dirPath
|
|
44
|
+
* @returns
|
|
45
|
+
*/
|
|
46
|
+
parse(dirPath) {
|
|
47
|
+
const classifications = this.parseSubdir(dirPath, 'classifications');
|
|
48
|
+
const policies = capitalizeKeys(this.parseSubdir(dirPath, 'policies'));
|
|
49
|
+
return { classifications, policies };
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Writes a full audit config to disk. If the config was not
|
|
53
|
+
* saved yet, initialises filePath on each element.
|
|
54
|
+
*
|
|
55
|
+
* @param dirPath
|
|
56
|
+
* @param subdirName
|
|
57
|
+
* @returns
|
|
58
|
+
*/
|
|
59
|
+
save(targetDirPath, conf) {
|
|
60
|
+
Object.entries(conf).forEach(([dirName, configFiles]) => {
|
|
61
|
+
fs.mkdirSync(path.join(targetDirPath, dirName), { recursive: true });
|
|
62
|
+
this.writeSubdir(configFiles, dirName, targetDirPath);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
parseSubdir(dirPath, subdirName) {
|
|
66
|
+
const parseResults = {};
|
|
67
|
+
Object.entries(this.directoryStructure[subdirName]).forEach(([fileName, fileConfig]) => {
|
|
68
|
+
const filePath = path.join(dirPath, subdirName, `${fileName}.yml`);
|
|
69
|
+
if (fs.existsSync(filePath)) {
|
|
70
|
+
const fileContent = yaml.load(fs.readFileSync(filePath, 'utf-8'));
|
|
71
|
+
const content = fileConfig.schema.parse(fileContent);
|
|
72
|
+
parseResults[fileName] = { filePath, content };
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
return parseResults;
|
|
76
|
+
}
|
|
77
|
+
writeSubdir(configFiles, dirName, targetDirPath) {
|
|
78
|
+
const dirConf = this.directoryStructure[dirName];
|
|
79
|
+
if (!dirConf) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
Object.entries(configFiles).forEach(([fileKey, confFile]) => {
|
|
83
|
+
const uncapitalizedKey = `${fileKey[0].toLowerCase()}${fileKey.slice(1)}`;
|
|
84
|
+
const fileDef = dirConf[uncapitalizedKey];
|
|
85
|
+
if (fileDef && !isEmpty(confFile.content)) {
|
|
86
|
+
// eslint-disable-next-line no-param-reassign
|
|
87
|
+
confFile.filePath = path.join(targetDirPath, dirName, `${uncapitalizedKey}.yml`);
|
|
88
|
+
fs.writeFileSync(confFile.filePath, yaml.dump(confFile.content));
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
function capitalizeKeys(object) {
|
|
94
|
+
const newObj = {};
|
|
95
|
+
Object.keys(object).forEach((key) => (newObj[`${key[0].toUpperCase()}${key.slice(1)}`] = object[key]));
|
|
96
|
+
return newObj;
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=auditConfigFileManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auditConfigFileManager.js","sourceRoot":"","sources":["../../../../src/libs/config/audit-run/auditConfigFileManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import z from 'zod';
|
|
2
|
+
import { PermissionRiskLevelPresets, PolicyRiskLevel } from '../../policies/types.js';
|
|
3
|
+
declare const PermissionsClassificationSchema: z.ZodObject<{
|
|
4
|
+
label: z.ZodOptional<z.ZodString>;
|
|
5
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
6
|
+
classification: z.ZodEnum<typeof PolicyRiskLevel>;
|
|
7
|
+
}, z.z.core.$strip>;
|
|
8
|
+
declare const PermsClassificationsMapSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
9
|
+
label: z.ZodOptional<z.ZodString>;
|
|
10
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
11
|
+
classification: z.ZodEnum<typeof PolicyRiskLevel>;
|
|
12
|
+
}, z.z.core.$strip>>;
|
|
13
|
+
declare const NamedPermissionsClassificationSchema: z.ZodObject<{
|
|
14
|
+
label: z.ZodOptional<z.ZodString>;
|
|
15
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
16
|
+
classification: z.ZodEnum<typeof PolicyRiskLevel>;
|
|
17
|
+
name: z.ZodString;
|
|
18
|
+
}, z.z.core.$strip>;
|
|
19
|
+
declare const PolicyRuleConfigSchema: z.ZodObject<{
|
|
20
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
21
|
+
config: z.ZodOptional<z.ZodUnknown>;
|
|
22
|
+
}, z.z.core.$strip>;
|
|
23
|
+
declare const RuleMapSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
24
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
25
|
+
config: z.ZodOptional<z.ZodUnknown>;
|
|
26
|
+
}, z.z.core.$strip>>;
|
|
27
|
+
declare const PermSetConfig: z.ZodObject<{
|
|
28
|
+
preset: z.ZodEnum<typeof PermissionRiskLevelPresets>;
|
|
29
|
+
}, z.z.core.$strip>;
|
|
30
|
+
declare const PermSetMap: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
31
|
+
preset: z.ZodEnum<typeof PermissionRiskLevelPresets>;
|
|
32
|
+
}, z.z.core.$strip>>;
|
|
33
|
+
export declare const PolicyFileSchema: z.ZodObject<{
|
|
34
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
35
|
+
rules: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
36
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
37
|
+
config: z.ZodOptional<z.ZodUnknown>;
|
|
38
|
+
}, z.z.core.$strip>>>;
|
|
39
|
+
}, z.z.core.$strip>;
|
|
40
|
+
export declare const ProfilesPolicyFileSchema: z.ZodObject<{
|
|
41
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
42
|
+
rules: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
43
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
44
|
+
config: z.ZodOptional<z.ZodUnknown>;
|
|
45
|
+
}, z.z.core.$strip>>>;
|
|
46
|
+
profiles: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
47
|
+
preset: z.ZodEnum<typeof PermissionRiskLevelPresets>;
|
|
48
|
+
}, z.z.core.$strip>>;
|
|
49
|
+
}, z.z.core.$strip>;
|
|
50
|
+
export declare const PermSetsPolicyFileSchema: z.ZodObject<{
|
|
51
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
52
|
+
rules: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
53
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
54
|
+
config: z.ZodOptional<z.ZodUnknown>;
|
|
55
|
+
}, z.z.core.$strip>>>;
|
|
56
|
+
permissionSets: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
57
|
+
preset: z.ZodEnum<typeof PermissionRiskLevelPresets>;
|
|
58
|
+
}, z.z.core.$strip>>;
|
|
59
|
+
}, z.z.core.$strip>;
|
|
60
|
+
export declare const PermissionsConfigFileSchema: z.ZodObject<{
|
|
61
|
+
permissions: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
62
|
+
label: z.ZodOptional<z.ZodString>;
|
|
63
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
64
|
+
classification: z.ZodEnum<typeof PolicyRiskLevel>;
|
|
65
|
+
}, z.z.core.$strip>>;
|
|
66
|
+
}, z.z.core.$strip>;
|
|
67
|
+
export type PermissionsClassification = z.infer<typeof PermissionsClassificationSchema>;
|
|
68
|
+
export type NamedPermissionsClassification = z.infer<typeof NamedPermissionsClassificationSchema>;
|
|
69
|
+
export type PermsClassificationsMap = z.infer<typeof PermsClassificationsMapSchema>;
|
|
70
|
+
export type PermissionsConfig = z.infer<typeof PermissionsConfigFileSchema>;
|
|
71
|
+
export type PolicyRuleConfig = z.infer<typeof PolicyRuleConfigSchema>;
|
|
72
|
+
export type BasePolicyFileContent = z.infer<typeof PolicyFileSchema>;
|
|
73
|
+
export type ProfilesPolicyFileContent = z.infer<typeof ProfilesPolicyFileSchema>;
|
|
74
|
+
export type PermSetsPolicyFileContent = z.infer<typeof PermSetsPolicyFileSchema>;
|
|
75
|
+
export type PermissionSetConfig = z.infer<typeof PermSetConfig>;
|
|
76
|
+
export type PermissionSetLikeMap = z.infer<typeof PermSetMap>;
|
|
77
|
+
export type RuleMap = z.infer<typeof RuleMapSchema>;
|
|
78
|
+
export type ConfigFile<T> = {
|
|
79
|
+
filePath?: string;
|
|
80
|
+
content: T;
|
|
81
|
+
};
|
|
82
|
+
export type AuditRunConfigClassifications = {
|
|
83
|
+
[classificationName: string]: unknown;
|
|
84
|
+
userPermissions?: ConfigFile<PermissionsConfig>;
|
|
85
|
+
customPermissions?: ConfigFile<PermissionsConfig>;
|
|
86
|
+
};
|
|
87
|
+
export type AuditRunConfigPolicies = {
|
|
88
|
+
[policyName: string]: unknown;
|
|
89
|
+
Profiles?: ConfigFile<ProfilesPolicyFileContent>;
|
|
90
|
+
PermissionSets?: ConfigFile<PermSetsPolicyFileContent>;
|
|
91
|
+
ConnectedApps?: ConfigFile<BasePolicyFileContent>;
|
|
92
|
+
};
|
|
93
|
+
export type AuditRunConfig = {
|
|
94
|
+
[configType: string]: unknown;
|
|
95
|
+
classifications: AuditRunConfigClassifications;
|
|
96
|
+
policies: AuditRunConfigPolicies;
|
|
97
|
+
};
|
|
98
|
+
export declare function isPermissionsConfig(cls: unknown): cls is ConfigFile<PermissionsConfig>;
|
|
99
|
+
export declare function isPolicyConfig(cls: unknown): cls is ConfigFile<BasePolicyFileContent>;
|
|
100
|
+
export {};
|