in Lab4/server/Resources/shared_service_authorizer.py [0:0]
def lambda_handler(event, context):
#get JWT token after Bearer from authorization
token = event['authorizationToken'].split(" ")
if (token[0] != 'Bearer'):
raise Exception('Authorization header should have a format Bearer <JWT> Token')
jwt_bearer_token = token[1]
logger.info("Method ARN: " + event['methodArn'])
#only to get tenant id to get user pool info
unauthorized_claims = jwt.get_unverified_claims(jwt_bearer_token)
logger.info(unauthorized_claims)
if(auth_manager.isSaaSProvider(unauthorized_claims['custom:userRole'])):
userpool_id = user_pool_operation_user
appclient_id = app_client_operation_user
else:
#get tenant user pool and app client to validate jwt token against
userpool_id = tenant_userpool_id
appclient_id = tenant_appclient_id
#get keys for tenant user pool to validate
keys_url = 'https://cognito-idp.{}.amazonaws.com/{}/.well-known/jwks.json'.format(region, userpool_id)
with urllib.request.urlopen(keys_url) as f:
response = f.read()
keys = json.loads(response.decode('utf-8'))['keys']
#authenticate against cognito user pool using the key
response = validateJWT(jwt_bearer_token, appclient_id, keys)
#get authenticated claims
if (response == False):
logger.error('Unauthorized')
raise Exception('Unauthorized')
else:
logger.info(response)
principal_id = response["sub"]
user_name = response["cognito:username"]
tenant_id = response["custom:tenantId"]
user_role = response["custom:userRole"]
tmp = event['methodArn'].split(':')
api_gateway_arn_tmp = tmp[5].split('/')
aws_account_id = tmp[4]
policy = AuthPolicy(principal_id, aws_account_id)
policy.restApiId = api_gateway_arn_tmp[0]
policy.region = tmp[3]
policy.stage = api_gateway_arn_tmp[1]
#only tenant admin and system admin can do certain actions like create and disable users
if (auth_manager.isTenantAdmin(user_role) or auth_manager.isSystemAdmin(user_role)):
policy.allowAllMethods()
if (auth_manager.isTenantAdmin(user_role)):
policy.denyMethod(HttpVerb.POST, "tenant-activation")
policy.denyMethod(HttpVerb.GET, "tenants")
else:
#if not tenant admin or system admin then only allow to get info and update info
policy.allowMethod(HttpVerb.GET, "user/*")
policy.allowMethod(HttpVerb.PUT, "user/*")
authResponse = policy.build()
# Generate STS credentials to be used for FGAC
# Important Note:
# We are generating STS token inside Authorizer to take advantage of the caching behavior of authorizer
# Another option is to generate the STS token inside the lambda function itself, as mentioned in this blog post: https://aws.amazon.com/blogs/apn/isolating-saas-tenants-with-dynamically-generated-iam-policies/
# Finally, you can also consider creating one Authorizer per microservice in cases where you want the IAM policy specific to that service
iam_policy = auth_manager.getPolicyForUser(user_role, utils.Service_Identifier.SHARED_SERVICES.value, tenant_id, region, aws_account_id)
logger.info(iam_policy)
role_arn = "arn:aws:iam::{}:role/authorizer-access-role".format(aws_account_id)
assumed_role = sts_client.assume_role(
RoleArn=role_arn,
RoleSessionName="tenant-aware-session",
Policy=iam_policy,
)
credentials = assumed_role["Credentials"]
#pass sts credentials to lambda
context = {
'accesskey': credentials['AccessKeyId'],
'secretkey' : credentials['SecretAccessKey'],
'sessiontoken' : credentials["SessionToken"],
'userName': user_name,
'userPoolId': userpool_id,
'tenantId': tenant_id,
'userRole': user_role
}
authResponse['context'] = context
return authResponse