1use crate::core::engine::Engine;
2use crate::rules::ats::{AtsAuditRule, AtsExceptionsGranularityRule};
3use crate::rules::bundle_leakage::BundleResourceLeakageRule;
4use crate::rules::bundle_metadata::BundleMetadataConsistencyRule;
5use crate::rules::core::AppStoreRule;
6use crate::rules::entitlements::{EntitlementsMismatchRule, EntitlementsProvisioningMismatchRule};
7use crate::rules::export_compliance::ExportComplianceRule;
8use crate::rules::extensions::ExtensionEntitlementsCompatibilityRule;
9use crate::rules::info_plist::{
10 InfoPlistCapabilitiesRule, InfoPlistRequiredKeysRule, InfoPlistVersionConsistencyRule,
11 LSApplicationQueriesSchemesAuditRule, UIRequiredDeviceCapabilitiesAuditRule,
12 UsageDescriptionsRule, UsageDescriptionsValueRule,
13};
14use crate::rules::permissions::CameraUsageDescriptionRule;
15use crate::rules::privacy::MissingPrivacyManifestRule;
16use crate::rules::privacy_manifest::PrivacyManifestCompletenessRule;
17use crate::rules::privacy_sdk::PrivacyManifestSdkCrossCheckRule;
18use crate::rules::private_api::PrivateApiRule;
19use crate::rules::signing::EmbeddedCodeSignatureTeamRule;
20use std::collections::HashSet;
21
22#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23pub enum ScanProfile {
24 Basic,
25 Full,
26}
27
28#[derive(Debug, Clone, Default)]
29pub struct RuleSelection {
30 pub include: HashSet<String>,
31 pub exclude: HashSet<String>,
32}
33
34impl RuleSelection {
35 pub fn allows(&self, rule_id: &str) -> bool {
36 let normalized = normalize_rule_id(rule_id);
37 let included = self.include.is_empty() || self.include.contains(&normalized);
38 let excluded = self.exclude.contains(&normalized);
39 included && !excluded
40 }
41}
42
43pub fn register_rules(engine: &mut Engine, profile: ScanProfile, selection: &RuleSelection) {
44 for rule in profile_rules(profile) {
45 if selection.allows(rule.id()) {
46 engine.register_rule(rule);
47 }
48 }
49}
50
51pub fn available_rule_ids(profile: ScanProfile) -> Vec<String> {
52 let mut ids: Vec<String> = profile_rules(profile)
53 .into_iter()
54 .map(|rule| normalize_rule_id(rule.id()))
55 .collect();
56 ids.sort();
57 ids.dedup();
58 ids
59}
60
61pub fn normalize_rule_id(rule_id: &str) -> String {
62 rule_id.trim().to_ascii_uppercase()
63}
64
65fn profile_rules(profile: ScanProfile) -> Vec<Box<dyn AppStoreRule>> {
66 match profile {
67 ScanProfile::Basic => basic_rules(),
68 ScanProfile::Full => full_rules(),
69 }
70}
71
72fn basic_rules() -> Vec<Box<dyn AppStoreRule>> {
73 vec![
74 Box::new(MissingPrivacyManifestRule),
75 Box::new(UsageDescriptionsRule),
76 Box::new(UsageDescriptionsValueRule),
77 Box::new(CameraUsageDescriptionRule),
78 Box::new(AtsAuditRule),
79 Box::new(AtsExceptionsGranularityRule),
80 Box::new(EntitlementsMismatchRule),
81 Box::new(EntitlementsProvisioningMismatchRule),
82 Box::new(EmbeddedCodeSignatureTeamRule),
83 ]
84}
85
86fn full_rules() -> Vec<Box<dyn AppStoreRule>> {
87 vec![
88 Box::new(MissingPrivacyManifestRule),
89 Box::new(PrivacyManifestCompletenessRule),
90 Box::new(PrivacyManifestSdkCrossCheckRule),
91 Box::new(CameraUsageDescriptionRule),
92 Box::new(UsageDescriptionsRule),
93 Box::new(UsageDescriptionsValueRule),
94 Box::new(InfoPlistRequiredKeysRule),
95 Box::new(InfoPlistCapabilitiesRule),
96 Box::new(LSApplicationQueriesSchemesAuditRule),
97 Box::new(UIRequiredDeviceCapabilitiesAuditRule),
98 Box::new(InfoPlistVersionConsistencyRule),
99 Box::new(ExportComplianceRule),
100 Box::new(AtsAuditRule),
101 Box::new(AtsExceptionsGranularityRule),
102 Box::new(EntitlementsMismatchRule),
103 Box::new(EntitlementsProvisioningMismatchRule),
104 Box::new(BundleMetadataConsistencyRule),
105 Box::new(BundleResourceLeakageRule),
106 Box::new(ExtensionEntitlementsCompatibilityRule),
107 Box::new(PrivateApiRule),
108 Box::new(EmbeddedCodeSignatureTeamRule),
109 ]
110}