@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.
Files changed (103) hide show
  1. package/README.md +10 -2
  2. package/lib/commands/org/audit/init.d.ts +17 -0
  3. package/lib/commands/org/audit/init.js +61 -0
  4. package/lib/commands/org/audit/init.js.map +1 -0
  5. package/lib/commands/org/audit/run.d.ts +22 -0
  6. package/lib/commands/org/audit/run.js +113 -0
  7. package/lib/commands/org/audit/run.js.map +1 -0
  8. package/lib/libs/audit/types.d.ts +154 -0
  9. package/lib/libs/audit/types.js +2 -0
  10. package/lib/libs/audit/types.js.map +1 -0
  11. package/lib/libs/config/audit-run/auditConfigFileManager.d.ts +26 -0
  12. package/lib/libs/config/audit-run/auditConfigFileManager.js +98 -0
  13. package/lib/libs/config/audit-run/auditConfigFileManager.js.map +1 -0
  14. package/lib/libs/config/audit-run/schema.d.ts +100 -0
  15. package/lib/libs/config/audit-run/schema.js +45 -0
  16. package/lib/libs/config/audit-run/schema.js.map +1 -0
  17. package/lib/libs/config/defaultPolicyClassification.d.ts +2 -0
  18. package/lib/libs/config/defaultPolicyClassification.js +63 -0
  19. package/lib/libs/config/defaultPolicyClassification.js.map +1 -0
  20. package/lib/libs/config/queries.d.ts +5 -0
  21. package/lib/libs/config/queries.js +6 -0
  22. package/lib/libs/config/queries.js.map +1 -0
  23. package/lib/libs/config/registries/connectedApps.d.ts +5 -0
  24. package/lib/libs/config/registries/connectedApps.js +13 -0
  25. package/lib/libs/config/registries/connectedApps.js.map +1 -0
  26. package/lib/libs/config/registries/permissionSets.d.ts +5 -0
  27. package/lib/libs/config/registries/permissionSets.js +11 -0
  28. package/lib/libs/config/registries/permissionSets.js.map +1 -0
  29. package/lib/libs/config/registries/profiles.d.ts +5 -0
  30. package/lib/libs/config/registries/profiles.js +13 -0
  31. package/lib/libs/config/registries/profiles.js.map +1 -0
  32. package/lib/libs/config/registries/ruleRegistry.d.ts +29 -0
  33. package/lib/libs/config/registries/ruleRegistry.js +48 -0
  34. package/lib/libs/config/registries/ruleRegistry.js.map +1 -0
  35. package/lib/libs/config/registries/types.d.ts +7 -0
  36. package/lib/libs/config/registries/types.js +2 -0
  37. package/lib/libs/config/registries/types.js.map +1 -0
  38. package/lib/libs/mdapiRetriever.d.ts +18 -0
  39. package/lib/libs/mdapiRetriever.js +60 -0
  40. package/lib/libs/mdapiRetriever.js.map +1 -0
  41. package/lib/libs/policies/auditRun.d.ts +36 -0
  42. package/lib/libs/policies/auditRun.js +92 -0
  43. package/lib/libs/policies/auditRun.js.map +1 -0
  44. package/lib/libs/policies/connectedAppPolicy.d.ts +18 -0
  45. package/lib/libs/policies/connectedAppPolicy.js +78 -0
  46. package/lib/libs/policies/connectedAppPolicy.js.map +1 -0
  47. package/lib/libs/policies/initialisation/auditConfig.d.ts +27 -0
  48. package/lib/libs/policies/initialisation/auditConfig.js +41 -0
  49. package/lib/libs/policies/initialisation/auditConfig.js.map +1 -0
  50. package/lib/libs/policies/initialisation/permissionsClassification.d.ts +17 -0
  51. package/lib/libs/policies/initialisation/permissionsClassification.js +71 -0
  52. package/lib/libs/policies/initialisation/permissionsClassification.js.map +1 -0
  53. package/lib/libs/policies/initialisation/policyConfigs.d.ts +25 -0
  54. package/lib/libs/policies/initialisation/policyConfigs.js +67 -0
  55. package/lib/libs/policies/initialisation/policyConfigs.js.map +1 -0
  56. package/lib/libs/policies/interfaces/policyRuleInterfaces.d.ts +30 -0
  57. package/lib/libs/policies/interfaces/policyRuleInterfaces.js +2 -0
  58. package/lib/libs/policies/interfaces/policyRuleInterfaces.js.map +1 -0
  59. package/lib/libs/policies/permissionSetPolicy.d.ts +17 -0
  60. package/lib/libs/policies/permissionSetPolicy.js +61 -0
  61. package/lib/libs/policies/permissionSetPolicy.js.map +1 -0
  62. package/lib/libs/policies/policy.d.ts +32 -0
  63. package/lib/libs/policies/policy.js +95 -0
  64. package/lib/libs/policies/policy.js.map +1 -0
  65. package/lib/libs/policies/profilePolicy.d.ts +17 -0
  66. package/lib/libs/policies/profilePolicy.js +71 -0
  67. package/lib/libs/policies/profilePolicy.js.map +1 -0
  68. package/lib/libs/policies/rules/allUsedAppsUnderManagement.d.ts +7 -0
  69. package/lib/libs/policies/rules/allUsedAppsUnderManagement.js +23 -0
  70. package/lib/libs/policies/rules/allUsedAppsUnderManagement.js.map +1 -0
  71. package/lib/libs/policies/rules/enforceCustomPermsClassificationOnProfiles.d.ts +7 -0
  72. package/lib/libs/policies/rules/enforceCustomPermsClassificationOnProfiles.js +51 -0
  73. package/lib/libs/policies/rules/enforceCustomPermsClassificationOnProfiles.js.map +1 -0
  74. package/lib/libs/policies/rules/enforceUserPermsClassificationOnPermSets.d.ts +7 -0
  75. package/lib/libs/policies/rules/enforceUserPermsClassificationOnPermSets.js +51 -0
  76. package/lib/libs/policies/rules/enforceUserPermsClassificationOnPermSets.js.map +1 -0
  77. package/lib/libs/policies/rules/enforceUserPermsClassificationOnProfiles.d.ts +7 -0
  78. package/lib/libs/policies/rules/enforceUserPermsClassificationOnProfiles.js +53 -0
  79. package/lib/libs/policies/rules/enforceUserPermsClassificationOnProfiles.js.map +1 -0
  80. package/lib/libs/policies/rules/noUserCanSelfAuthorize.d.ts +7 -0
  81. package/lib/libs/policies/rules/noUserCanSelfAuthorize.js +31 -0
  82. package/lib/libs/policies/rules/noUserCanSelfAuthorize.js.map +1 -0
  83. package/lib/libs/policies/rules/policyRule.d.ts +16 -0
  84. package/lib/libs/policies/rules/policyRule.js +29 -0
  85. package/lib/libs/policies/rules/policyRule.js.map +1 -0
  86. package/lib/libs/policies/salesforceStandardTypes.d.ts +39 -0
  87. package/lib/libs/policies/salesforceStandardTypes.js +2 -0
  88. package/lib/libs/policies/salesforceStandardTypes.js.map +1 -0
  89. package/lib/libs/policies/types.d.ts +36 -0
  90. package/lib/libs/policies/types.js +45 -0
  91. package/lib/libs/policies/types.js.map +1 -0
  92. package/lib/libs/utils.d.ts +3 -0
  93. package/lib/libs/utils.js +13 -0
  94. package/lib/libs/utils.js.map +1 -0
  95. package/lib/ux/auditRunMultiStage.d.ts +65 -0
  96. package/lib/ux/auditRunMultiStage.js +117 -0
  97. package/lib/ux/auditRunMultiStage.js.map +1 -0
  98. package/messages/org.audit.init.md +1 -1
  99. package/messages/org.audit.run.md +0 -4
  100. package/messages/policies.general.md +12 -0
  101. package/messages/rules.connectedApps.md +11 -0
  102. package/oclif.manifest.json +159 -2
  103. 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,2 @@
1
+ import { PermissionsClassification } from './audit-run/schema.js';
2
+ export declare const DEFAULT_CLASSIFICATIONS: Record<string, PermissionsClassification>;
@@ -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,5 @@
1
+ import RuleRegistry from './ruleRegistry.js';
2
+ export default class ConnectedAppsRuleRegistry extends RuleRegistry {
3
+ constructor();
4
+ }
5
+ export declare const ConnectedAppsRegistry: ConnectedAppsRuleRegistry;
@@ -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,5 @@
1
+ import RuleRegistry from './ruleRegistry.js';
2
+ export default class PermSetsRuleRegistry extends RuleRegistry {
3
+ constructor();
4
+ }
5
+ export declare const PermissionSetsRegistry: PermSetsRuleRegistry;
@@ -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,5 @@
1
+ import RuleRegistry from './ruleRegistry.js';
2
+ export default class ProfilesRuleRegistry extends RuleRegistry {
3
+ constructor();
4
+ }
5
+ export declare const ProfilesRegistry: ProfilesRuleRegistry;
@@ -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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -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