diff --git a/.gitlab/helper_functions.sh b/.gitlab/helper_functions.sh index b390d69a19a6..14fa385de567 100644 --- a/.gitlab/helper_functions.sh +++ b/.gitlab/helper_functions.sh @@ -75,3 +75,4 @@ sleep-with-progress() { local sleep_step=$((sleep_time / sleep_interval)) for ((i=0; i< sleep_step;i++)); do echo "${sleep_interval}";sleep "${sleep_interval}"; done | tqdm --total ${sleep_time} --unit seconds --leave --update --colour green -ncols ${columns} --desc "${sleep_message}" 1> /dev/null } + diff --git a/Packs/AbnormalSecurity/Integrations/AbnormalSecurityEventCollector/AbnormalSecurityEventCollector.py b/Packs/AbnormalSecurity/Integrations/AbnormalSecurityEventCollector/AbnormalSecurityEventCollector.py index e631d805de67..48e1a3236259 100644 --- a/Packs/AbnormalSecurity/Integrations/AbnormalSecurityEventCollector/AbnormalSecurityEventCollector.py +++ b/Packs/AbnormalSecurity/Integrations/AbnormalSecurityEventCollector/AbnormalSecurityEventCollector.py @@ -111,7 +111,7 @@ def main(): verify = params['verify'] proxy = params['proxy'] after = arg_to_datetime( - arg=params.get('after'), arg_name='after', required=True).strftime("%Y-%m-%dT%H:%M:%SZ") # type: ignore + arg='1 minute').strftime("%Y-%m-%dT%H:%M:%SZ") # type: ignore client = Client(base_url='https://api.abnormalplatform.com/v1', verify=verify, proxy=proxy, @@ -122,6 +122,7 @@ def main(): after = last_run command = demisto.command() + demisto.debug(f'Command being called is {command}') try: threats, last_run = get_events(client, after) if command == 'test-module': diff --git a/Packs/AbnormalSecurity/Integrations/AbnormalSecurityEventCollector/AbnormalSecurityEventCollector.yml b/Packs/AbnormalSecurity/Integrations/AbnormalSecurityEventCollector/AbnormalSecurityEventCollector.yml index 5e2477a5f5a4..c737e1bfc55e 100644 --- a/Packs/AbnormalSecurity/Integrations/AbnormalSecurityEventCollector/AbnormalSecurityEventCollector.yml +++ b/Packs/AbnormalSecurity/Integrations/AbnormalSecurityEventCollector/AbnormalSecurityEventCollector.yml @@ -17,6 +17,7 @@ configuration: type: 0 defaultvalue: 1 day required: false + hidden: true - display: Use system proxy settings name: proxy type: 8 @@ -40,7 +41,7 @@ script: - 'True' - 'False' required: true - dockerimage: demisto/python3:3.10.13.78960 + dockerimage: demisto/python3:3.10.14.92207 isfetchevents: true subtype: python3 fromversion: 6.8.0 diff --git a/Packs/AbnormalSecurity/ReleaseNotes/2_2_9.md b/Packs/AbnormalSecurity/ReleaseNotes/2_2_9.md new file mode 100644 index 000000000000..bb5855e7e7fe --- /dev/null +++ b/Packs/AbnormalSecurity/ReleaseNotes/2_2_9.md @@ -0,0 +1,7 @@ + +#### Integrations + +##### Abnormal Security Event Collector + +- Changed the default value for *First fetch time interval* parameter to 1 minute and hid it. +- Updated the Docker image to: *demisto/python3:3.10.14.92207*. \ No newline at end of file diff --git a/Packs/AbnormalSecurity/pack_metadata.json b/Packs/AbnormalSecurity/pack_metadata.json index 2cfeb69e8eee..291eeef562e5 100644 --- a/Packs/AbnormalSecurity/pack_metadata.json +++ b/Packs/AbnormalSecurity/pack_metadata.json @@ -2,7 +2,7 @@ "name": "Abnormal Security", "description": "Abnormal Security detects and protects against the whole spectrum of email attacks", "support": "partner", - "currentVersion": "2.2.8", + "currentVersion": "2.2.9", "author": "Abnormal Security", "url": "", "email": "support@abnormalsecurity.com", diff --git a/Packs/DomainTools_Iris/Integrations/DomainTools_Iris/DomainTools_Iris.py b/Packs/DomainTools_Iris/Integrations/DomainTools_Iris/DomainTools_Iris.py index 36a1bf973aa0..83593298d718 100644 --- a/Packs/DomainTools_Iris/Integrations/DomainTools_Iris/DomainTools_Iris.py +++ b/Packs/DomainTools_Iris/Integrations/DomainTools_Iris/DomainTools_Iris.py @@ -16,8 +16,8 @@ urllib3.disable_warnings() ''' GLOBALS ''' -USERNAME = demisto.params().get('username') -API_KEY = demisto.params().get('apikey') +USERNAME = demisto.params().get('credentials', {}).get('identifier') or demisto.params().get('username') +API_KEY = demisto.params().get('credentials', {}).get('password') or demisto.params().get('apikey') RISK_THRESHOLD = arg_to_number(demisto.params().get('risk_threshold')) or 70 YOUNG_DOMAIN_TIMEFRAME = arg_to_number(demisto.params().get('young_domain_timeframe')) or 7 VERIFY_CERT = not demisto.params().get('insecure', False) @@ -95,6 +95,8 @@ def http_request(method, params=None): """ proxy_url = PROXIES.get('https') if PROXIES.get('https') != '' else PROXIES.get('http') + if not (USERNAME and API_KEY): + raise DemistoException("The 'API Username' and 'API Key' parameters are required.") api = API( USERNAME, API_KEY, @@ -156,7 +158,7 @@ def prune_context_data(data_obj): items_to_prune = [] if isinstance(data_obj, dict) and len(data_obj): for k, v in data_obj.items(): - if isinstance(data_obj[k], dict) or isinstance(data_obj[k], list): + if isinstance(data_obj[k], dict | list): prune_context_data(data_obj[k]) if not isinstance(v, int) and not v: items_to_prune.append(k) @@ -288,8 +290,8 @@ def create_results(domain_result): 'Postal': contact_data.get('postal'), 'Org': contact_data.get('org') } - soa_email = [soa_email for soa_email in domain_result.get('soa_email')] - ssl_email = [ssl_email for ssl_email in domain_result.get('ssl_email')] + soa_email = list(domain_result.get('soa_email')) + ssl_email = list(domain_result.get('ssl_email')) email_domains = [email_domain.get('value') for email_domain in domain_result.get('email_domain')] additional_whois_emails = domain_result.get('additional_whois_email') domain_registrar = domain_result.get('registrar') @@ -369,12 +371,12 @@ def create_results(domain_result): registrar = domain_result.get('registrar') registrant_country = domain_result.get('registrant_contact', {}).get('country', {}).get('value') admin_name = domain_result.get('admin_contact', {}).get('name', {}).get('value') - admin_email = [email for email in domain_result.get('admin_contact', {}).get('email', [])] + admin_email = list(domain_result.get('admin_contact', {}).get('email', [])) admin_phone = domain_result.get('admin_contact', {}).get('phone', {}).get('value') admin_country = domain_result.get('admin_contact', {}).get('country', {}).get('value') threat_types = format_risk_grid(domain_result.get('domain_risk', {})) tech_name = domain_result.get('technical_contact', {}).get('name', {}).get('value') - tech_email = [email for email in domain_result.get('technical_contact', {}).get('email', [])] + tech_email = list(domain_result.get('technical_contact', {}).get('email', [])) tech_org = domain_result.get('technical_contact', {}).get('org', {}).get('value') tech_country = domain_result.get('technical_contact', {}).get('country', {}).get('value') rank = [Common.Rank(source="DomainTools Popularity Rank", rank=popularity_rank if popularity_rank else 'None')] diff --git a/Packs/DomainTools_Iris/Integrations/DomainTools_Iris/DomainTools_Iris.yml b/Packs/DomainTools_Iris/Integrations/DomainTools_Iris/DomainTools_Iris.yml index 293a2d88c6b7..b659570c02e0 100644 --- a/Packs/DomainTools_Iris/Integrations/DomainTools_Iris/DomainTools_Iris.yml +++ b/Packs/DomainTools_Iris/Integrations/DomainTools_Iris/DomainTools_Iris.yml @@ -3,13 +3,20 @@ commonfields: id: DomainTools Iris version: -1 configuration: +- display: API Username + name: credentials + type: 9 + required: false + displaypassword: API Key - display: API Username name: username - required: true + required: false + hidden: true type: 0 - display: API Key name: apikey - required: true + required: false + hidden: true type: 4 - display: High-Risk Threshold name: risk_threshold @@ -2403,7 +2410,7 @@ script: description: Parsed Whois data. - contextPath: Domain.WhoisRecords description: Full Whois record. - dockerimage: demisto/vendors-sdk:1.0.0.87491 + dockerimage: demisto/vendors-sdk:1.0.0.92984 runonce: false script: '-' type: python diff --git a/Packs/DomainTools_Iris/ReleaseNotes/2_0_2.md b/Packs/DomainTools_Iris/ReleaseNotes/2_0_2.md new file mode 100644 index 000000000000..ae9c1bab0fbf --- /dev/null +++ b/Packs/DomainTools_Iris/ReleaseNotes/2_0_2.md @@ -0,0 +1,7 @@ + +#### Integrations + +##### DomainTools Iris + +- Added support for credentials type. +- Updated the Docker image to: *demisto/vendors-sdk:1.0.0.92984*. diff --git a/Packs/DomainTools_Iris/pack_metadata.json b/Packs/DomainTools_Iris/pack_metadata.json index 82d93eba1c87..3255031c21c7 100644 --- a/Packs/DomainTools_Iris/pack_metadata.json +++ b/Packs/DomainTools_Iris/pack_metadata.json @@ -2,7 +2,7 @@ "name": "DomainTools Iris Investigate", "description": "Facilitates automation of key infrastructure characterization and hunting portions of the incident response process. Organizations will have access to essential domain profile, web crawl, SSL, and infrastructure data from within Cortex XSOAR. Requires a DomainTools Iris Investigate API key.", "support": "partner", - "currentVersion": "2.0.1", + "currentVersion": "2.0.2", "author": "DomainTools", "url": "https://www.domaintools.com/support/", "email": "memberservices@domaintools.com", diff --git a/Tests/Marketplace/approved_categories.json b/Tests/Marketplace/approved_categories.json new file mode 100644 index 000000000000..f84513ca155f --- /dev/null +++ b/Tests/Marketplace/approved_categories.json @@ -0,0 +1,21 @@ +{ + "description": "Approved categories for use in pack_metadata.json and integration yml. To modify this file you will need a CODEOWNER to approve. Please make sure to trigger the sdk build in case you edit this list.", + "approved_list": [ + "Analytics & SIEM", + "Case Management", + "Cloud Services", + "Data Enrichment & Threat Intelligence", + "Database", + "Deception & Breach Simulation", + "Endpoint", + "Forensics & Malware Analysis", + "IT Services", + "Identity and Access Management", + "Messaging and Conferencing", + "Network Security", + "Utilities", + "Vulnerability Management", + "Authentication & Identity Management", + "Email" + ] +} diff --git a/Tests/Marketplace/approved_tags.json b/Tests/Marketplace/approved_tags.json new file mode 100644 index 000000000000..428011ecd5a1 --- /dev/null +++ b/Tests/Marketplace/approved_tags.json @@ -0,0 +1,54 @@ +{ + "description": "Approved tags for use in pack_metadata.json. To modify this file you will need a CODEOWNER to approve.", + "approved_list": { + "common": [ + "Alerts", + "Attack", + "Breach", + "Breach Simulation", + "Core", + "Compliance", + "Dark Web", + "Email", + "Forensics", + "GDPR", + "Getting Started", + "HIPAA", + "IAM", + "Incident Handling", + "Incident Response", + "IoT", + "IT", + "Malware", + "Network", + "PII", + "Palo Alto Networks Products", + "Pcap", + "Scam", + "Security", + "Security Analytics", + "Private Offer", + "Simulation", + "TIM", + "Threat Intelligence", + "Threat Intelligence Management", + "VPN", + "MITRE ATT&CK", + "Unit 42", + "Use Case", + "New", + "Trending", + "Relationship", + "Elasticsearch", + "Free Feed", + "Plug & Fetch", + "Generic Feed", + "Allow List", + "Plug & Enrich", + "Free Enricher" + ], + "xsoar": [], + "marketplacev2": ["Data Source"], + "xpanse": ["Data Source"] + } +} diff --git a/Tests/Marketplace/approved_usecases.json b/Tests/Marketplace/approved_usecases.json new file mode 100644 index 000000000000..1eba66057fa7 --- /dev/null +++ b/Tests/Marketplace/approved_usecases.json @@ -0,0 +1,21 @@ +{ + "description": "Approved usecases for use in pack_metadata.json. To modify this file you will need a CODEOWNER to approve.", + "approved_list": [ + "Asset Management", + "Breach Notification", + "Breach and Attack Simulation", + "Case Management", + "Compliance", + "Health Check", + "Hunting", + "Identity and Access Management", + "Incident Response", + "Malware", + "Network Security", + "Phishing", + "Ransomware", + "SANS", + "Threat Intelligence Management", + "Vulnerability Management" + ] +} diff --git a/Utils/github_workflow_scripts/handle_external_pr.py b/Utils/github_workflow_scripts/handle_external_pr.py index ea125d92897a..e5f0f9ef5637 100755 --- a/Utils/github_workflow_scripts/handle_external_pr.py +++ b/Utils/github_workflow_scripts/handle_external_pr.py @@ -65,6 +65,7 @@ "Triggers" ] PR_AUTHOR_PATTERN = '## Contributor\n@(.*)' +LABELS_TO_SKIP_PR_REVIEW = {'contribution on hold'} def get_location_of_reviewer(assigned_prs_per_potential_reviewer: dict) -> int: @@ -93,6 +94,24 @@ def get_location_of_reviewer(assigned_prs_per_potential_reviewer: dict) -> int: return 0 +def skip_pr_from_count_for_reviewer(pr: PullRequest, pr_labels: list[str]) -> bool: + """ Checks if the current PR has the label "contribution on hold" or pr is in draft state, + if so - the PR won't be counted for the PR count to determine reviewer + + Args: + pr (PullRequest): The PR + pr_labels (list): The PR labels + + Returns: + bool: if PR need to be skipped + """ + pr_labels_set = set(pr_labels) + if pr.draft or LABELS_TO_SKIP_PR_REVIEW.issubset(pr_labels_set): + print(f'PR number {pr.number} with draft status {pr.draft} and labels {pr_labels_set} will be skipped from count ') + return True + return False + + def determine_random_reviewer(potential_reviewers: list[str], repo: Repository) -> str: """Checks the number of open 'Contribution' PRs that have been assigned to a user for each potential reviewer and returns the user with the smallest amount. @@ -111,7 +130,7 @@ def determine_random_reviewer(potential_reviewers: list[str], repo: Repository) for pull in pulls: # we only consider 'Contribution' prs when computing who to assign pr_labels = [label.name.casefold() for label in pull.labels] - if label_to_consider not in pr_labels: + if label_to_consider not in pr_labels or skip_pr_from_count_for_reviewer(pull, pr_labels): continue assignees = {assignee.login for assignee in pull.assignees} for reviewer in potential_reviewers: