Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update public date on oracle flaws to be 3rd Tuesday from Apr 2022 #32

Merged
merged 2 commits into from
Jul 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion advisory_parser/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
from .parser import Parser


__version__ = "1.12"
__version__ = "1.13"
78 changes: 59 additions & 19 deletions advisory_parser/parsers/mysql.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# Author: Martin Prpič, Red Hat Product Security
# License: LGPLv3+

import calendar
import re
from datetime import datetime, timedelta

Expand All @@ -14,6 +15,21 @@
MARIADB_VULN_PAGE = "https://mariadb.com/kb/en/security/"
VERSION_REGEX = re.compile(r"(\d\d?\.\d\.\d\d?)")

month_to_num = {
"jan": 1,
"feb": 2,
"mar": 3,
"apr": 4,
"may": 5,
"jun": 6,
"jul": 7,
"aug": 8,
"sep": 9,
"oct": 10,
"nov": 11,
"dec": 12,
}


def _nearest_tuesday(year, month, day=17):
"""For a given year and month, return nearest Tuesday to the 17th of that month
Expand All @@ -24,25 +40,8 @@ def _nearest_tuesday(year, month, day=17):
July and October."
[https://www.oracle.com/security-alerts/]
"""
month_to_num = {
"jan": 1,
"feb": 2,
"mar": 3,
"apr": 4,
"may": 5,
"jun": 6,
"jul": 7,
"aug": 8,
"sep": 9,
"oct": 10,
"nov": 11,
"dec": 12,
}

if month.lower() not in month_to_num:
raise AdvisoryParserTextException("Invalid month parsed from advisory URL:", str(month))

base_date = datetime(year, month_to_num[month.lower()], day)
base_date = datetime(year, month, day)

previous_tuesday = base_date - timedelta(days=((base_date.weekday() + 6) % 7))
next_tuesday = base_date + timedelta(days=((1 - base_date.weekday()) % 7))
Expand All @@ -54,6 +53,34 @@ def _nearest_tuesday(year, month, day=17):
)


def _third_tuesday(year, month):
"""For a given year and month, return the 3rd Tuesday of that month

"Critical Patch Updates provide security patches for supported Oracle on-premises products.
They are available to customers with valid support contracts. Starting in April 2022,
Critical Patch Updates are released on the third Tuesday of January, April, July, and October
(They were previously published on the Tuesday closest to the 17th day of January, April, July,
and October). The next four dates are:

16 July 2024
15 October 2024
21 January 2025
15 April 2025
"
[https://www.oracle.com/security-alerts/]
"""

c = calendar.Calendar()
monthcal = c.monthdatescalendar(year, month)
third_tuesday = [
day
for week in monthcal
for day in week
if day.weekday() == calendar.TUESDAY and day.month == month
][2]
return third_tuesday


def create_mariadb_cve_map():
# Pull plain text of the MariaDB page since the HTML is invalid: it
# doesn't define </li> ending tags for list elements. The HTML would
Expand Down Expand Up @@ -98,7 +125,20 @@ def parse_mysql_advisory(url):
# Extract the CPU's month and year from the URL since the verbose page has
# no dates on it
month, year = url_match.groups()
cpu_date = _nearest_tuesday(int(year), month)
if month.lower() not in month_to_num:
raise AdvisoryParserTextException("Invalid month parsed from advisory URL:", str(month))
month_num = month_to_num[month.lower()]
year_int = int(year)
# Starting in April 2022, Critical Patch Updates are released on the third Tuesday of January,
# April, July, and October (They were previously published on the Tuesday closest to the 17th
# day of January, April, July, and October).
# [https://www.oracle.com/security-alerts/]
if year_int < 2022:
cpu_date = _nearest_tuesday(year_int, month_num)
elif year_int == 2022 and month_num < 4:
cpu_date = _nearest_tuesday(year_int, month_num)
else:
cpu_date = _third_tuesday(year_int, month_num)
advisory_id = "CPU {} {}".format(month.capitalize(), year)

# Fetch the CPU verbose page
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

setup(
name="advisory-parser",
version="1.12",
version="1.13",
description="Security flaw parser for upstream security advisories",
long_description=description,
url="https://github.com/RedHatProductSecurity/advisory-parser",
Expand Down
36 changes: 25 additions & 11 deletions tests/test_mysql_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,42 @@
except ImportError:
from mock import patch

from advisory_parser.parsers.mysql import parse_mysql_advisory, _nearest_tuesday
from advisory_parser.parsers.mysql import parse_mysql_advisory, _nearest_tuesday, _third_tuesday


@pytest.mark.parametrize(
"year, month, day, expected_date",
[
(2017, "jul", 3, datetime(2017, 7, 4)),
(2017, "jul", 4, datetime(2017, 7, 4)), # Tuesday
(2017, "jul", 5, datetime(2017, 7, 4)),
(2017, "jul", 6, datetime(2017, 7, 4)),
(2017, "jul", 7, datetime(2017, 7, 4)),
(2017, "jul", 8, datetime(2017, 7, 11)),
(2017, "jul", 9, datetime(2017, 7, 11)),
(2017, "jul", 10, datetime(2017, 7, 11)),
(2017, "jul", 11, datetime(2017, 7, 11)), # Tuesday
(2017, "jul", 12, datetime(2017, 7, 11)),
(2017, 7, 3, datetime(2017, 7, 4)),
(2017, 7, 4, datetime(2017, 7, 4)), # Tuesday
(2017, 7, 5, datetime(2017, 7, 4)),
(2017, 7, 6, datetime(2017, 7, 4)),
(2017, 7, 7, datetime(2017, 7, 4)),
(2017, 7, 8, datetime(2017, 7, 11)),
(2017, 7, 9, datetime(2017, 7, 11)),
(2017, 7, 10, datetime(2017, 7, 11)),
(2017, 7, 11, datetime(2017, 7, 11)), # Tuesday
(2017, 7, 12, datetime(2017, 7, 11)),
],
)
def test_nearest_tuesday(year, month, day, expected_date):
assert expected_date == _nearest_tuesday(year, month, day)


@pytest.mark.parametrize(
"year, month, expected_date",
[
(2017, 7, datetime(2017, 7, 18).date()),
(2024, 7, datetime(2024, 7, 16).date()),
(2024, 10, datetime(2024, 10, 15).date()),
(2025, 1, datetime(2025, 1, 21).date()),
(2025, 4, datetime(2025, 4, 15).date()),
],
)
def test_third_tuesday(year, month, expected_date):
assert expected_date == _third_tuesday(year, month)


@patch("advisory_parser.parsers.mysql.get_request")
@patch("advisory_parser.parsers.mysql.create_mariadb_cve_map")
@pytest.mark.parametrize(
Expand Down
Loading