diff --git a/manage.py b/manage.py index 166d3e72..56375771 100755 --- a/manage.py +++ b/manage.py @@ -10,6 +10,7 @@ import subprocess import sys from collections import defaultdict +from datetime import UTC, datetime, timedelta from email.parser import Parser from email.policy import default from itertools import islice @@ -294,6 +295,57 @@ def zones(api_token, defaults): print_resources(resources, disabled=disabled, default=default) +@cloudflare.command() +@api_token_option +@click.option("--hours", type=int, default=24, help="Hours of events to query") +@click.option("--limit", type=int, default=10000, help="Maximum events per zone") +def events(api_token, hours, limit): + """Print firewall events, one JSON object per line.""" + since = (datetime.now(tz=UTC) - timedelta(hours=hours)).strftime("%Y-%m-%dT%H:%M:%SZ") + fields = ( + "datetime action source ruleId edgeResponseStatus userAgent " + "clientIP clientAsn clientCountryName clientRequestHTTPHost clientRequestHTTPMethodName clientRequestPath" + ) + + for zone in Cloudflare(api_token=api_token).zones.list(): + # https://developers.cloudflare.com/waf/analytics/security-events/#query-using-graphql + query = f"""{{ + viewer {{ + zones(filter: {{zoneTag: "{zone.id}"}}) {{ + firewallEventsAdaptive( + filter: {{datetime_gt: "{since}"}} + limit: {limit} + orderBy: [datetime_DESC] + ) {{ + {fields} + }} + }} + }} + }}""" + + response = requests.post( + "https://api.cloudflare.com/client/v4/graphql", + headers={"Authorization": f"Bearer {api_token}"}, + json={"query": query}, + timeout=10, + ) + response.raise_for_status() + data = response.json() + + # "A 200 response can contain an error." + # https://developers.cloudflare.com/analytics/graphql-api/errors/ + if errors := data.get("errors"): + for error in errors: + click.secho(f"{zone.name}: {error['message']}", fg="red", err=True) + continue + + for result in data["data"]["viewer"]["zones"]: + if len(result["firewallEventsAdaptive"]) == limit: + click.secho(f"{zone.name}: {limit} limit reached (requires pagination code)", fg="yellow", err=True) + for event in result["firewallEventsAdaptive"]: + click.echo(json.dumps({"zone": zone.name, **event})) + + @cloudflare.command() @api_token_option @account_id_option diff --git a/salt/apache/files/sites/docs.conf.include b/salt/apache/files/sites/docs.conf.include index 915599fe..51d5cc7c 100644 --- a/salt/apache/files/sites/docs.conf.include +++ b/salt/apache/files/sites/docs.conf.include @@ -237,50 +237,50 @@ RewriteRule . %1/%2 [R=301,L] #################### # Extensions -RedirectMatch ^/{{ version }}/{{ lang }}/extensions/community/? https://extensions.open-contracting.org/{{ lang }}/extensions/ -RedirectMatch ^/{{ version }}/{{ lang }}/extensions/developing/? https://extensions.open-contracting.org/{{ lang }}/extensions/ -RedirectMatch ^/{{ version }}/{{ lang }}/extensions/party_details/? https://extensions.open-contracting.org/{{ lang }}/extensions/ -RedirectMatch ^/{{ version }}/{{ lang }}/extensions/bids/? https://extensions.open-contracting.org/{{ lang }}/extensions/bids/ -RedirectMatch ^/{{ version }}/{{ lang }}/extensions/enquiries/? https://extensions.open-contracting.org/{{ lang }}/extensions/enquiries/ -RedirectMatch ^/{{ version }}/{{ lang }}/extensions/location/? https://extensions.open-contracting.org/{{ lang }}/extensions/location/ -RedirectMatch ^/{{ version }}/{{ lang }}/extensions/lots/? https://extensions.open-contracting.org/{{ lang }}/extensions/lots/ -RedirectMatch ^/{{ version }}/{{ lang }}/extensions/participation_fee/? https://extensions.open-contracting.org/{{ lang }}/extensions/participation_fee/ -RedirectMatch ^/{{ version }}/{{ lang }}/extensions/process_title/? https://extensions.open-contracting.org/{{ lang }}/extensions/process_title/ +RedirectMatch ^/{{ version }}/{{ lang }}/extensions/community/?$ https://extensions.open-contracting.org/{{ lang }}/extensions/ +RedirectMatch ^/{{ version }}/{{ lang }}/extensions/developing/?$ https://extensions.open-contracting.org/{{ lang }}/extensions/ +RedirectMatch ^/{{ version }}/{{ lang }}/extensions/party_details/?$ https://extensions.open-contracting.org/{{ lang }}/extensions/ +RedirectMatch ^/{{ version }}/{{ lang }}/extensions/bids/?$ https://extensions.open-contracting.org/{{ lang }}/extensions/bids/ +RedirectMatch ^/{{ version }}/{{ lang }}/extensions/enquiries/?$ https://extensions.open-contracting.org/{{ lang }}/extensions/enquiries/ +RedirectMatch ^/{{ version }}/{{ lang }}/extensions/location/?$ https://extensions.open-contracting.org/{{ lang }}/extensions/location/ +RedirectMatch ^/{{ version }}/{{ lang }}/extensions/lots/?$ https://extensions.open-contracting.org/{{ lang }}/extensions/lots/ +RedirectMatch ^/{{ version }}/{{ lang }}/extensions/participation_fee/?$ https://extensions.open-contracting.org/{{ lang }}/extensions/participation_fee/ +RedirectMatch ^/{{ version }}/{{ lang }}/extensions/process_title/?$ https://extensions.open-contracting.org/{{ lang }}/extensions/process_title/ # Iterative improvements from OCDS 1.1.4 and up -RedirectMatch ^/{{ version }}/{{ lang }}/getting_started/building_blocks/? /{{ version }}/{{ lang }}/primer/how/ -RedirectMatch ^/{{ version }}/{{ lang }}/getting_started/contracting_process/? /{{ version }}/{{ lang }}/primer/how/ -RedirectMatch ^/{{ version }}/{{ lang }}/getting_started/publication_patterns/? /{{ version }}/{{ lang }}/guidance/build/hosting/ -RedirectMatch ^/{{ version }}/{{ lang }}/getting_started/quality/? /{{ version }}/{{ lang }}/guidance/publish/quality/ -RedirectMatch ^/{{ version }}/{{ lang }}/getting_started/releases_and_records/? /{{ version }}/{{ lang }}/primer/releases_and_records/ -RedirectMatch ^/{{ version }}/{{ lang }}/getting_started/use_cases/? /{{ version }}/{{ lang }}/guidance/design/user_needs/ -RedirectMatch ^/{{ version }}/{{ lang }}/getting_started/validation/? /{{ version }}/{{ lang }}/guidance/build/#check-your-data -RedirectMatch ^/{{ version }}/{{ lang }}/getting_started/? /{{ version }}/{{ lang }}/primer/ -RedirectMatch ^/{{ version }}/{{ lang }}/guidance/map/awards_contracts_buyers_suppliers/? /{{ version }}/{{ lang }}/guidance/map/awards_contracts/ -RedirectMatch ^/{{ version }}/{{ lang }}/guidance/map/award_notices_decisions/? /{{ version }}/{{ lang }}/guidance/map/awards_contracts/#awards-and-award-notices -RedirectMatch ^/{{ version }}/{{ lang }}/guidance/map/mapping_awards_contracts/? /{{ version }}/{{ lang }}/guidance/map/awards_contracts/#awards-and-contracts -RedirectMatch ^/{{ version }}/{{ lang }}/guidance/map/purchase_orders/? /{{ version }}/{{ lang }}/guidance/map/awards_contracts/#purchase-orders -RedirectMatch ^/{{ version }}/{{ lang }}/guidance/map/consortia/? /{{ version }}/{{ lang }}/guidance/map/buyers_suppliers/#consortia-suppliers -RedirectMatch ^/{{ version }}/{{ lang }}/guidance/map/frameworks/? /{{ version }}/{{ lang }}/guidance/map/framework_agreements/ -RedirectMatch ^/{{ version }}/{{ lang }}/guidance/map/related_processes/? /{{ version }}/{{ lang }}/guidance/map/framework_agreements/ -RedirectMatch ^/{{ version }}/{{ lang }}/guidance/map/unsuccessful_tender/? /{{ version }}/{{ lang }}/guidance/map/unsuccessful_processes/ -RedirectMatch ^/{{ version }}/{{ lang }}/guidance/map/catalogs/? /{{ version }}/{{ lang }}/guidance/map/electronic_catalogues/ -RedirectMatch ^/{{ version }}/{{ lang }}/extensions/? /{{ version }}/{{ lang }}/guidance/map/extensions/ -RedirectMatch ^/{{ version }}/{{ lang }}/implementation/amendments/? /{{ version }}/{{ lang }}/guidance/map/amendments/ -RedirectMatch ^/{{ version }}/{{ lang }}/implementation/hosting/? /{{ version }}/{{ lang }}/guidance/build/hosting/ -RedirectMatch ^/{{ version }}/{{ lang }}/implementation/levels/? /{{ version }}/{{ lang }}/guidance/publish/quality/ -RedirectMatch ^/{{ version }}/{{ lang }}/implementation/licensing/? /{{ version }}/{{ lang }}/guidance/publish/#license-your-data -RedirectMatch ^/{{ version }}/{{ lang }}/implementation/publication_policy/? /{{ version }}/{{ lang }}/guidance/publish/#finalize-your-publication-policy -RedirectMatch ^/{{ version }}/{{ lang }}/implementation/registration/? /{{ version }}/{{ lang }}/guidance/build/#register-an-ocid-prefix -RedirectMatch ^/{{ version }}/{{ lang }}/implementation/related_processes/? /{{ version }}/{{ lang }}/guidance/map/framework_agreements/ -RedirectMatch ^/{{ version }}/{{ lang }}/implementation/serialization/? /{{ version }}/{{ lang }}/guidance/build/serialization/ -RedirectMatch ^/{{ version }}/{{ lang }}/implementation/? /{{ version }}/{{ lang }}/guidance/ -RedirectMatch ^/{{ version }}/{{ lang }}/schema/changelog/? /{{ version }}/{{ lang }}/history/changelog/ -RedirectMatch ^/{{ version }}/{{ lang }}/schema/deprecation/? /{{ version }}/{{ lang }}/governance/deprecation/ -RedirectMatch ^/{{ version }}/{{ lang }}/support/credits/? /{{ version }}/{{ lang }}/history/history_and_development/#appreciation -RedirectMatch ^/{{ version }}/{{ lang }}/support/governance/? /{{ version }}/{{ lang }}/governance/ -RedirectMatch ^/{{ version }}/{{ lang }}/support/history_and_development/? /{{ version }}/{{ lang }}/history/history_and_development/ -RedirectMatch ^/{{ version }}/{{ lang }}/support/tools/? /{{ version }}/{{ lang }}/support/#ocds-tools +RedirectMatch ^/{{ version }}/{{ lang }}/getting_started/building_blocks/?$ /{{ version }}/{{ lang }}/primer/how/ +RedirectMatch ^/{{ version }}/{{ lang }}/getting_started/contracting_process/?$ /{{ version }}/{{ lang }}/primer/how/ +RedirectMatch ^/{{ version }}/{{ lang }}/getting_started/publication_patterns/?$ /{{ version }}/{{ lang }}/guidance/build/hosting/ +RedirectMatch ^/{{ version }}/{{ lang }}/getting_started/quality/?$ /{{ version }}/{{ lang }}/guidance/publish/quality/ +RedirectMatch ^/{{ version }}/{{ lang }}/getting_started/releases_and_records/?$ /{{ version }}/{{ lang }}/primer/releases_and_records/ +RedirectMatch ^/{{ version }}/{{ lang }}/getting_started/use_cases/?$ /{{ version }}/{{ lang }}/guidance/design/user_needs/ +RedirectMatch ^/{{ version }}/{{ lang }}/getting_started/validation/?$ /{{ version }}/{{ lang }}/guidance/build/#check-your-data +RedirectMatch ^/{{ version }}/{{ lang }}/getting_started/?$ /{{ version }}/{{ lang }}/primer/ +RedirectMatch ^/{{ version }}/{{ lang }}/guidance/map/awards_contracts_buyers_suppliers/?$ /{{ version }}/{{ lang }}/guidance/map/awards_contracts/ +RedirectMatch ^/{{ version }}/{{ lang }}/guidance/map/award_notices_decisions/?$ /{{ version }}/{{ lang }}/guidance/map/awards_contracts/#awards-and-award-notices +RedirectMatch ^/{{ version }}/{{ lang }}/guidance/map/mapping_awards_contracts/?$ /{{ version }}/{{ lang }}/guidance/map/awards_contracts/#awards-and-contracts +RedirectMatch ^/{{ version }}/{{ lang }}/guidance/map/purchase_orders/?$ /{{ version }}/{{ lang }}/guidance/map/awards_contracts/#purchase-orders +RedirectMatch ^/{{ version }}/{{ lang }}/guidance/map/consortia/?$ /{{ version }}/{{ lang }}/guidance/map/buyers_suppliers/#consortia-suppliers +RedirectMatch ^/{{ version }}/{{ lang }}/guidance/map/frameworks/?$ /{{ version }}/{{ lang }}/guidance/map/framework_agreements/ +RedirectMatch ^/{{ version }}/{{ lang }}/guidance/map/related_processes/?$ /{{ version }}/{{ lang }}/guidance/map/framework_agreements/ +RedirectMatch ^/{{ version }}/{{ lang }}/guidance/map/unsuccessful_tender/?$ /{{ version }}/{{ lang }}/guidance/map/unsuccessful_processes/ +RedirectMatch ^/{{ version }}/{{ lang }}/guidance/map/catalogs/?$ /{{ version }}/{{ lang }}/guidance/map/electronic_catalogues/ +RedirectMatch ^/{{ version }}/{{ lang }}/extensions/?$ /{{ version }}/{{ lang }}/guidance/map/extensions/ +RedirectMatch ^/{{ version }}/{{ lang }}/implementation/amendments/?$ /{{ version }}/{{ lang }}/guidance/map/amendments/ +RedirectMatch ^/{{ version }}/{{ lang }}/implementation/hosting/?$ /{{ version }}/{{ lang }}/guidance/build/hosting/ +RedirectMatch ^/{{ version }}/{{ lang }}/implementation/levels/?$ /{{ version }}/{{ lang }}/guidance/publish/quality/ +RedirectMatch ^/{{ version }}/{{ lang }}/implementation/licensing/?$ /{{ version }}/{{ lang }}/guidance/publish/#license-your-data +RedirectMatch ^/{{ version }}/{{ lang }}/implementation/publication_policy/?$ /{{ version }}/{{ lang }}/guidance/publish/#finalize-your-publication-policy +RedirectMatch ^/{{ version }}/{{ lang }}/implementation/registration/?$ /{{ version }}/{{ lang }}/guidance/build/#register-an-ocid-prefix +RedirectMatch ^/{{ version }}/{{ lang }}/implementation/related_processes/?$ /{{ version }}/{{ lang }}/guidance/map/framework_agreements/ +RedirectMatch ^/{{ version }}/{{ lang }}/implementation/serialization/?$ /{{ version }}/{{ lang }}/guidance/build/serialization/ +RedirectMatch ^/{{ version }}/{{ lang }}/implementation/?$ /{{ version }}/{{ lang }}/guidance/ +RedirectMatch ^/{{ version }}/{{ lang }}/schema/changelog/?$ /{{ version }}/{{ lang }}/history/changelog/ +RedirectMatch ^/{{ version }}/{{ lang }}/schema/deprecation/?$ /{{ version }}/{{ lang }}/governance/deprecation/ +RedirectMatch ^/{{ version }}/{{ lang }}/support/credits/?$ /{{ version }}/{{ lang }}/history/history_and_development/#appreciation +RedirectMatch ^/{{ version }}/{{ lang }}/support/governance/?$ /{{ version }}/{{ lang }}/governance/ +RedirectMatch ^/{{ version }}/{{ lang }}/support/history_and_development/?$ /{{ version }}/{{ lang }}/history/history_and_development/ +RedirectMatch ^/{{ version }}/{{ lang }}/support/tools/?$ /{{ version }}/{{ lang }}/support/#ocds-tools {%- endfor %} {%- endfor %} @@ -290,24 +290,24 @@ RedirectMatch ^/{{ version }}/{{ lang }}/support/tools/? # PPP {{ lang }} {{ version }} #################### -RedirectMatch /profiles/ppp/{{ version }}/{{ lang }}/extensions/bids/? https://extensions.open-contracting.org/{{ lang }}/extensions/bids/ -RedirectMatch /profiles/ppp/{{ version }}/{{ lang }}/extensions/budget/? https://extensions.open-contracting.org/{{ lang }}/extensions/budget/ -RedirectMatch /profiles/ppp/{{ version }}/{{ lang }}/extensions/budget_project/? https://extensions.open-contracting.org/{{ lang }}/extensions/budget_project/ -RedirectMatch /profiles/ppp/{{ version }}/{{ lang }}/extensions/charges/? https://extensions.open-contracting.org/{{ lang }}/extensions/charges/ -RedirectMatch /profiles/ppp/{{ version }}/{{ lang }}/extensions/documentation_details/? https://extensions.open-contracting.org/{{ lang }}/extensions/documentation_details/ -RedirectMatch /profiles/ppp/{{ version }}/{{ lang }}/extensions/finance/? https://extensions.open-contracting.org/{{ lang }}/extensions/finance/ -RedirectMatch /profiles/ppp/{{ version }}/{{ lang }}/extensions/location/? https://extensions.open-contracting.org/{{ lang }}/extensions/location/ -RedirectMatch /profiles/ppp/{{ version }}/{{ lang }}/extensions/metrics/? https://extensions.open-contracting.org/{{ lang }}/extensions/metrics/ -RedirectMatch /profiles/ppp/{{ version }}/{{ lang }}/extensions/performance_failures/? https://extensions.open-contracting.org/{{ lang }}/extensions/performance_failures/ -RedirectMatch /profiles/ppp/{{ version }}/{{ lang }}/extensions/ppp/? https://extensions.open-contracting.org/{{ lang }}/extensions/ppp/ -RedirectMatch /profiles/ppp/{{ version }}/{{ lang }}/extensions/process_title/? https://extensions.open-contracting.org/{{ lang }}/extensions/process_title/ -RedirectMatch /profiles/ppp/{{ version }}/{{ lang }}/extensions/qualification/? https://extensions.open-contracting.org/{{ lang }}/extensions/qualification/ -RedirectMatch /profiles/ppp/{{ version }}/{{ lang }}/extensions/requirements/? https://extensions.open-contracting.org/{{ lang }}/extensions/requirements/ -RedirectMatch /profiles/ppp/{{ version }}/{{ lang }}/extensions/risk_allocation/? https://extensions.open-contracting.org/{{ lang }}/extensions/risk_allocation/ -RedirectMatch /profiles/ppp/{{ version }}/{{ lang }}/extensions/shareholders/? https://extensions.open-contracting.org/{{ lang }}/extensions/shareholders/ -RedirectMatch /profiles/ppp/{{ version }}/{{ lang }}/extensions/signatories/? https://extensions.open-contracting.org/{{ lang }}/extensions/signatories/ -RedirectMatch /profiles/ppp/{{ version }}/{{ lang }}/extensions/tariffs/? https://extensions.open-contracting.org/{{ lang }}/extensions/tariffs/ -RedirectMatch /profiles/ppp/{{ version }}/{{ lang }}/extensions/transaction_milestones/? https://extensions.open-contracting.org/{{ lang }}/extensions/transaction_milestones/ +RedirectMatch /profiles/ppp/{{ version }}/{{ lang }}/extensions/bids/?$ https://extensions.open-contracting.org/{{ lang }}/extensions/bids/ +RedirectMatch /profiles/ppp/{{ version }}/{{ lang }}/extensions/budget/?$ https://extensions.open-contracting.org/{{ lang }}/extensions/budget/ +RedirectMatch /profiles/ppp/{{ version }}/{{ lang }}/extensions/budget_project/?$ https://extensions.open-contracting.org/{{ lang }}/extensions/budget_project/ +RedirectMatch /profiles/ppp/{{ version }}/{{ lang }}/extensions/charges/?$ https://extensions.open-contracting.org/{{ lang }}/extensions/charges/ +RedirectMatch /profiles/ppp/{{ version }}/{{ lang }}/extensions/documentation_details/?$ https://extensions.open-contracting.org/{{ lang }}/extensions/documentation_details/ +RedirectMatch /profiles/ppp/{{ version }}/{{ lang }}/extensions/finance/?$ https://extensions.open-contracting.org/{{ lang }}/extensions/finance/ +RedirectMatch /profiles/ppp/{{ version }}/{{ lang }}/extensions/location/?$ https://extensions.open-contracting.org/{{ lang }}/extensions/location/ +RedirectMatch /profiles/ppp/{{ version }}/{{ lang }}/extensions/metrics/?$ https://extensions.open-contracting.org/{{ lang }}/extensions/metrics/ +RedirectMatch /profiles/ppp/{{ version }}/{{ lang }}/extensions/performance_failures/?$ https://extensions.open-contracting.org/{{ lang }}/extensions/performance_failures/ +RedirectMatch /profiles/ppp/{{ version }}/{{ lang }}/extensions/ppp/?$ https://extensions.open-contracting.org/{{ lang }}/extensions/ppp/ +RedirectMatch /profiles/ppp/{{ version }}/{{ lang }}/extensions/process_title/?$ https://extensions.open-contracting.org/{{ lang }}/extensions/process_title/ +RedirectMatch /profiles/ppp/{{ version }}/{{ lang }}/extensions/qualification/?$ https://extensions.open-contracting.org/{{ lang }}/extensions/qualification/ +RedirectMatch /profiles/ppp/{{ version }}/{{ lang }}/extensions/requirements/?$ https://extensions.open-contracting.org/{{ lang }}/extensions/requirements/ +RedirectMatch /profiles/ppp/{{ version }}/{{ lang }}/extensions/risk_allocation/?$ https://extensions.open-contracting.org/{{ lang }}/extensions/risk_allocation/ +RedirectMatch /profiles/ppp/{{ version }}/{{ lang }}/extensions/shareholders/?$ https://extensions.open-contracting.org/{{ lang }}/extensions/shareholders/ +RedirectMatch /profiles/ppp/{{ version }}/{{ lang }}/extensions/signatories/?$ https://extensions.open-contracting.org/{{ lang }}/extensions/signatories/ +RedirectMatch /profiles/ppp/{{ version }}/{{ lang }}/extensions/tariffs/?$ https://extensions.open-contracting.org/{{ lang }}/extensions/tariffs/ +RedirectMatch /profiles/ppp/{{ version }}/{{ lang }}/extensions/transaction_milestones/?$ https://extensions.open-contracting.org/{{ lang }}/extensions/transaction_milestones/ {%- endfor %} {%- endfor %}