From e65525150573bedc595cbdff98bc994b50ef5d71 Mon Sep 17 00:00:00 2001 From: Benjamin Moody Date: Tue, 24 Oct 2023 14:12:34 -0400 Subject: [PATCH] [WIP] Add model fields for storing AWS identity information. We want to verify a person's AWS identity in order to permit them to access restricted resources via direct cloud APIs; and possibly for other purposes in the future. An AWS account ID is not an identity. An account may contain many identities (known as "userids" or "unique IDs"), which might or might not belong to the same person. (Even if they do all belong to the same person, it doesn't mean that person wants or should want to give all of their identities the ability to access sensitive data.) Here, we add fields to store the userid alongside the account ID (which is still retained, since it may be of interest in the future), and to store the date and time that the person's credentials were verified. --- ...58_cloudinformation_aws_userid_and_more.py | 29 +++++++++++++++++++ physionet-django/user/models.py | 5 ++++ physionet-django/user/validators.py | 19 ++++++++++-- 3 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 physionet-django/user/migrations/0058_cloudinformation_aws_userid_and_more.py diff --git a/physionet-django/user/migrations/0058_cloudinformation_aws_userid_and_more.py b/physionet-django/user/migrations/0058_cloudinformation_aws_userid_and_more.py new file mode 100644 index 0000000000..3f09326eef --- /dev/null +++ b/physionet-django/user/migrations/0058_cloudinformation_aws_userid_and_more.py @@ -0,0 +1,29 @@ +# Generated by Django 4.1.10 on 2023-10-27 22:00 + +from django.db import migrations, models +import user.validators + + +class Migration(migrations.Migration): + + dependencies = [ + ("user", "0057_alter_cloudinformation_aws_id"), + ] + + operations = [ + migrations.AddField( + model_name="cloudinformation", + name="aws_userid", + field=models.CharField( + blank=True, + max_length=30, + null=True, + validators=[user.validators.validate_aws_userid], + ), + ), + migrations.AddField( + model_name="cloudinformation", + name="aws_verification_datetime", + field=models.DateTimeField(null=True), + ), + ] diff --git a/physionet-django/user/models.py b/physionet-django/user/models.py index 2ad2e396f2..cc65b7dab5 100644 --- a/physionet-django/user/models.py +++ b/physionet-django/user/models.py @@ -1225,6 +1225,11 @@ class CloudInformation(models.Model): default=None, validators=[validators.validate_aws_id], ) + aws_userid = models.CharField( + max_length=30, null=True, blank=True, + validators=[validators.validate_aws_userid], + ) + aws_verification_datetime = models.DateTimeField(null=True) class Meta: default_permissions = () diff --git a/physionet-django/user/validators.py b/physionet-django/user/validators.py index 455a8619c2..444d6678bd 100644 --- a/physionet-django/user/validators.py +++ b/physionet-django/user/validators.py @@ -277,8 +277,23 @@ def validate_aws_id(value): """" Validate an AWS ID. """ - aws_id_pattern = r"\b\d{12}\b" - if value is not None and not re.search(aws_id_pattern, value): + if not re.fullmatch(r"\d{12}", value): raise ValidationError( "Invalid AWS ID. Please provide a valid AWS ID, which should be a 12-digit number." ) + + +def validate_aws_userid(value): + """ + Validate an AWS user ID. + """ + # Officially, "minimum length of 16, maximum length of 128", but + # that includes all types of unique IDs, not just IAM user IDs. + # Some examples in AWS documentation show 16-character user IDs, + # while others show 21-character IDs. The size matters since we + # need to store a fixed number of IDs in a fixed-size JSON file. + if not re.fullmatch('AIDA[A-Z0-9]{12,17}', value): + raise ValidationError( + 'Invalid AWS user ID. Your user ID should be 16 to 21 ' + 'characters long, beginning with "AIDA".' + )