Skip to content

Commit

Permalink
Added rate limiting to cves and notice
Browse files Browse the repository at this point in the history
  • Loading branch information
samhotep committed May 23, 2024
1 parent 50c1bcf commit 1b75163
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 59 deletions.
64 changes: 15 additions & 49 deletions webapp/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,12 +209,8 @@
app.add_url_rule("/navigation", view_func=navigation_nojs)
app.add_url_rule("/pro/dashboard", view_func=advantage_view)
app.add_url_rule("/pro/user-subscriptions", view_func=get_user_subscriptions)
app.add_url_rule(
"/pro/subscriptions.json", view_func=get_annotated_subscriptions
)
app.add_url_rule(
"/pro/contracts/<contract_id>/token", view_func=get_contract_token
)
app.add_url_rule("/pro/subscriptions.json", view_func=get_annotated_subscriptions)
app.add_url_rule("/pro/contracts/<contract_id>/token", view_func=get_contract_token)
app.add_url_rule("/pro/users", view_func=advantage_account_users_view)
app.add_url_rule("/pro/account-users", view_func=get_account_users)
app.add_url_rule(
Expand Down Expand Up @@ -245,9 +241,7 @@
view_func=post_auto_renewal_settings,
methods=["POST"],
)
app.add_url_rule(
"/pro/renewals/<renewal_id>", view_func=get_renewal, methods=["GET"]
)
app.add_url_rule("/pro/renewals/<renewal_id>", view_func=get_renewal, methods=["GET"])
app.add_url_rule(
"/pro/trial/<account_id>",
view_func=cancel_trial,
Expand Down Expand Up @@ -278,9 +272,7 @@
methods=["GET"],
)

app.add_url_rule(
"/pro/attach", view_func=activate_magic_attach, methods=["POST"]
)
app.add_url_rule("/pro/attach", view_func=activate_magic_attach, methods=["POST"])
app.add_url_rule("/pro/attach", view_func=magic_attach_view, methods=["GET"])
# shop
app.add_url_rule(
Expand Down Expand Up @@ -385,11 +377,7 @@
# end of shop

app.add_url_rule(
(
"/download"
"/<regex('server|desktop|cloud|raspberry-pi'):category>"
"/thank-you"
),
("/download" "/<regex('server|desktop|cloud|raspberry-pi'):category>" "/thank-you"),
view_func=download_thank_you,
)

Expand Down Expand Up @@ -523,9 +511,7 @@
view_func=build_engage_pages_sitemap(engage_pages),
)

app.add_url_rule(
"/openstack/resources", view_func=openstack_engage(engage_pages)
)
app.add_url_rule("/openstack/resources", view_func=openstack_engage(engage_pages))
# Custom engage page in German
app.add_url_rule(
"/engage/de/warum-openstack",
Expand Down Expand Up @@ -581,15 +567,9 @@ def takeovers_json():

def takeovers_index():
all_takeovers = discourse_takeovers.get_index()
all_takeovers.sort(
key=lambda takeover: takeover["active"] == "true", reverse=True
)
all_takeovers.sort(key=lambda takeover: takeover["active"] == "true", reverse=True)
active_count = len(
[
takeover
for takeover in all_takeovers
if takeover["active"] == "true"
]
[takeover for takeover in all_takeovers if takeover["active"] == "true"]
)

return flask.render_template(
Expand Down Expand Up @@ -718,15 +698,11 @@ def takeovers_index():
)
tutorials_docs.init_app(app)

app.add_url_rule(
"/tutorials.json", view_func=build_tutorials_query(tutorials_docs)
)
app.add_url_rule("/tutorials.json", view_func=build_tutorials_query(tutorials_docs))

# Ceph docs
ceph_docs = Docs(
parser=DocParser(
api=discourse_api, index_topic_id=17250, url_prefix="/ceph/docs"
),
parser=DocParser(api=discourse_api, index_topic_id=17250, url_prefix="/ceph/docs"),
document_template="/ceph/docs/document.html",
url_prefix="/ceph/docs",
blueprint_name="ceph",
Expand All @@ -748,9 +724,7 @@ def takeovers_index():

# Core docs
core_docs = Docs(
parser=DocParser(
api=discourse_api, index_topic_id=19764, url_prefix="/core/docs"
),
parser=DocParser(api=discourse_api, index_topic_id=19764, url_prefix="/core/docs"),
document_template="/core/docs/document.html",
url_prefix="/core/docs",
blueprint_name="core",
Expand Down Expand Up @@ -887,9 +861,7 @@ def takeovers_index():
app.add_url_rule("/credentials/shop/", view_func=cred_shop)
app.add_url_rule("/credentials/shop/<p>", view_func=cred_shop)
app.add_url_rule("/credentials/shop/keys", view_func=cred_shop_keys)
app.add_url_rule(
"/credentials/shop/order-thank-you", view_func=cred_shop_thank_you
)
app.add_url_rule("/credentials/shop/order-thank-you", view_func=cred_shop_thank_you)
app.add_url_rule(
"/credentials/shop/webhook_responses",
view_func=cred_shop_webhook_responses,
Expand Down Expand Up @@ -1105,17 +1077,13 @@ def takeovers_index():
# HPE blog section
def render_blogs():
blogs = BlogViews(
api=BlogAPI(
session=session, thumbnail_width=555, thumbnail_height=311
),
api=BlogAPI(session=session, thumbnail_width=555, thumbnail_height=311),
tag_ids=[4307],
per_page=3,
blog_title="HPE blogs",
)
hpe_articles = blogs.get_tag("hpe")
return flask.render_template(
"/hpe/index.html", blogs=hpe_articles["articles"]
)
return flask.render_template("/hpe/index.html", blogs=hpe_articles["articles"])


app.add_url_rule("/hpe", view_func=render_blogs)
Expand All @@ -1124,9 +1092,7 @@ def render_blogs():
# Supermicro blog section
def render_supermicro_blogs():
blogs = BlogViews(
api=BlogAPI(
session=session, thumbnail_width=555, thumbnail_height=311
),
api=BlogAPI(session=session, thumbnail_width=555, thumbnail_height=311),
tag_ids=[2247],
per_page=3,
blog_title="Supermicro blogs",
Expand Down
31 changes: 25 additions & 6 deletions webapp/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
import dateutil.parser
from slugify import slugify
from canonicalwebteam.http import CachedSession
from limits import storage, strategies, parse

memory_storage = storage.MemoryStorage()
fixed_window = strategies.MovingWindowRateLimiter(memory_storage)


logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -76,9 +80,9 @@ def get_navigation(path):
child_to_set_active = None

for child in nav_section["children"]:
if (
child["path"] == path and path.startswith(nav_section["path"])
) or (path.startswith(child["path"])):
if (child["path"] == path and path.startswith(nav_section["path"])) or (
path.startswith(child["path"])
):
# look for the closest patch match
if len(child["path"]) > longest_match_path:
longest_match_path = len(child["path"])
Expand Down Expand Up @@ -161,9 +165,7 @@ def get_json_feed(url, offset=0, limit=None):
json.JSONDecodeError,
requests.exceptions.RequestException,
) as fetch_error:
logger.warning(
"Error getting feed from {}: {}".format(url, str(fetch_error))
)
logger.warning("Error getting feed from {}: {}".format(url, str(fetch_error)))
return False

return content[offset:end]
Expand Down Expand Up @@ -195,3 +197,20 @@ def sort_by_key_and_ordered_list(list_to_sort, obj_key, ordered_list):
if item[obj_key] in ordered_list
else len(ordered_list),
)


def add_rate_limiting(request_limit="100/hour"):
# Rate limit requests to protect from spamming
# To adjust this rate visit
# https://limits.readthedocs.io/en/latest/quickstart.html#examples
def decorator(fn):
def wrapper(*args, **kwargs):
limit = parse(request_limit)
rate_limit = fixed_window.hit(limit)
if not rate_limit:
return flask.abort(429, f"The rate limit is: {request_limit}")
return fn(*args, **kwargs)

return wrapper

return decorator
8 changes: 4 additions & 4 deletions webapp/security/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from sortedcontainers import SortedDict

# Local
from webapp.context import api_session
from webapp.context import add_rate_limiting, api_session
from webapp.security.api import SecurityAPI

markdown_parser = Markdown(
Expand All @@ -35,7 +35,7 @@ def get_processed_details(notice):
pattern, r'<a href="/security/\g<0>">\g<0></a>', notice["description"]
)


@add_rate_limiting(request_limit="80/hour")
def notice(notice_id):
# Check if notice_id is a valid USN or LSN
if re.fullmatch(r"(USN|LSN|SSN)-\d{1,5}-\d{1,2}", notice_id):
Expand Down Expand Up @@ -116,7 +116,7 @@ def notice(notice_id):

return flask.render_template(template, notice=notice)


@add_rate_limiting(request_limit="80/hour")
def notices():
details = flask.request.args.get("details", type=str)
release = flask.request.args.get("release", type=str)
Expand Down Expand Up @@ -402,7 +402,7 @@ def cve_index():
selected_releases=selected_releases,
)


@add_rate_limiting(request_limit="80/hour")
def cve(cve_id):
"""
Retrieve and display an individual CVE details page
Expand Down

0 comments on commit 1b75163

Please sign in to comment.