Skip to content

Commit

Permalink
[u] Merge branch 'promotions/2023-05-25' into prod (#5242, PR #5243)
Browse files Browse the repository at this point in the history
  • Loading branch information
achave11-ucsc committed May 25, 2023
2 parents 7c461e6 + be7830d commit 5093a46
Show file tree
Hide file tree
Showing 25 changed files with 577 additions and 487 deletions.
64 changes: 55 additions & 9 deletions OPERATOR.rst
Original file line number Diff line number Diff line change
Expand Up @@ -239,22 +239,55 @@ Change the target branch of the blocked PR to ``develop`` and remove the ``chain
label from that PR. Remove the ``base`` label from the blocking PR. Lastly, remove the blocking
relationship.

Updating the AMI for GitLab instances
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Once a month, operators must check for updates to the AMI for the root volume of
the EC2 instance running GitLab. There are ways to dynamically determine the
latest AMI for Amazon Linux 2 but in the spirit of reproducible builds, we would
rather pin the AMI ID and adopt updates at our own discretion to avoid
unexpected failures. To obtain the latest compatible AMI ID, select the desired
``….gitlab`` component, say, ``_select dev.gitlab`` and run

::

aws ssm get-parameters \
--names \
$(aws ssm get-parameters-by-path \
--path /aws/service/ami-amazon-linux-latest \
--query "Parameters[].Name" \
| jq -r .[] \
| grep -F amzn2 \
| grep -Fv minimal \
| grep -Fv kernel-5.10 \
| grep -F x86_64 \
| grep -F ebs) \
| jq -r .Parameters[].Value

This will print the ID of the most recent Amazon Linux 2 AMI. Update the value
of the ``ami_id`` variable in ``terraform/gitlab/gitlab.tf.json.template.py``.
The variable holds a dictionary with one entry per region, because AMIs are
specific to a region. If there are ``….gitlab`` components in more than one AWS
region (uncommon), you need to select at least one ``….gitlab`` component in
each of these regions, rerun the command above for each such component, and add
or update the ``ami_id`` entry for the respective region.

Upgrading GitLab & ClamAV
^^^^^^^^^^^^^^^^^^^^^^^^^

Operators must check for updates to GitLab and ClamAV on a monthly basis in
addition to triaging GitLab security releases that occur during the month.
An email notification is sent to ``[email protected]`` when a GitLab security
Operators must check for updates to the Docker images for GitLab and ClamAV at
least once a month, and whenever a GitLab security releases requires it. An
email notification is sent to ``[email protected]`` when a GitLab security
release is available. Discuss with the lead the **Table of Fixes** referenced in
the release blog post to determine the urgency of the update. An email
notification should also be received when ClamAV releases become available. The
current version of GitLab installed can be found on the ``/help`` endpoint of
`GitLab dev`_, and the available releases can be found on the
`GitLab Docker image`_ page. When updating the GitLab instance, check if there
are applicable updates to the `GitLab runner image`_. Use the latest runner
image whose major and minor version match that of the GitLab image. Similarly,
check for available releases to ClamAV in the `ClamAV image`_. The current
version of ClamAV image being used can be found by running::
`GitLab dev`_, and the available releases can be found on the `GitLab Docker
image`_ page. When updating the GitLab instance, check if there are applicable
updates to the `GitLab runner image`_. Use the latest runner image whose major
and minor version match that of the GitLab image. Similarly, check for available
releases to ClamAV in the `ClamAV image`_. The current version of ClamAV image
being used can be found by running::

cat $project_root/terraform/gitlab/gitlab.tf.json.template.py | grep 'clamav_image ='

Expand Down Expand Up @@ -313,6 +346,19 @@ For GitLab or ClamAV updates, use the ``--no-restart`` flag in order to leave
the instance stopped after the snapshot has been created. There is no point in
starting the instance only to have the update terminate it again.

Updating software packages on GitLab instances
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Once a week, operators must update all Linux packages installed on the root
volume of each GitLab instance. SSH access to the instances is necessary to
perform these instructions but on production instances this access is
unavailable, even to operators. In these cases the operator must request the
help of the system administrator via Slack to perform these steps.

SSH into the instance, and run ``sudo yum update`` followed by ``sudo reboot``.
Wait for the GitLab web application to become available again and perform a
``git pull`` from one of the Git repositories hosted on that instance.

Adding snapshots to ``dev``
^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down
33 changes: 33 additions & 0 deletions UPGRADING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,39 @@ branch that does not have the listed changes, the steps would need to be
reverted. This is all fairly informal and loosely defined. Hopefully we won't
have too many entries in this file.

#5207 Fix: Partition sizing ignores supplementary bundles
=========================================================

Subgraph counts have been updated for `anvildev` and `anvilbox`. If you have any
personal deployments that index these snapshots, update the subgraph counts
accordingly.


#4022 Encrypt GitLab data and root volume and snapshots
=======================================================

Operator
~~~~~~~~

Prior to pushing the merge commit to a GitLab instance, login to the AWS
Console and navigate to `EC2` -> `Instances` -> select the GitLab instance ->
`Storage` to confirm that root volume is encrypted.

If the root volume is not encrypted, manually deploy the ``gitlab`` component of
a deployment just before pushing the merge commit to the GitLab instance in that
deployment.


#5133 Trigger an alarm on absence of logs
=========================================

Operator
~~~~~~~~

Manually deploy the ``shared`` component of any main deployment just before
pushing the merge commit to the GitLab instance in that deployment.


#5110 Update GitLab IAM policy for FedRAMP inventory
====================================================

Expand Down
20 changes: 10 additions & 10 deletions deployments/anvilbox/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,17 @@ def mkdict(previous_catalog: dict[str, str],


anvil_sources = mkdict({}, 11, mkdelta([
mksrc('datarepo-1ba591a6', 'ANVIL_1000G_high_coverage_2019_20221019_ANV5_202303081523', 6404),
mksrc('datarepo-aa67671a', 'ANVIL_CMG_UWASH_DS_BAV_IRB_PUB_RD_20221020_ANV5_202303081451', 177),
mksrc('datarepo-1ba591a6', 'ANVIL_1000G_high_coverage_2019_20221019_ANV5_202303081523', 6804),
mksrc('datarepo-aa67671a', 'ANVIL_CMG_UWASH_DS_BAV_IRB_PUB_RD_20221020_ANV5_202303081451', 181),
mksrc('datarepo-b4e0bfd5', 'ANVIL_CMG_UWASH_DS_BDIS_20221020_ANV5_202303081501', 10),
mksrc('datarepo-333dd883', 'ANVIL_CMG_UWASH_DS_HFA_20221020_ANV5_202303081456', 83),
mksrc('datarepo-b968cbdb', 'ANVIL_CMG_UWASH_DS_NBIA_20221020_ANV5_202303081459', 107),
mksrc('datarepo-6a5b13ea', 'ANVIL_CMG_UWASH_HMB_20221020_ANV5_202303081455', 419),
mksrc('datarepo-3d4c42f7', 'ANVIL_CMG_UWASH_HMB_IRB_20221020_ANV5_202303081454', 41),
mksrc('datarepo-080b2c9e', 'ANVIL_CMG_UWash_DS_EP_20221020_ANV5_202303081452', 49),
mksrc('datarepo-4f75c9e3', 'ANVIL_CMG_UWash_GRU_20230308_ANV5_202303081731', 2113),
mksrc('datarepo-ec9365be', 'ANVIL_CMG_UWash_GRU_IRB_20221020_ANV5_202303081458', 559),
mksrc('datarepo-8392ac2c', 'ANVIL_GTEx_V8_hg38_20221013_ANV5_202303081502', 18361),
mksrc('datarepo-333dd883', 'ANVIL_CMG_UWASH_DS_HFA_20221020_ANV5_202303081456', 198),
mksrc('datarepo-b968cbdb', 'ANVIL_CMG_UWASH_DS_NBIA_20221020_ANV5_202303081459', 110),
mksrc('datarepo-6a5b13ea', 'ANVIL_CMG_UWASH_HMB_20221020_ANV5_202303081455', 423),
mksrc('datarepo-3d4c42f7', 'ANVIL_CMG_UWASH_HMB_IRB_20221020_ANV5_202303081454', 45),
mksrc('datarepo-080b2c9e', 'ANVIL_CMG_UWash_DS_EP_20221020_ANV5_202303081452', 53),
mksrc('datarepo-4f75c9e3', 'ANVIL_CMG_UWash_GRU_20230308_ANV5_202303081731', 5861),
mksrc('datarepo-ec9365be', 'ANVIL_CMG_UWash_GRU_IRB_20221020_ANV5_202303081458', 563),
mksrc('datarepo-8392ac2c', 'ANVIL_GTEx_V8_hg38_20221013_ANV5_202303081502', 101205)
]))


Expand Down
20 changes: 10 additions & 10 deletions deployments/anvildev/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +56,17 @@ def mkdict(previous_catalog: dict[str, str],


anvil_sources = mkdict({}, 11, mkdelta([
mksrc('datarepo-1ba591a6', 'ANVIL_1000G_high_coverage_2019_20221019_ANV5_202303081523', 6404),
mksrc('datarepo-aa67671a', 'ANVIL_CMG_UWASH_DS_BAV_IRB_PUB_RD_20221020_ANV5_202303081451', 177),
mksrc('datarepo-1ba591a6', 'ANVIL_1000G_high_coverage_2019_20221019_ANV5_202303081523', 6804),
mksrc('datarepo-aa67671a', 'ANVIL_CMG_UWASH_DS_BAV_IRB_PUB_RD_20221020_ANV5_202303081451', 181),
mksrc('datarepo-b4e0bfd5', 'ANVIL_CMG_UWASH_DS_BDIS_20221020_ANV5_202303081501', 10),
mksrc('datarepo-333dd883', 'ANVIL_CMG_UWASH_DS_HFA_20221020_ANV5_202303081456', 83),
mksrc('datarepo-b968cbdb', 'ANVIL_CMG_UWASH_DS_NBIA_20221020_ANV5_202303081459', 107),
mksrc('datarepo-6a5b13ea', 'ANVIL_CMG_UWASH_HMB_20221020_ANV5_202303081455', 419),
mksrc('datarepo-3d4c42f7', 'ANVIL_CMG_UWASH_HMB_IRB_20221020_ANV5_202303081454', 41),
mksrc('datarepo-080b2c9e', 'ANVIL_CMG_UWash_DS_EP_20221020_ANV5_202303081452', 49),
mksrc('datarepo-4f75c9e3', 'ANVIL_CMG_UWash_GRU_20230308_ANV5_202303081731', 2113),
mksrc('datarepo-ec9365be', 'ANVIL_CMG_UWash_GRU_IRB_20221020_ANV5_202303081458', 559),
mksrc('datarepo-8392ac2c', 'ANVIL_GTEx_V8_hg38_20221013_ANV5_202303081502', 18361),
mksrc('datarepo-333dd883', 'ANVIL_CMG_UWASH_DS_HFA_20221020_ANV5_202303081456', 198),
mksrc('datarepo-b968cbdb', 'ANVIL_CMG_UWASH_DS_NBIA_20221020_ANV5_202303081459', 110),
mksrc('datarepo-6a5b13ea', 'ANVIL_CMG_UWASH_HMB_20221020_ANV5_202303081455', 423),
mksrc('datarepo-3d4c42f7', 'ANVIL_CMG_UWASH_HMB_IRB_20221020_ANV5_202303081454', 45),
mksrc('datarepo-080b2c9e', 'ANVIL_CMG_UWash_DS_EP_20221020_ANV5_202303081452', 53),
mksrc('datarepo-4f75c9e3', 'ANVIL_CMG_UWash_GRU_20230308_ANV5_202303081731', 5861),
mksrc('datarepo-ec9365be', 'ANVIL_CMG_UWash_GRU_IRB_20221020_ANV5_202303081458', 563),
mksrc('datarepo-8392ac2c', 'ANVIL_GTEx_V8_hg38_20221013_ANV5_202303081502', 101205)
]))


Expand Down
6 changes: 3 additions & 3 deletions deployments/anvilprod/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ def mkdict(previous_catalog: dict[str, str],


anvil_sources = mkdict({}, 3, mkdelta([
mksrc('datarepo-dev-43738c90', 'ANVIL_1000G_2019_Dev_20230302_ANV5_202303032342', 6404),
mksrc('datarepo-dev-42c70e6a', 'ANVIL_CCDG_Sample_1_20230228_ANV5_202302281520', 25),
mksrc('datarepo-dev-97ad270b', 'ANVIL_CMG_Sample_1_20230225_ANV5_202302281509', 25),
mksrc('datarepo-dev-43738c90', 'ANVIL_1000G_2019_Dev_20230302_ANV5_202303032342', 22814),
mksrc('datarepo-dev-42c70e6a', 'ANVIL_CCDG_Sample_1_20230228_ANV5_202302281520', 28),
mksrc('datarepo-dev-97ad270b', 'ANVIL_CMG_Sample_1_20230225_ANV5_202302281509', 25)
]))


Expand Down
11 changes: 6 additions & 5 deletions scripts/create_gitlab_snapshot.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,9 @@ def gitlab_volume_info() -> JSON:

def shutdown_instance(instance: JSON):
instance_id = instance['InstanceId']
log.info('Preparing to stop GitLab instance for %r, waiting 10 seconds '
'before proceeding. Hit Ctrl-C to abort …',
log.info('Preparing to stop GitLab instance in %r. '
'Waiting 10 seconds before proceeding. '
'Hit Ctrl-C to abort …',
config.deployment_stage)
sleep(10)
log.info('Stopping instance %r …', instance_id)
Expand All @@ -83,7 +84,7 @@ def shutdown_instance(instance: JSON):

def start_instance(instance: JSON):
instance_id = instance['InstanceId']
log.info('Starting instance %r …', config.deployment_stage)
log.info('Starting instance %r …', instance_id)
aws.ec2.start_instances(InstanceIds=[instance_id])
waiter = aws.ec2.get_waiter('instance_status_ok')
waiter.wait(InstanceIds=[instance_id],
Expand All @@ -105,7 +106,7 @@ def create_snapshot(volume: JSON):
'service': 'azul',
}
date = datetime.datetime.now().strftime('%Y-%m-%d %H:%M')
response = aws.ec2.create_snapshot(Description=f'{date} GitLab Update',
response = aws.ec2.create_snapshot(Description=f'{date} snapshot of GitLab data volume',
VolumeId=volume['VolumeId'],
TagSpecifications=[
dict(ResourceType='snapshot',
Expand All @@ -118,7 +119,7 @@ def create_snapshot(volume: JSON):
waiter.wait(SnapshotIds=[snapshot_id],
WaiterConfig=dict(MaxAttempts=9999, Delay=15))
log.info('Snapshot %r of volume %r is complete',
volume['VolumeId'], config.deployment_stage)
snapshot_id, volume['VolumeId'])


if __name__ == '__main__':
Expand Down
89 changes: 89 additions & 0 deletions scripts/update_subgraph_counts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
"""
Count the number of subgraphs per configured source and produce output to
expedite updated source configurations.
"""

import argparse
import sys

import attr

from azul import (
config,
)
from azul.args import (
AzulArgumentHelpFormatter,
)
from azul.azulclient import (
AzulClient,
)
from azul.indexer import (
Prefix,
)
from azul.openapi import (
format_description,
)
from azul.terra import (
TDRSourceSpec,
)


@attr.s(auto_attribs=True, frozen=True, kw_only=True)
class SourceSpecArgs:
project: str
snapshot: str
subgraph_count: int

def __str__(self) -> str:
return f'mksrc({self.project!r}, {self.snapshot!r}, {self.subgraph_count!r})'


def generate_sources(catalog: str) -> list[SourceSpecArgs]:
plugin = AzulClient().repository_plugin(catalog)
sources = []
for spec in plugin.sources:
spec: TDRSourceSpec = attr.evolve(spec, prefix=Prefix.of_everything)
ref = plugin.resolve_source(str(spec))
partitions = plugin.list_partitions(ref)
sources.append(SourceSpecArgs(project=spec.project,
snapshot=spec.name,
subgraph_count=sum(partitions.values())))
return sources


def main(args: list[str]):
parser = argparse.ArgumentParser(description=__doc__,
formatter_class=AzulArgumentHelpFormatter)

parser.add_argument('--catalogs',
nargs='+',
metavar='NAME',
default=[
c for c in config.catalogs
if c not in config.integration_test_catalogs
],
help='The names of the catalogs to determine source specs for.')

args = parser.parse_args(args)

for catalog in args.catalogs:
print(catalog)
print('-' * len(catalog))
spec_args_list = generate_sources(catalog)
spec_args_list.sort(key=lambda spec_args: spec_args.snapshot)
print(',\n'.join(map(str, spec_args_list)), end='\n\n')

print(format_description('''
-----------------
!!! IMPORTANT !!!
-----------------
This script does *not* populate the `ma` or `pop` flags for the source
specs. Do not copy/paste the above output without checking whether these
flags should be applied. If `mksrc` generates a common prefix, manual
adjustment of the generated common prefix may be required.
'''))


if __name__ == '__main__':
main(sys.argv[1:])
38 changes: 4 additions & 34 deletions src/azul/chalice.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from collections.abc import (
Iterable,
)
import html
import json
from json import (
JSONEncoder,
Expand Down Expand Up @@ -37,12 +36,6 @@
from furl import (
furl,
)
from more_itertools import (
only,
)
from werkzeug.http import (
parse_accept_header,
)

from azul import (
config,
Expand Down Expand Up @@ -79,6 +72,10 @@ class GoneError(ChaliceViewError):


# Chalice does not define any exceptions for 5xx status codes besides 500
class BadGatewayError(ChaliceViewError):
STATUS_CODE = 502


class ServiceUnavailableError(ChaliceViewError):
STATUS_CODE = 503

Expand Down Expand Up @@ -110,7 +107,6 @@ def __init__(self,
self._specs: Optional[MutableJSON] = None
super().__init__(app_name, debug=config.debug > 0, configure_logs=False)
# Middleware is invoked in order of registration
self.register_middleware(self._html_wrapping_middleware, 'http')
self.register_middleware(self._logging_middleware, 'http')
self.register_middleware(self._hsts_header_middleware, 'http')
self.register_middleware(self._lambda_context_middleware, 'all')
Expand Down Expand Up @@ -145,32 +141,6 @@ def patched_event_source_handler(self_, event, context):
if old_handler.__code__ != patched_event_source_handler.__code__:
chalice.app.EventSourceHandler.__call__ = patched_event_source_handler

def _html_wrapping_middleware(self, event, get_response):
"""
Embed a `text/plain` response in HTML if the request favors `text/html`.
Any HTML fragments in the original response are escaped to counteract
HTML injection attacks. This doesn't fully prevent those attacks because
a broken, ancient user agent might still request `text/plain`, `*/*` or
nothing, ignore the `text/plain` content type, sniff the HTML fragment
and render it. It does, however, handle vulnerability scanners because
those do prefer `text/html`.
"""
response = get_response(event)
ct_key = only(k for k in response.headers if k.casefold() == 'content-type')
if ct_key and response.headers[ct_key] == 'text/plain':
parsed = parse_accept_header(event.headers.get('accept'))
text_html = parsed.find('text/html')
star_star = parsed.find('*/*')
if 0 <= text_html and (star_star < 0 or text_html < star_star):
response.body = (
'<html><body>'
f'<h1>Status {response.status_code}</h1>'
f'<pre>{html.escape(json.dumps(response.body), quote=False)}</pre>'
'</body></html>'
)
response.headers[ct_key] = 'text/html'
return response

def _logging_middleware(self, event, get_response):
self._log_request()
response = get_response(event)
Expand Down
Loading

0 comments on commit 5093a46

Please sign in to comment.