diff --git a/config/prd/regional/api-clients/stanford.yaml b/config/prd/regional/api-clients/stanford.yaml new file mode 100644 index 00000000..94c9a284 --- /dev/null +++ b/config/prd/regional/api-clients/stanford.yaml @@ -0,0 +1,31 @@ +template: + path: 'cognito-app-client.yaml' + type: 'file' + +parameters: + UserPoolId: !stack_output prd/regional/cognito.yaml::UserPoolId + + Domain: !stack_attr sceptre_user_data.domain + Subdomain: 'auth' + Env: !stack_attr sceptre_user_data.env + + ClientName: 'stanford' + + ClientCallbackUri: 'https://localhost:3000/callback' + + AllowWrite: 'yes' + + OnlyAllowAdminsToCreateUsers: 'false' + UnusedAccountValidityDays: '14' + MinimumPasswordLength: '8' + + TokenValidityUnits: 'minutes' + AccessTokenValidity: '10' + AuthSessionValidatyMinutes: '3' + IdTokenValidity: '7' + RefreshTokenValidity: '10080' + +hooks: + after_update: + cmd: 'src/scripts/add-api-client.sh prd stanford http://localhost:3000/callback' + cmd: 'aws ssm put-parameter --overwrite --name /uc3/dmp/tool/provenance/stanford/ror_list --type String --value "[\"https://ror.org/03mtd9a03\",\"https://ror.org/00f54p054\",\"https://ror.org/014qe3j22\",\"https://ror.org/0551gkb08\"]"' diff --git a/config/prd/regional/api-clients/uc-boulder.yaml b/config/prd/regional/api-clients/uc-boulder.yaml new file mode 100644 index 00000000..fa3270ba --- /dev/null +++ b/config/prd/regional/api-clients/uc-boulder.yaml @@ -0,0 +1,29 @@ +template: + path: 'cognito-app-client.yaml' + type: 'file' + +parameters: + UserPoolId: !stack_output prd/regional/cognito.yaml::UserPoolId + + Domain: !stack_attr sceptre_user_data.domain + Subdomain: 'auth' + Env: !stack_attr sceptre_user_data.env + + ClientName: 'uc-boulder' + + ClientCallbackUri: 'https://localhost:3000/callback' + + OnlyAllowAdminsToCreateUsers: 'false' + UnusedAccountValidityDays: '14' + MinimumPasswordLength: '8' + + TokenValidityUnits: 'minutes' + AccessTokenValidity: '10' + AuthSessionValidatyMinutes: '3' + IdTokenValidity: '7' + RefreshTokenValidity: '10080' + +hooks: + after_update: + cmd: 'src/scripts/add-api-client.sh prd uc-boulder http://localhost:3000/callback' + cmd: 'aws ssm put-parameter --overwrite --name /uc3/dmp/tool/provenance/uc-boulder/ror_list --type String --value "[\"https://ror.org/02ttsq026\"]"' diff --git a/config/prd/regional/api-clients/uc-riverside.yaml b/config/prd/regional/api-clients/uc-riverside.yaml new file mode 100644 index 00000000..643f84e3 --- /dev/null +++ b/config/prd/regional/api-clients/uc-riverside.yaml @@ -0,0 +1,29 @@ +template: + path: 'cognito-app-client.yaml' + type: 'file' + +parameters: + UserPoolId: !stack_output prd/regional/cognito.yaml::UserPoolId + + Domain: !stack_attr sceptre_user_data.domain + Subdomain: 'auth' + Env: !stack_attr sceptre_user_data.env + + ClientName: 'uc-riverside' + + ClientCallbackUri: 'https://localhost:3000/callback' + + OnlyAllowAdminsToCreateUsers: 'false' + UnusedAccountValidityDays: '14' + MinimumPasswordLength: '8' + + TokenValidityUnits: 'minutes' + AccessTokenValidity: '10' + AuthSessionValidatyMinutes: '3' + IdTokenValidity: '7' + RefreshTokenValidity: '10080' + +hooks: + after_update: + cmd: 'src/scripts/add-api-client.sh prd uc-riverside http://localhost:3000/callback' + cmd: 'aws ssm put-parameter --overwrite --name /uc3/dmp/tool/provenance/uc-riverside/ror_list --type String --value "[\"https://ror.org/03nawhv43\"]"' diff --git a/src/scripts/add-api-client.sh b/src/scripts/add-api-client.sh new file mode 100755 index 00000000..28438f91 --- /dev/null +++ b/src/scripts/add-api-client.sh @@ -0,0 +1,27 @@ + +if [ $# -ne 3 ]; then + echo 'Wrong number of arguments. Expecting 2:' + echo ' - The `env` for the Dynamo Table (e.g. dev)' + echo ' - The Name of the external system (e.g. Foo)' + echo ' - The Domain of the external system (e.g. example.com)' + exit 1 +fi + +KEY=$(echo $2 | tr '[:upper:]' '[:lower:]') +SSM_PATH_DYNAMO="/uc3/dmp/hub/$1/DynamoTableName" +SSM_PATH_EMAIL="/uc3/dmp/hub/$1/AdminEmail" + +echo "Looking for Dynamo Table name at $SSM_PATH_DYNAMO" +echo "----------------------------------------------------------------------------" +DYNAMO_TABLE=$(echo `aws ssm get-parameter --name $SSM_PATH_DYNAMO | jq .Parameter.Value | sed -e "s/\"//g"`) +ADMIN_EMAIL=$(echo `aws ssm get-parameter --name $SSM_PATH_EMAIL | jq .Parameter.Value | sed -e "s/\"//g"`) + +if [ -z $DYNAMO_TABLE ]; then echo "No Dynamo Table name found in SSM!"; exit 1; fi + +echo "Seeding $DYNAMO_TABLE ..." +echo "----------------------------------------------------------------------------" +echo "Creating Provenance item for $2 -> {\"PK\": \"PROVENANCE#$KEY\", \"SK\": \"PROFILE\"}" +# Insert the Provenance record for the DMPTool application +aws dynamodb put-item --table-name $DYNAMO_TABLE \ + --item \ + "{\"PK\":{\"S\":\"PROVENANCE#$KEY\"},\"SK\":{\"S\":\"PROFILE\"},\"contact\":{\"M\":{\"email\":{\"S\":\"$ADMIN_EMAIL\"},\"name\":{\"S\":\"Administrator\"}}},\"description\":{\"S\":\"The $2 $1 system\"},\"downloadUri\":{\"S\":\"https://$3/api/v2/plans/\"},\"homepage\":{\"S\":\"https://$3\"},\"name\":{\"S\":\"$2\"},\"redirectUri\":{\"S\":\"https://$3/callback\"},\"tokenUri\":{\"S\":\"https://$3/oauth/token\"},\"org_access_level\":{\"S\":\"restricted\"}}" diff --git a/templates/cognito-app-client.yaml b/templates/cognito-app-client.yaml new file mode 100644 index 00000000..c6ea1253 --- /dev/null +++ b/templates/cognito-app-client.yaml @@ -0,0 +1,128 @@ +AWSTemplateFormatVersion: '2010-09-09' + +Description: 'Cognito user pool app integration' + +Parameters: + UserPoolId: + Type: 'String' + + Env: + Type: 'String' + Default: 'dev' + + Domain: + Type: 'String' + + Subdomain: + Type: 'String' + + ClientName: + Type: 'String' + + ClientCallbackUri: + Type: 'String' + + OnlyAllowAdminsToCreateUsers: + Type: 'String' + Default: 'false' + AllowedValues: + - 'true' + - 'false' + + UnusedAccountValidityDays: + Type: 'Number' + Default: 14 + + MinimumPasswordLength: + Type: 'Number' + Default: 8 + + TokenValidityUnits: + Type: 'String' + Default: 'minutes' + AllowedValues: + - 'seconds' + - 'minutes' + - 'hours' + - 'days' + + AccessTokenValidity: + Type: 'Number' + Default: 10 + + AuthSessionValidatyMinutes: + Type: 'Number' + Default: 3 + + IdTokenValidity: + Type: 'Number' + Default: 7 + + RefreshTokenValidity: + Type: 'Number' + Default: 10080 # 7 days + + AllowWrite: + Type: 'String' + Default: 'no' + AllowedValues: + - 'yes' + - 'no' + +Conditions: + WriteAllowed: + !Equals [!Ref AllowWrite, 'yes'] + +Resources: + # -------------------------------------------------------------- + # Cognito UserPool application clients + # See: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cognito-userpoolclient.html + # -------------------------------------------------------------- + UserPoolClient: + Type: 'AWS::Cognito::UserPoolClient' + DeletionPolicy: Retain + Properties: + ClientName: !Ref ClientName + UserPoolId: !Ref UserPoolId + ExplicitAuthFlows: + - 'ALLOW_ADMIN_USER_PASSWORD_AUTH' + - 'ALLOW_CUSTOM_AUTH' + - 'ALLOW_USER_SRP_AUTH' + - 'ALLOW_REFRESH_TOKEN_AUTH' + AllowedOAuthFlowsUserPoolClient: true + AllowedOAuthFlows: + - 'client_credentials' + AllowedOAuthScopes: !If + - WriteAllowed + # Allow both read and write + - - !Sub 'https://${Subdomain}.${Domain}/${Env}.read' + - !Sub 'https://${Subdomain}.${Domain}/${Env}.write' + # Only allow read + - - !Sub 'https://${Subdomain}.${Domain}/${Env}.read' + EnableTokenRevocation: true + PreventUserExistenceErrors: 'ENABLED' + GenerateSecret: true + SupportedIdentityProviders: + - 'COGNITO' + # The CF docs indicate that this is not required but I am unable to get a token from Cognito without it + CallbackURLs: + - !Ref ClientCallbackUri + TokenValidityUnits: + AccessToken: !Ref TokenValidityUnits + IdToken: !Ref TokenValidityUnits + RefreshToken: !Ref TokenValidityUnits + # The token issued after the user signs in + AccessTokenValidity: !Ref AccessTokenValidity + # The length (minutes) that a session token for each API request in an authentication flow lasts + AuthSessionValidity: !Ref AuthSessionValidatyMinutes + # The token used during user authentication + IdTokenValidity: !Ref IdTokenValidity + # The length of time the user can refresh their token + RefreshTokenValidity: !Ref RefreshTokenValidity + +Outputs: + LogicalClientId: + Value: !Ref UserPoolClient + + ClientId: + Value: !GetAtt UserPoolClient.ClientId \ No newline at end of file