Skip to content

Commit 9915be7

Browse files
deshrajRishabhJain2018
authored andcommitted
Challenges: Add API to create AWS federated user for docker based challenges (Cloud-CV#2099)
1 parent 09741c1 commit 9915be7

File tree

4 files changed

+69
-4
lines changed

4 files changed

+69
-4
lines changed

apps/challenges/urls.py

+3
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,7 @@
5656
views.get_broker_url_by_challenge_pk, name='get_broker_url_by_challenge_pk'),
5757
url(r'^get_broker_urls/$',
5858
views.get_broker_urls, name='get_broker_urls'),
59+
url(r'^phases/(?P<phase_pk>[0-9]+)/participant_team/aws/credentials/$',
60+
views.get_aws_credentials_for_participant_team,
61+
name='get_aws_credentials_for_participant_team'),
5962
]

apps/challenges/utils.py

+24-3
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@
22

33
import boto3
44
import json
5+
import logging
56

67
from botocore.exceptions import ClientError
78

89
from base.utils import get_model_object
910

1011
from .models import Challenge, ChallengePhase, Leaderboard, DatasetSplit, ChallengePhaseSplit
1112

13+
logger = logging.getLogger(__name__)
1214

1315
get_challenge_model = get_model_object(Challenge)
1416

@@ -39,6 +41,23 @@ def convert_to_aws_ecr_compatible_format(string):
3941
return string.replace(" ", "-").lower()
4042

4143

44+
def convert_to_aws_federated_user_format(string):
45+
'''Make string compatible with AWS ECR repository naming
46+
47+
Arguments:
48+
string {string} -- Desired ECR repository name
49+
50+
Returns:
51+
string -- Valid ECR repository name
52+
'''
53+
string = string.replace(" ", "-")
54+
result = ""
55+
for ch in string:
56+
if ch.isalnum() or ch in ['=', ',', '.', '@', '-']:
57+
result += ch
58+
return result
59+
60+
4261
def get_or_create_ecr_repository(name, region_name='us-east-1'):
4362
'''Get or create AWS ECR Repository
4463
@@ -77,6 +96,8 @@ def get_or_create_ecr_repository(name, region_name='us-east-1'):
7796
response = client.create_repository(repositoryName=name)
7897
repository = response['repository']
7998
created = True
99+
else:
100+
logger.exception(e)
80101
return (repository, created)
81102

82103

@@ -117,7 +138,7 @@ def create_federated_user(name, repository):
117138
'''
118139
AWS_ACCOUNT_ID = os.environ.get('AWS_ACCOUNT_ID')
119140
policy = {
120-
"Version": "2019-02-07",
141+
"Version": "2012-10-17",
121142
"Statement": [
122143
{
123144
"Effect": "Allow",
@@ -135,8 +156,8 @@ def create_federated_user(name, repository):
135156
}
136157
client = boto3.client('sts')
137158
response = client.get_federation_token(
138-
Name=name,
159+
Name=convert_to_aws_federated_user_format(name),
139160
Policy=json.dumps(policy),
140-
DurationSeconds=3600
161+
DurationSeconds=43200,
141162
)
142163
return response

apps/challenges/views.py

+36-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@
6464
ZipChallengePhaseSplitSerializer,)
6565
from .utils import (get_file_content,
6666
get_or_create_ecr_repository,
67-
convert_to_aws_ecr_compatible_format,)
67+
convert_to_aws_ecr_compatible_format,
68+
create_federated_user,)
6869

6970
logger = logging.getLogger(__name__)
7071

@@ -1376,3 +1377,37 @@ def get_broker_url_by_challenge_pk(request, challenge_pk):
13761377

13771378
response_data = [challenge.queue]
13781379
return Response(response_data, status=status.HTTP_200_OK)
1380+
1381+
1382+
@api_view(['GET'])
1383+
@throttle_classes([UserRateThrottle])
1384+
@permission_classes((permissions.IsAuthenticated, HasVerifiedEmail))
1385+
@authentication_classes((ExpiringTokenAuthentication,))
1386+
def get_aws_credentials_for_participant_team(request, phase_pk):
1387+
"""
1388+
Returns:
1389+
Dictionary containing AWS credentials for the participant team for a particular challenge
1390+
"""
1391+
1392+
challenge_phase = get_challenge_phase_model(phase_pk)
1393+
1394+
challenge = challenge_phase.challenge
1395+
participant_team_pk = get_participant_team_id_of_user_for_a_challenge(
1396+
request.user, challenge.pk)
1397+
1398+
if not challenge.is_docker_based:
1399+
response_data = {'error': 'Sorry, this is not a docker based challenge.'}
1400+
return Response(response_data, status=status.HTTP_400_BAD_REQUEST)
1401+
1402+
if participant_team_pk is None:
1403+
response_data = {'error': 'You have not participated in this challenge.'}
1404+
return Response(response_data, status=status.HTTP_400_BAD_REQUEST)
1405+
1406+
participant_team = ParticipantTeam.objects.get(id=participant_team_pk)
1407+
federated_user = create_federated_user(participant_team.team_name, participant_team.get_docker_repository_name())
1408+
data = {
1409+
'federated_user': federated_user,
1410+
'docker_repository_uri': participant_team.docker_repository_uri
1411+
}
1412+
response_data = {'success': data}
1413+
return Response(response_data, status=status.HTTP_200_OK)

apps/participants/models.py

+6
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ def get_all_participants_email(self):
4848
email_ids = Participant.objects.filter(team=self).values_list('user__email', flat=True)
4949
return list(email_ids)
5050

51+
def get_docker_repository_name(self):
52+
if self.docker_repository_uri != "":
53+
return self.docker_repository_uri.split("/")[-1]
54+
else:
55+
return None
56+
5157
class Meta:
5258
app_label = 'participants'
5359
db_table = 'participant_team'

0 commit comments

Comments
 (0)