@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
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import z from 'zod';
|
|
2
|
+
import { PermissionRiskLevelPresets, PolicyRiskLevel } from '../../policies/types.js';
|
|
3
|
+
const PermissionsClassificationSchema = z.object({
|
|
4
|
+
/** UI Label */
|
|
5
|
+
label: z.string().optional(),
|
|
6
|
+
/** An optional description to explain the classification */
|
|
7
|
+
reason: z.string().optional(),
|
|
8
|
+
/** Risk assessment of the permissions */
|
|
9
|
+
classification: z.enum(PolicyRiskLevel),
|
|
10
|
+
});
|
|
11
|
+
const PermsClassificationsMapSchema = z.record(z.string(), PermissionsClassificationSchema);
|
|
12
|
+
const NamedPermissionsClassificationSchema = PermissionsClassificationSchema.extend({
|
|
13
|
+
/** Developer name of the permission, used in metadata */
|
|
14
|
+
name: z.string(),
|
|
15
|
+
});
|
|
16
|
+
const PolicyRuleConfigSchema = z.object({
|
|
17
|
+
enabled: z.boolean().default(true),
|
|
18
|
+
config: z.unknown().optional(),
|
|
19
|
+
});
|
|
20
|
+
const RuleMapSchema = z.record(z.string(), PolicyRuleConfigSchema);
|
|
21
|
+
const PermSetConfig = z.object({
|
|
22
|
+
preset: z.enum(PermissionRiskLevelPresets),
|
|
23
|
+
});
|
|
24
|
+
const PermSetMap = z.record(z.string(), PermSetConfig);
|
|
25
|
+
// FILE CONTENT SCHEMATA
|
|
26
|
+
export const PolicyFileSchema = z.object({
|
|
27
|
+
enabled: z.boolean().default(true),
|
|
28
|
+
rules: RuleMapSchema.default({}),
|
|
29
|
+
});
|
|
30
|
+
export const ProfilesPolicyFileSchema = PolicyFileSchema.extend({
|
|
31
|
+
profiles: PermSetMap,
|
|
32
|
+
});
|
|
33
|
+
export const PermSetsPolicyFileSchema = PolicyFileSchema.extend({
|
|
34
|
+
permissionSets: PermSetMap,
|
|
35
|
+
});
|
|
36
|
+
export const PermissionsConfigFileSchema = z.object({
|
|
37
|
+
permissions: z.record(z.string(), PermissionsClassificationSchema),
|
|
38
|
+
});
|
|
39
|
+
export function isPermissionsConfig(cls) {
|
|
40
|
+
return cls.content?.permissions !== undefined;
|
|
41
|
+
}
|
|
42
|
+
export function isPolicyConfig(cls) {
|
|
43
|
+
return cls.content?.rules !== undefined;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../../src/libs/config/audit-run/schema.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,KAAK,CAAC;AACpB,OAAO,EAAE,0BAA0B,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAEtF,MAAM,+BAA+B,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/C,eAAe;IACf,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,4DAA4D;IAC5D,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,yCAAyC;IACzC,cAAc,EAAE,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC;CACxC,CAAC,CAAC;AAEH,MAAM,6BAA6B,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,+BAA+B,CAAC,CAAC;AAE5F,MAAM,oCAAoC,GAAG,+BAA+B,CAAC,MAAM,CAAC;IAClF,yDAAyD;IACzD,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;CACjB,CAAC,CAAC;AAEH,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IACtC,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAClC,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;CAC/B,CAAC,CAAC;AAEH,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,sBAAsB,CAAC,CAAC;AAEnE,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7B,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,0BAA0B,CAAC;CAC3C,CAAC,CAAC;AAEH,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,aAAa,CAAC,CAAC;AAEvD,wBAAwB;AAExB,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAClC,KAAK,EAAE,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;CACjC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,wBAAwB,GAAG,gBAAgB,CAAC,MAAM,CAAC;IAC9D,QAAQ,EAAE,UAAU;CACrB,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,wBAAwB,GAAG,gBAAgB,CAAC,MAAM,CAAC;IAC9D,cAAc,EAAE,UAAU;CAC3B,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAC,MAAM,CAAC;IAClD,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,+BAA+B,CAAC;CACnE,CAAC,CAAC;AA0CH,MAAM,UAAU,mBAAmB,CAAC,GAAY;IAC9C,OAAQ,GAAqC,CAAC,OAAO,EAAE,WAAW,KAAK,SAAS,CAAC;AACnF,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,GAAY;IACzC,OAAQ,GAAyC,CAAC,OAAO,EAAE,KAAK,KAAK,SAAS,CAAC;AACjF,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { Messages } from '@salesforce/core';
|
|
2
|
+
import { PolicyRiskLevel } from '../policies/types.js';
|
|
3
|
+
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
|
|
4
|
+
const messages = Messages.loadMessages('@j-schreiber/sf-cli-security-audit', 'policyclassifications');
|
|
5
|
+
export const DEFAULT_CLASSIFICATIONS = {
|
|
6
|
+
CustomizeApplication: {
|
|
7
|
+
classification: PolicyRiskLevel.CRITICAL,
|
|
8
|
+
reason: messages.getMessage('CustomizeApplication'),
|
|
9
|
+
},
|
|
10
|
+
ModifyMetadata: {
|
|
11
|
+
classification: PolicyRiskLevel.CRITICAL,
|
|
12
|
+
reason: messages.getMessage('CustomizeApplication'),
|
|
13
|
+
},
|
|
14
|
+
ViewSetup: {
|
|
15
|
+
classification: PolicyRiskLevel.HIGH,
|
|
16
|
+
reason: messages.getMessage('ViewSetup'),
|
|
17
|
+
},
|
|
18
|
+
AuthorApex: {
|
|
19
|
+
classification: PolicyRiskLevel.CRITICAL,
|
|
20
|
+
reason: messages.getMessage('AuthorApex'),
|
|
21
|
+
},
|
|
22
|
+
ManageAuthProviders: {
|
|
23
|
+
classification: PolicyRiskLevel.CRITICAL,
|
|
24
|
+
reason: messages.getMessage('ManageAuthProviders'),
|
|
25
|
+
},
|
|
26
|
+
Packaging2: {
|
|
27
|
+
classification: PolicyRiskLevel.CRITICAL,
|
|
28
|
+
reason: messages.getMessage('Packaging'),
|
|
29
|
+
},
|
|
30
|
+
Packaging2Delete: {
|
|
31
|
+
classification: PolicyRiskLevel.CRITICAL,
|
|
32
|
+
reason: messages.getMessage('Packaging'),
|
|
33
|
+
},
|
|
34
|
+
Packaging2PromoteVersion: {
|
|
35
|
+
classification: PolicyRiskLevel.CRITICAL,
|
|
36
|
+
reason: messages.getMessage('Packaging'),
|
|
37
|
+
},
|
|
38
|
+
InstallPackaging: {
|
|
39
|
+
classification: PolicyRiskLevel.CRITICAL,
|
|
40
|
+
reason: messages.getMessage('Packaging'),
|
|
41
|
+
},
|
|
42
|
+
ApiEnabled: {
|
|
43
|
+
classification: PolicyRiskLevel.HIGH,
|
|
44
|
+
reason: messages.getMessage('ApiEnabled'),
|
|
45
|
+
},
|
|
46
|
+
ViewAllData: {
|
|
47
|
+
classification: PolicyRiskLevel.HIGH,
|
|
48
|
+
reason: messages.getMessage('ViewAllData'),
|
|
49
|
+
},
|
|
50
|
+
ModifyAllData: {
|
|
51
|
+
classification: PolicyRiskLevel.HIGH,
|
|
52
|
+
reason: messages.getMessage('ViewAllData'),
|
|
53
|
+
},
|
|
54
|
+
ManageTwoFactor: {
|
|
55
|
+
classification: PolicyRiskLevel.HIGH,
|
|
56
|
+
reason: messages.getMessage('ManageTwoFactor'),
|
|
57
|
+
},
|
|
58
|
+
CanApproveUninstalledApps: {
|
|
59
|
+
classification: PolicyRiskLevel.HIGH,
|
|
60
|
+
reason: messages.getMessage('CanApproveUninstalledApps'),
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
//# sourceMappingURL=defaultPolicyClassification.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaultPolicyClassification.js","sourceRoot":"","sources":["../../../src/libs/config/defaultPolicyClassification.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAGvD,QAAQ,CAAC,kCAAkC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC7D,MAAM,QAAQ,GAAG,QAAQ,CAAC,YAAY,CAAC,oCAAoC,EAAE,uBAAuB,CAAC,CAAC;AAEtG,MAAM,CAAC,MAAM,uBAAuB,GAA8C;IAChF,oBAAoB,EAAE;QACpB,cAAc,EAAE,eAAe,CAAC,QAAQ;QACxC,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,sBAAsB,CAAC;KACpD;IACD,cAAc,EAAE;QACd,cAAc,EAAE,eAAe,CAAC,QAAQ;QACxC,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,sBAAsB,CAAC;KACpD;IACD,SAAS,EAAE;QACT,cAAc,EAAE,eAAe,CAAC,IAAI;QACpC,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC;KACzC;IACD,UAAU,EAAE;QACV,cAAc,EAAE,eAAe,CAAC,QAAQ;QACxC,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,YAAY,CAAC;KAC1C;IACD,mBAAmB,EAAE;QACnB,cAAc,EAAE,eAAe,CAAC,QAAQ;QACxC,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,qBAAqB,CAAC;KACnD;IACD,UAAU,EAAE;QACV,cAAc,EAAE,eAAe,CAAC,QAAQ;QACxC,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC;KACzC;IACD,gBAAgB,EAAE;QAChB,cAAc,EAAE,eAAe,CAAC,QAAQ;QACxC,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC;KACzC;IACD,wBAAwB,EAAE;QACxB,cAAc,EAAE,eAAe,CAAC,QAAQ;QACxC,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC;KACzC;IACD,gBAAgB,EAAE;QAChB,cAAc,EAAE,eAAe,CAAC,QAAQ;QACxC,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC;KACzC;IACD,UAAU,EAAE;QACV,cAAc,EAAE,eAAe,CAAC,IAAI;QACpC,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,YAAY,CAAC;KAC1C;IACD,WAAW,EAAE;QACX,cAAc,EAAE,eAAe,CAAC,IAAI;QACpC,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,aAAa,CAAC;KAC3C;IACD,aAAa,EAAE;QACb,cAAc,EAAE,eAAe,CAAC,IAAI;QACpC,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,aAAa,CAAC;KAC3C;IACD,eAAe,EAAE;QACf,cAAc,EAAE,eAAe,CAAC,IAAI;QACpC,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,iBAAiB,CAAC;KAC/C;IACD,yBAAyB,EAAE;QACzB,cAAc,EAAE,eAAe,CAAC,IAAI;QACpC,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,2BAA2B,CAAC;KACzD;CACF,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const CUSTOM_PERMS_QUERY = "SELECT Id,MasterLabel,DeveloperName FROM CustomPermission";
|
|
2
|
+
export declare const PROFILES_QUERY = "SELECT Profile.Name,Profile.UserType,IsCustom FROM PermissionSet WHERE IsOwnedByProfile = TRUE";
|
|
3
|
+
export declare const PERMISSION_SETS_QUERY = "SELECT Name,Label,IsCustom,NamespacePrefix FROM PermissionSet WHERE IsOwnedByProfile = FALSE AND NamespacePrefix = NULL";
|
|
4
|
+
export declare const CONNECTED_APPS_QUERY = "SELECT Name,OptionsAllowAdminApprovedUsersOnly FROM ConnectedApplication";
|
|
5
|
+
export declare const OAUTH_TOKEN_QUERY = "SELECT User.Username,UseCount,AppName FROM OauthToken";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export const CUSTOM_PERMS_QUERY = 'SELECT Id,MasterLabel,DeveloperName FROM CustomPermission';
|
|
2
|
+
export const PROFILES_QUERY = 'SELECT Profile.Name,Profile.UserType,IsCustom FROM PermissionSet WHERE IsOwnedByProfile = TRUE';
|
|
3
|
+
export const PERMISSION_SETS_QUERY = 'SELECT Name,Label,IsCustom,NamespacePrefix FROM PermissionSet WHERE IsOwnedByProfile = FALSE AND NamespacePrefix = NULL';
|
|
4
|
+
export const CONNECTED_APPS_QUERY = 'SELECT Name,OptionsAllowAdminApprovedUsersOnly FROM ConnectedApplication';
|
|
5
|
+
export const OAUTH_TOKEN_QUERY = 'SELECT User.Username,UseCount,AppName FROM OauthToken';
|
|
6
|
+
//# sourceMappingURL=queries.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queries.js","sourceRoot":"","sources":["../../../src/libs/config/queries.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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import AllUsedAppsUnderManagement from '../../policies/rules/allUsedAppsUnderManagement.js';
|
|
2
|
+
import NoUserCanSelfAuthorize from '../../policies/rules/noUserCanSelfAuthorize.js';
|
|
3
|
+
import RuleRegistry from './ruleRegistry.js';
|
|
4
|
+
export default class ConnectedAppsRuleRegistry extends RuleRegistry {
|
|
5
|
+
constructor() {
|
|
6
|
+
super({
|
|
7
|
+
AllUsedAppsUnderManagement,
|
|
8
|
+
NoUserCanSelfAuthorize,
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export const ConnectedAppsRegistry = new ConnectedAppsRuleRegistry();
|
|
13
|
+
//# sourceMappingURL=connectedApps.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connectedApps.js","sourceRoot":"","sources":["../../../../src/libs/config/registries/connectedApps.ts"],"names":[],"mappings":"AAAA,OAAO,0BAA0B,MAAM,oDAAoD,CAAC;AAC5F,OAAO,sBAAsB,MAAM,gDAAgD,CAAC;AACpF,OAAO,YAAY,MAAM,mBAAmB,CAAC;AAE7C,MAAM,CAAC,OAAO,OAAO,yBAA0B,SAAQ,YAAY;IACjE;QACE,KAAK,CAAC;YACJ,0BAA0B;YAC1B,sBAAsB;SACvB,CAAC,CAAC;IACL,CAAC;CACF;AAED,MAAM,CAAC,MAAM,qBAAqB,GAAG,IAAI,yBAAyB,EAAE,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import EnforceUserPermsClassificationOnPermSets from '../../policies/rules/enforceUserPermsClassificationOnPermSets.js';
|
|
2
|
+
import RuleRegistry from './ruleRegistry.js';
|
|
3
|
+
export default class PermSetsRuleRegistry extends RuleRegistry {
|
|
4
|
+
constructor() {
|
|
5
|
+
super({
|
|
6
|
+
EnforceUserPermissionClassifications: EnforceUserPermsClassificationOnPermSets,
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export const PermissionSetsRegistry = new PermSetsRuleRegistry();
|
|
11
|
+
//# sourceMappingURL=permissionSets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissionSets.js","sourceRoot":"","sources":["../../../../src/libs/config/registries/permissionSets.ts"],"names":[],"mappings":"AAAA,OAAO,wCAAwC,MAAM,kEAAkE,CAAC;AACxH,OAAO,YAAY,MAAM,mBAAmB,CAAC;AAE7C,MAAM,CAAC,OAAO,OAAO,oBAAqB,SAAQ,YAAY;IAC5D;QACE,KAAK,CAAC;YACJ,oCAAoC,EAAE,wCAAwC;SAC/E,CAAC,CAAC;IACL,CAAC;CACF;AAED,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,oBAAoB,EAAE,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import EnforceCustomPermsClassificationOnProfiles from '../../policies/rules/enforceCustomPermsClassificationOnProfiles.js';
|
|
2
|
+
import EnforceUserPermsClassificationOnProfiles from '../../policies/rules/enforceUserPermsClassificationOnProfiles.js';
|
|
3
|
+
import RuleRegistry from './ruleRegistry.js';
|
|
4
|
+
export default class ProfilesRuleRegistry extends RuleRegistry {
|
|
5
|
+
constructor() {
|
|
6
|
+
super({
|
|
7
|
+
EnforceCustomPermissionClassifications: EnforceCustomPermsClassificationOnProfiles,
|
|
8
|
+
EnforceUserPermissionClassifications: EnforceUserPermsClassificationOnProfiles,
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export const ProfilesRegistry = new ProfilesRuleRegistry();
|
|
13
|
+
//# sourceMappingURL=profiles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profiles.js","sourceRoot":"","sources":["../../../../src/libs/config/registries/profiles.ts"],"names":[],"mappings":"AAAA,OAAO,0CAA0C,MAAM,oEAAoE,CAAC;AAC5H,OAAO,wCAAwC,MAAM,kEAAkE,CAAC;AACxH,OAAO,YAAY,MAAM,mBAAmB,CAAC;AAE7C,MAAM,CAAC,OAAO,OAAO,oBAAqB,SAAQ,YAAY;IAC5D;QACE,KAAK,CAAC;YACJ,sCAAsC,EAAE,0CAA0C;YAClF,oCAAoC,EAAE,wCAAwC;SAC/E,CAAC,CAAC;IACL,CAAC;CACF;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,oBAAoB,EAAE,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { AuditRunConfig, RuleMap } from '../audit-run/schema.js';
|
|
2
|
+
import { RowLevelPolicyRule } from '../../policies/interfaces/policyRuleInterfaces.js';
|
|
3
|
+
import { RegistryRuleResolveResult } from './types.js';
|
|
4
|
+
type Constructor<T, Args extends any[] = any[]> = new (...args: Args) => T;
|
|
5
|
+
/**
|
|
6
|
+
* The rule registry holds all available rules for a given policy at run time.
|
|
7
|
+
* It is designed to be extendible so we can easily register new rules and it will
|
|
8
|
+
* allow users to BYOR ("bring your own rules").
|
|
9
|
+
*/
|
|
10
|
+
export default class RuleRegistry {
|
|
11
|
+
rules: Record<string, Constructor<RowLevelPolicyRule<unknown>>>;
|
|
12
|
+
constructor(rules: Record<string, Constructor<RowLevelPolicyRule<unknown>>>);
|
|
13
|
+
/**
|
|
14
|
+
* Returns the display/config names of all registered rules
|
|
15
|
+
*
|
|
16
|
+
* @returns
|
|
17
|
+
*/
|
|
18
|
+
registeredRules(): string[];
|
|
19
|
+
/**
|
|
20
|
+
* Resolves a given set of rule configs to actually registered rules. Unknown
|
|
21
|
+
* rules are ignored and disabled rules are skipped.
|
|
22
|
+
*
|
|
23
|
+
* @param ruleObjs
|
|
24
|
+
* @param auditContext
|
|
25
|
+
* @returns
|
|
26
|
+
*/
|
|
27
|
+
resolveRules(ruleObjs: RuleMap, auditContext: AuditRunConfig): RegistryRuleResolveResult;
|
|
28
|
+
}
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Messages } from '@salesforce/core';
|
|
2
|
+
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
|
|
3
|
+
const messages = Messages.loadMessages('@j-schreiber/sf-cli-security-audit', 'policies.general');
|
|
4
|
+
/**
|
|
5
|
+
* The rule registry holds all available rules for a given policy at run time.
|
|
6
|
+
* It is designed to be extendible so we can easily register new rules and it will
|
|
7
|
+
* allow users to BYOR ("bring your own rules").
|
|
8
|
+
*/
|
|
9
|
+
export default class RuleRegistry {
|
|
10
|
+
rules;
|
|
11
|
+
constructor(rules) {
|
|
12
|
+
this.rules = rules;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Returns the display/config names of all registered rules
|
|
16
|
+
*
|
|
17
|
+
* @returns
|
|
18
|
+
*/
|
|
19
|
+
registeredRules() {
|
|
20
|
+
return Object.keys(this.rules);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Resolves a given set of rule configs to actually registered rules. Unknown
|
|
24
|
+
* rules are ignored and disabled rules are skipped.
|
|
25
|
+
*
|
|
26
|
+
* @param ruleObjs
|
|
27
|
+
* @param auditContext
|
|
28
|
+
* @returns
|
|
29
|
+
*/
|
|
30
|
+
resolveRules(ruleObjs, auditContext) {
|
|
31
|
+
const enabledRules = new Array();
|
|
32
|
+
const skippedRules = new Array();
|
|
33
|
+
const resolveErrors = new Array();
|
|
34
|
+
Object.entries(ruleObjs).forEach(([ruleName, ruleConfig]) => {
|
|
35
|
+
if (this.rules[ruleName] && ruleConfig.enabled) {
|
|
36
|
+
enabledRules.push(new this.rules[ruleName]({ auditContext, ruleDisplayName: ruleName, ruleConfig: ruleConfig.config }));
|
|
37
|
+
}
|
|
38
|
+
else if (!ruleConfig.enabled) {
|
|
39
|
+
skippedRules.push({ name: ruleName, skipReason: messages.getMessage('skip-reason.rule-not-enabled') });
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
resolveErrors.push({ name: ruleName, message: messages.getMessage('resolve-error.rule-not-registered') });
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
return { enabledRules, skippedRules, resolveErrors };
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=ruleRegistry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ruleRegistry.js","sourceRoot":"","sources":["../../../../src/libs/config/registries/ruleRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAM5C,QAAQ,CAAC,kCAAkC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC7D,MAAM,QAAQ,GAAG,QAAQ,CAAC,YAAY,CAAC,oCAAoC,EAAE,kBAAkB,CAAC,CAAC;AAKjG;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,YAAY;IACL;IAA1B,YAA0B,KAA+D;QAA/D,UAAK,GAAL,KAAK,CAA0D;IAAG,CAAC;IAE7F;;;;OAIG;IACI,eAAe;QACpB,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC;IAED;;;;;;;OAOG;IACI,YAAY,CAAC,QAAiB,EAAE,YAA4B;QACjE,MAAM,YAAY,GAAG,IAAI,KAAK,EAA+B,CAAC;QAC9D,MAAM,YAAY,GAAG,IAAI,KAAK,EAAwB,CAAC;QACvD,MAAM,aAAa,GAAG,IAAI,KAAK,EAAsB,CAAC;QACtD,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,EAAE,UAAU,CAAC,EAAE,EAAE;YAC1D,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;gBAC/C,YAAY,CAAC,IAAI,CACf,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,YAAY,EAAE,eAAe,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC,CACrG,CAAC;YACJ,CAAC;iBAAM,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;gBAC/B,YAAY,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,CAAC,UAAU,CAAC,8BAA8B,CAAC,EAAE,CAAC,CAAC;YACzG,CAAC;iBAAM,CAAC;gBACN,aAAa,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,mCAAmC,CAAC,EAAE,CAAC,CAAC;YAC5G,CAAC;QACH,CAAC,CAAC,CAAC;QACH,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,CAAC;IACvD,CAAC;CACF"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { EntityResolveError, PolicyRuleSkipResult } from '../../audit/types.js';
|
|
2
|
+
import { RowLevelPolicyRule } from '../../policies/interfaces/policyRuleInterfaces.js';
|
|
3
|
+
export type RegistryRuleResolveResult = {
|
|
4
|
+
enabledRules: Array<RowLevelPolicyRule<unknown>>;
|
|
5
|
+
skippedRules: PolicyRuleSkipResult[];
|
|
6
|
+
resolveErrors: EntityResolveError[];
|
|
7
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/libs/config/registries/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Connection } from '@salesforce/core';
|
|
2
|
+
import { ConnectedAppSettings, PermissionSet } from '@jsforce/jsforce-node/lib/api/metadata.js';
|
|
3
|
+
export type PermissionSetMetadata = {
|
|
4
|
+
PermissionSet: PermissionSet;
|
|
5
|
+
};
|
|
6
|
+
export type ConnectedAppSettingsFileContent = {
|
|
7
|
+
ConnectedAppSettings: ConnectedAppSettings;
|
|
8
|
+
};
|
|
9
|
+
export default class MdapiRetriever {
|
|
10
|
+
private connection;
|
|
11
|
+
private readonly retrieveOptions;
|
|
12
|
+
constructor(connection: Connection);
|
|
13
|
+
retrievePermissionsets(componentNames: string[]): Promise<Record<string, PermissionSet>>;
|
|
14
|
+
retrieveConnectedAppSetting(): Promise<ConnectedAppSettings | undefined>;
|
|
15
|
+
private retrieve;
|
|
16
|
+
}
|
|
17
|
+
export declare function parseAsPermissionset(filePath: string): PermissionSet;
|
|
18
|
+
export declare function parseAsConnectedAppSetting(filePath: string): ConnectedAppSettings;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { ComponentSet } from '@salesforce/source-deploy-retrieve';
|
|
3
|
+
import { XMLParser } from 'fast-xml-parser';
|
|
4
|
+
const parser = new XMLParser({
|
|
5
|
+
isArray: (jpath) => ['userPermissions', 'fieldPermissions', 'customPermissions', 'classAccesses'].includes(jpath),
|
|
6
|
+
});
|
|
7
|
+
export default class MdapiRetriever {
|
|
8
|
+
connection;
|
|
9
|
+
retrieveOptions;
|
|
10
|
+
constructor(connection) {
|
|
11
|
+
this.connection = connection;
|
|
12
|
+
this.retrieveOptions = {
|
|
13
|
+
usernameOrConnection: this.connection,
|
|
14
|
+
output: '.jsc/retrieves',
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
async retrievePermissionsets(componentNames) {
|
|
18
|
+
const components = componentNames.map((cname) => ({ type: 'PermissionSet', fullName: cname }));
|
|
19
|
+
if (components.length === 0) {
|
|
20
|
+
return {};
|
|
21
|
+
}
|
|
22
|
+
const retrieveResult = await this.retrieve(components);
|
|
23
|
+
const result = {};
|
|
24
|
+
retrieveResult.components
|
|
25
|
+
.getSourceComponents()
|
|
26
|
+
.toArray()
|
|
27
|
+
.forEach((sourceComponent) => {
|
|
28
|
+
if (sourceComponent.xml) {
|
|
29
|
+
result[sourceComponent.name] = parseAsPermissionset(sourceComponent.xml);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
async retrieveConnectedAppSetting() {
|
|
35
|
+
const cmp = { type: 'Settings', fullName: 'ConnectedApp' };
|
|
36
|
+
const retrieveResult = await this.retrieve([cmp]);
|
|
37
|
+
if (retrieveResult.components.getSourceComponents().toArray().length === 1) {
|
|
38
|
+
const filePath = retrieveResult.components.getSourceComponents().toArray()[0].xml;
|
|
39
|
+
if (filePath) {
|
|
40
|
+
return parseAsConnectedAppSetting(filePath);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
async retrieve(components) {
|
|
46
|
+
const compSet = new ComponentSet(components);
|
|
47
|
+
const retrieveRequest = await compSet.retrieve(this.retrieveOptions);
|
|
48
|
+
const retrieveResult = await retrieveRequest.pollStatus();
|
|
49
|
+
return retrieveResult;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
export function parseAsPermissionset(filePath) {
|
|
53
|
+
const cmpSrcContent = readFileSync(filePath, 'utf-8');
|
|
54
|
+
return parser.parse(cmpSrcContent).PermissionSet;
|
|
55
|
+
}
|
|
56
|
+
export function parseAsConnectedAppSetting(filePath) {
|
|
57
|
+
const cmpSrcContent = readFileSync(filePath, 'utf-8');
|
|
58
|
+
return parser.parse(cmpSrcContent).ConnectedAppSettings;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=mdapiRetriever.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mdapiRetriever.js","sourceRoot":"","sources":["../../src/libs/mdapiRetriever.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import EventEmitter from 'node:events';
|
|
2
|
+
import { Connection } from '@salesforce/core';
|
|
3
|
+
import { AuditResult } from '../audit/types.js';
|
|
4
|
+
import { AuditRunConfig } from '../config/audit-run/schema.js';
|
|
5
|
+
import Policy from './policy.js';
|
|
6
|
+
type PolicyMap = Record<string, Policy>;
|
|
7
|
+
export declare function startAuditRun(directoryPath: string): AuditRun;
|
|
8
|
+
export type EntityResolveEvent = {
|
|
9
|
+
total: number;
|
|
10
|
+
resolved: number;
|
|
11
|
+
policyName: string;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Instance of an audit run that manages high-level operations
|
|
15
|
+
*/
|
|
16
|
+
export default class AuditRun extends EventEmitter {
|
|
17
|
+
configs: AuditRunConfig;
|
|
18
|
+
private executablePolicies?;
|
|
19
|
+
constructor(configs: AuditRunConfig);
|
|
20
|
+
/**
|
|
21
|
+
* Loads all policies, resolves entities and caches the results.
|
|
22
|
+
*
|
|
23
|
+
* @param targetOrgConnection
|
|
24
|
+
*/
|
|
25
|
+
resolve(targetOrgConnection: Connection): Promise<PolicyMap>;
|
|
26
|
+
/**
|
|
27
|
+
* Executes an initialised audit run. Resolves policies entities
|
|
28
|
+
* and executes all rules.
|
|
29
|
+
*
|
|
30
|
+
* @param targetOrgConnection
|
|
31
|
+
* @returns
|
|
32
|
+
*/
|
|
33
|
+
execute(targetCon: Connection): Promise<Omit<AuditResult, 'orgId'>>;
|
|
34
|
+
private loadPolicies;
|
|
35
|
+
}
|
|
36
|
+
export {};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// import fs from 'node:fs';
|
|
2
|
+
import EventEmitter from 'node:events';
|
|
3
|
+
import ProfilePolicy from './profilePolicy.js';
|
|
4
|
+
import PermissionSetPolicy from './permissionSetPolicy.js';
|
|
5
|
+
import ConnectedAppPolicy from './connectedAppPolicy.js';
|
|
6
|
+
import AuditConfig from './initialisation/auditConfig.js';
|
|
7
|
+
export function startAuditRun(directoryPath) {
|
|
8
|
+
const conf = AuditConfig.load(directoryPath);
|
|
9
|
+
return new AuditRun(conf);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Instance of an audit run that manages high-level operations
|
|
13
|
+
*/
|
|
14
|
+
export default class AuditRun extends EventEmitter {
|
|
15
|
+
configs;
|
|
16
|
+
executablePolicies;
|
|
17
|
+
constructor(configs) {
|
|
18
|
+
super();
|
|
19
|
+
this.configs = configs;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Loads all policies, resolves entities and caches the results.
|
|
23
|
+
*
|
|
24
|
+
* @param targetOrgConnection
|
|
25
|
+
*/
|
|
26
|
+
async resolve(targetOrgConnection) {
|
|
27
|
+
if (this.executablePolicies) {
|
|
28
|
+
return this.executablePolicies;
|
|
29
|
+
}
|
|
30
|
+
this.executablePolicies = this.loadPolicies(this.configs);
|
|
31
|
+
const resolveResultPromises = [];
|
|
32
|
+
Object.values(this.executablePolicies).forEach((executable) => {
|
|
33
|
+
resolveResultPromises.push(executable.resolve({ targetOrgConnection }));
|
|
34
|
+
});
|
|
35
|
+
await Promise.all(resolveResultPromises);
|
|
36
|
+
return this.executablePolicies;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Executes an initialised audit run. Resolves policies entities
|
|
40
|
+
* and executes all rules.
|
|
41
|
+
*
|
|
42
|
+
* @param targetOrgConnection
|
|
43
|
+
* @returns
|
|
44
|
+
*/
|
|
45
|
+
async execute(targetCon) {
|
|
46
|
+
this.executablePolicies = await this.resolve(targetCon);
|
|
47
|
+
const results = await runPolicies(this.executablePolicies, targetCon);
|
|
48
|
+
return {
|
|
49
|
+
auditDate: new Date().toISOString(),
|
|
50
|
+
isCompliant: isCompliant(results),
|
|
51
|
+
policies: results,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
loadPolicies(config) {
|
|
55
|
+
const pols = {};
|
|
56
|
+
if (config.policies.Profiles) {
|
|
57
|
+
pols.Profiles = new ProfilePolicy(config.policies.Profiles.content, config);
|
|
58
|
+
}
|
|
59
|
+
if (config.policies.PermissionSets) {
|
|
60
|
+
pols.PermissionSets = new PermissionSetPolicy(config.policies.PermissionSets.content, config);
|
|
61
|
+
}
|
|
62
|
+
if (config.policies.ConnectedApps) {
|
|
63
|
+
pols.ConnectedApps = new ConnectedAppPolicy(config.policies.ConnectedApps.content, config);
|
|
64
|
+
}
|
|
65
|
+
Object.entries(pols).forEach(([policyName, policy]) => {
|
|
66
|
+
policy.addListener('entityresolve', (resolveStats) => {
|
|
67
|
+
this.emit(`entityresolve-${policyName}`, { policyName, ...resolveStats });
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
return pols;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function isCompliant(results) {
|
|
74
|
+
const list = Object.values(results);
|
|
75
|
+
return list.reduce((prevVal, currentVal) => prevVal && currentVal.isCompliant, list[0].isCompliant);
|
|
76
|
+
}
|
|
77
|
+
async function runPolicies(policies, targetOrgConnection) {
|
|
78
|
+
const resultsArray = [];
|
|
79
|
+
const policiesList = [];
|
|
80
|
+
Object.entries(policies).forEach(([policyKey, executable]) => {
|
|
81
|
+
policiesList.push(policyKey);
|
|
82
|
+
resultsArray.push(executable.run({ targetOrgConnection }));
|
|
83
|
+
});
|
|
84
|
+
const arrayResult = await Promise.all(resultsArray);
|
|
85
|
+
const results = {};
|
|
86
|
+
arrayResult.forEach((policyResult) => {
|
|
87
|
+
const policyKey = policiesList[arrayResult.indexOf(policyResult)];
|
|
88
|
+
results[policyKey] = policyResult;
|
|
89
|
+
});
|
|
90
|
+
return results;
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=auditRun.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auditRun.js","sourceRoot":"","sources":["../../../src/libs/policies/auditRun.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import RuleRegistry from '../config/registries/ruleRegistry.js';
|
|
2
|
+
import { AuditRunConfig, BasePolicyFileContent } from '../config/audit-run/schema.js';
|
|
3
|
+
import { AuditContext } from './interfaces/policyRuleInterfaces.js';
|
|
4
|
+
import Policy, { ResolveEntityResult } from './policy.js';
|
|
5
|
+
export type ResolvedConnectedApp = {
|
|
6
|
+
name: string;
|
|
7
|
+
origin: 'Installed' | 'OauthToken' | 'Owned';
|
|
8
|
+
onlyAdminApprovedUsersAllowed: boolean;
|
|
9
|
+
overrideByApiSecurityAccess: boolean;
|
|
10
|
+
useCount: number;
|
|
11
|
+
users: string[];
|
|
12
|
+
};
|
|
13
|
+
export default class ConnectedAppPolicy extends Policy {
|
|
14
|
+
config: BasePolicyFileContent;
|
|
15
|
+
auditConfig: AuditRunConfig;
|
|
16
|
+
constructor(config: BasePolicyFileContent, auditConfig: AuditRunConfig, registry?: RuleRegistry);
|
|
17
|
+
protected resolveEntities(context: AuditContext): Promise<ResolveEntityResult>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import ConnectedAppsRuleRegistry from '../config/registries/connectedApps.js';
|
|
2
|
+
import { CONNECTED_APPS_QUERY, OAUTH_TOKEN_QUERY } from '../config/queries.js';
|
|
3
|
+
import MdapiRetriever from '../mdapiRetriever.js';
|
|
4
|
+
import Policy, { getTotal } from './policy.js';
|
|
5
|
+
export default class ConnectedAppPolicy extends Policy {
|
|
6
|
+
config;
|
|
7
|
+
auditConfig;
|
|
8
|
+
constructor(config, auditConfig, registry = new ConnectedAppsRuleRegistry()) {
|
|
9
|
+
super(config, auditConfig, registry);
|
|
10
|
+
this.config = config;
|
|
11
|
+
this.auditConfig = auditConfig;
|
|
12
|
+
}
|
|
13
|
+
// eslint-disable-next-line class-methods-use-this
|
|
14
|
+
async resolveEntities(context) {
|
|
15
|
+
const successfullyResolved = {};
|
|
16
|
+
const ignoredEntities = {};
|
|
17
|
+
const metadataApi = new MdapiRetriever(context.targetOrgConnection);
|
|
18
|
+
this.emit('entityresolve', {
|
|
19
|
+
total: 0,
|
|
20
|
+
resolved: 0,
|
|
21
|
+
});
|
|
22
|
+
const installedApps = await context.targetOrgConnection.query(CONNECTED_APPS_QUERY);
|
|
23
|
+
this.emit('entityresolve', {
|
|
24
|
+
total: installedApps.totalSize,
|
|
25
|
+
resolved: 0,
|
|
26
|
+
});
|
|
27
|
+
installedApps.records.forEach((installedApp) => {
|
|
28
|
+
successfullyResolved[installedApp.Name] = {
|
|
29
|
+
name: installedApp.Name,
|
|
30
|
+
origin: 'Installed',
|
|
31
|
+
onlyAdminApprovedUsersAllowed: installedApp.OptionsAllowAdminApprovedUsersOnly,
|
|
32
|
+
overrideByApiSecurityAccess: false,
|
|
33
|
+
useCount: 0,
|
|
34
|
+
users: [],
|
|
35
|
+
};
|
|
36
|
+
});
|
|
37
|
+
const usersOAuthToken = await context.targetOrgConnection.query(OAUTH_TOKEN_QUERY);
|
|
38
|
+
usersOAuthToken.records.forEach((token) => {
|
|
39
|
+
if (successfullyResolved[token.AppName] === undefined) {
|
|
40
|
+
successfullyResolved[token.AppName] = {
|
|
41
|
+
name: token.AppName,
|
|
42
|
+
origin: 'OauthToken',
|
|
43
|
+
onlyAdminApprovedUsersAllowed: false,
|
|
44
|
+
overrideByApiSecurityAccess: false,
|
|
45
|
+
useCount: token.UseCount,
|
|
46
|
+
users: [token.User.Username],
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
successfullyResolved[token.AppName].useCount += token.UseCount;
|
|
51
|
+
if (!successfullyResolved[token.AppName].users.includes(token.User.Username)) {
|
|
52
|
+
successfullyResolved[token.AppName].users.push(token.User.Username);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
this.emit('entityresolve', {
|
|
57
|
+
total: Object.keys(successfullyResolved).length,
|
|
58
|
+
resolved: 0,
|
|
59
|
+
});
|
|
60
|
+
let overrideByApiSecurityAccess = false;
|
|
61
|
+
const apiSecurityAccessSetting = await metadataApi.retrieveConnectedAppSetting();
|
|
62
|
+
if (apiSecurityAccessSetting && apiSecurityAccessSetting.enableAdminApprovedAppsOnly) {
|
|
63
|
+
overrideByApiSecurityAccess = true;
|
|
64
|
+
}
|
|
65
|
+
Object.values(successfullyResolved).forEach((conApp) => {
|
|
66
|
+
// eslint-disable-next-line no-param-reassign
|
|
67
|
+
conApp.overrideByApiSecurityAccess = overrideByApiSecurityAccess;
|
|
68
|
+
});
|
|
69
|
+
const result = { resolvedEntities: successfullyResolved, ignoredEntities: Object.values(ignoredEntities) };
|
|
70
|
+
this.emit('entityresolve', {
|
|
71
|
+
total: getTotal(result),
|
|
72
|
+
resolved: getTotal(result),
|
|
73
|
+
});
|
|
74
|
+
// also query from tooling, to get additional information info
|
|
75
|
+
return result;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=connectedAppPolicy.js.map
|