CVE-2023-51386 (JavaScript, published 2023-12-22T22:15Z)
Description: value: Sandbox Accounts for Events provides multiple, temporary AWS accounts to a number of authenticated users simultaneously via a browser-based GUI. Authenticated users could potentially read data from the events table by sending request payloads to the events API, collecting information on planned events, timeframes, budgets and owner email addresses. This data access may allow users to get insights into upcoming events and join events which they have not been invited to. This issue has been patched in version 1.10.0.
Severity: nan (CVSS v3 base score: 3.3)
Weakness: CWE-269 \u2014 Improper Privilege Management
The product does not properly assign, modify, track, or check privileges for an actor, creating an unintended sphere of control for that actor.
Repository: https://github.com/awslabs/sandbox-accounts-for-events
Files changed:
.eslintignore
CHANGELOG.md
Makefile
amplify.yml
amplify/backend/api/AdminQueries/admin-queries-cloudformation-template.json
amplify/backend/api/safegraphql/cli-inputs.json
amplify/backend/api/safegraphql/schema.graphql
amplify/backend/auth/safeafe5208f/safeafe5208f-cloudformation-template.yml
amplify/backend/auth/userPoolGroups/template.json
amplify/backend/backend-config.json
amplify/backend/custom/cfnAdminUser/cfnAdminUser-cloudformation-template.json
amplify/backend/function/AdminQueries4757b5b2/AdminQueries4757b5b2-cloudformation-template.json
amplify/backend/function/safeAdminApi/safeAdminApi-cloudformation-template.json
amplify/backend/function/safeAdminApi/src/index.js
amplify/backend/function/safeLoginApi/custom-policies.json
amplify/backend/function/safeLoginApi/safeLoginApi-cloudformation-template.json
amplify/backend/function/safeLoginApi/src/index.js
amplify/backend/function/safeLoginApi/src/package-lock.json
amplify/backend/function/safeLoginApi/src/package.json
amplify/backend/function/safeOperatorApi/safeOperatorApi-cloudformation-template.json
amplify/backend/function/safeOperatorApi/src/index.js
amplify/backend/types/amplify-dependent-resources-ref.d.ts
amplify/cli.json
src/App.js
src/graphql/mutations.js
src/graphql/queries.js
src/graphql/schema.json
src/graphql/subscriptions.js
src/pages/DetailEvent.js
src/pages/OverviewEvents.js
src/pages/OverviewUsage.js
src/pages/Statistics.js
src/pages/components/EventLogin.js
src/pages/modals/CreateEventModal.js
src/pages/modals/CreateLeaseModal.js
src/pages/modals/EditEventModal.js
src/pages/modals/EditLeaseModal.js
src/redux/actions/aws_login.js
src/redux/actions/config.js
src/redux/actions/current_user.js
src/redux/actions/events.js
src/redux/actions/leases.js
src/redux/actions/usage.js
Commit message: Reduced end user API permissions


Vulnerable code:
- no changed.

[1.0.0]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.3.0...v1.0.0
	git archive --format zip --output build-cfn/sandbox-accounts-for-events.zip $(branch)
	cd install/cfn-lambda/dceHandleTerraFormDeployment && zip -r ../../../build-cfn/sandbox-accounts-for-events-lambda-terraform.zip . && cd -
	cd install/cfn-lambda/dceHandleAmplifyDeployment && zip -r ../../../build-cfn/sandbox-accounts-for-events-lambda-amplify.zip . && cd -
  "Description": "{\"createdOn\":\"Linux\",\"createdBy\":\"Amplify\",\"createdWith\":\"7.6.15\",\"stackType\":\"api-API Gateway\",\"metadata\":{}}",
  { allow: private, operations: [read] },
        ZipFile:
          Fn::Join:
            - ''
            - - const response = require('cfn-response');
              - const aws = require('aws-sdk');
              - const identity = new aws.CognitoIdentityServiceProvider();
              - exports.handler = (event, context, callback) => {
              - ' if (event.RequestType == ''Delete'') { '
              - '   response.send(event, context, response.SUCCESS, {})'
              - ' }'
              - ' if (event.RequestType == ''Update'' || event.RequestType == ''Create'') {'
              - '   const params = {'
              - '     ClientId: event.ResourceProperties.clientId,'
              - '     UserPoolId: event.ResourceProperties.userpoolId'
              - '   };'
              - '   identity.describeUserPoolClient(params).promise()'
              - '     .then((res) => {'
              - '       response.send(event, context, response.SUCCESS, {''appSecret'': res.UserPoolClient.ClientSecret});'
              - '     })'
              - '     .catch((err) => {'
              - '       response.send(event, context, response.FAILED, {err});'
              - '     });'
              - ' }'
              - '};'
      Runtime: nodejs14.x
  {"createdOn":"Linux","createdBy":"Amplify","createdWith":"7.6.15","stackType":"auth-Cognito","metadata":{}}
                "const AWS = require('aws-sdk');",
                "       const cognitoidentity = new AWS.CognitoIdentity();",
                "    cognitoidentity.setIdentityPoolRoles(params).promise();",
        "Runtime": "nodejs14.x",
  "Description": "{\"createdOn\":\"Linux\",\"createdBy\":\"Amplify\",\"createdWith\":\"7.6.15\",\"stackType\":\"auth-Cognito-UserPool-Groups\",\"metadata\":{}}"
  "auth": {
    "userPoolGroups": {
      "service": "Cognito-UserPool-Groups",
      "providerPlugin": "awscloudformation",
      "dependsOn": [
        {
          "category": "auth",
          "resourceName": "safeafe5208f",
          "attributes": [
            "UserPoolId",
            "AppClientIDWeb",
            "AppClientID",
            "IdentityPoolId"
          ]
        }
      ]
    },
    "safeafe5208f": {
      "service": "Cognito",
      "providerPlugin": "awscloudformation",
      "dependsOn": [],
      "customAuth": false
    }
  },
      "service": "API Gateway",
      "providerPlugin": "awscloudformation",
          "category": "auth",
          "resourceName": "safeafe5208f",
          ]
          "category": "function",
          "resourceName": "AdminQueries4757b5b2",
          ]
      ]
      "service": "AppSync",
      "providerPlugin": "awscloudformation",
          },
          "additionalAuthenticationProviders": []
      }
  "function": {
    "AdminQueries4757b5b2": {
      "service": "Lambda",
      "build": true,
          "category": "auth",
          "resourceName": "safeafe5208f",
            "UserPoolId"
          ]
      ]
    },
    "safeOperatorApi": {
      "build": true,
      "service": "Lambda",
      "dependsOn": []
    },
    "safeLoginApi": {
      "build": true,
      "providerPlugin": "awscloudformation",
      "service": "Lambda",
      "dependsOn": []
    },
    "safeAdminApi": {
      "build": true,
      "providerPlugin": "awscloudformation",
      "service": "Lambda",
      "dependsOn": []
      "service": "customCloudformation",
      "providerPlugin": "awscloudformation",
          "category": "auth",
          "resourceName": "safeafe5208f",
          ]
          "category": "auth",
          "resourceName": "userPoolGroups",
          ]
  "Description": "{\"createdOn\":\"Linux\",\"createdBy\":\"Amplify\",\"createdWith\":\"7.6.15\",\"stackType\":\"custom-customCloudformation\",\"metadata\":{}}"
  "Description": "{\"createdOn\":\"Linux\",\"createdBy\":\"Amplify\",\"createdWith\":\"7.6.15\",\"stackType\":\"function-Lambda\",\"metadata\":{}}",
        "Runtime": "nodejs14.x",
  "Description": "{\"createdOn\":\"Linux\",\"createdBy\":\"Amplify\",\"createdWith\":\"7.6.15\",\"stackType\":\"function-Lambda\",\"metadata\":{}}",
        "Runtime": "nodejs14.x",
const AWS = require("aws-sdk");
    const sts = new AWS.STS({ region: region });
    return sts
        .assumeRole({
        })
        .promise()
            const iam = new AWS.IAM({
            return iam
                .listAttachedRolePolicies({ RoleName: roleName })
                .promise()
                    return iam
                        .listAccountAliases({})
                        .promise()
    let ddb = new AWS.DynamoDB.DocumentClient({
        region: region
    });
    return ddb
        .update({
        })
        .promise()
exports.handler = async ({ arguments: args }, context) => {
  "Description": "{\"createdOn\":\"Linux\",\"createdBy\":\"Amplify\",\"createdWith\":\"7.6.15\",\"stackType\":\"function-Lambda\",\"metadata\":{}}",
        "Runtime": "nodejs14.x",
const getAwsLoginUrlForEvent = ({
    eventId,
    budgetAmount,
    budgetCurrency,
    expiresOn,
    principalId,
    user,
    maxAccounts
}) => {
    if (!principalId)
        return respondWithError("Internal error while trying to log in.", "Parameter 'principalId' missing.");
    if (!budgetAmount)
        return respondWithError("Internal error while trying to log in.", "Parameter 'budgetAmount' missing.");
    if (!budgetCurrency)
        return respondWithError("Internal error while trying to log in.", "Parameter 'budgetCurrency' missing.");
    if (!expiresOn) return respondWithError("Internal error while trying to log in.", "Parameter 'expiresOn' missing.");
    if (!user) return respondWithError("Internal error while trying to log in.", "Parameter 'user' missing.");
    if (!maxAccounts)
        return respondWithError("Internal error while trying to log in.", "Parameter 'maxAccounts' missing.");

    return invokeApi("leases", "GET")
        .then((leases) => {
            if (leases.message) return respondWithError("Failed to list leases.", leases.message);

            let foundLease = leases.find((item) => item.principalId === principalId);
            if (foundLease) {
                switch (foundLease.leaseStatus) {
                    case "Active":
                        return getLeaseLoginUrl(foundLease, user);
                    case "Expired":
                        return respondWithError(
                            "Your AWS account has expired its lifetime and has been terminated now."
                        );
                    case "OverBudget":
                            "Your AWS account has reached its maximum budget and has been terminated now."
                    case "Inactive":
                        return respondWithError("Your AWS account has been manually terminated.");
                    default:
                        return respondWithError("Your account is not available for logging in.");
                }
            } else {
                if (leases.filter((lease) => lease.principalId.startsWith(eventId)).length >= maxAccounts)
                    return respondWithError("No more free AWS accounts available for this event.");
                return invokeApi("leases", "POST", {
                    budgetAmount,
                    expiresOn,
                    principalId,
                    budgetNotificationEmails: [user],
                    budgetCurrency
                    .then((newLease) => {
                        if (newLease.error) {
                            switch (newLease.error.code) {
                                case "ServerError":
                                    if (newLease.error.message === "No Available accounts at this moment")
                                        return respondWithError("No more free AWS accounts available.", newLease.error);
                                    else
                                        return respondWithError(
                                            "Failed to create lease for " + user + ".",
                                            newLease.error
                                        );
                                case "AlreadyExistsError":
                                    return respondWithError(
                                        "Found already existing lease for " + user + ".",
                                        newLease.error
                                    );
                                default:
                                    return respondWithError(
                                        "Failed to create lease for " + user + ".",
                                        newLease.error
                                    );
                            }
                        }
                        return getLeaseLoginUrl(newLease, user);
                    })
                    .catch((error) => respondWithError("Failed to create lease for " + user + ".", error));
            }
        .catch((error) => respondWithError("Failed to list leases.", error));
exports.handler = async ({ arguments: args }) => {
                return getAwsLoginUrlForEvent(params);
    "aws4": "^1.11.0"
  "Description": "{\"createdOn\":\"Linux\",\"createdBy\":\"Amplify\",\"createdWith\":\"7.6.15\",\"stackType\":\"function-Lambda\",\"metadata\":{}}",
        "Runtime": "nodejs14.x",
const AWS = require("aws-sdk");
    if (!user) return respondWithError("Internal error while trying to update lease.", "Parameter 'user' missing.");
    const ddb = new AWS.DynamoDB.DocumentClient({
        region: region
    });
    return ddb
        .update({
        })
        .promise()
    const ddb = new AWS.DynamoDB.DocumentClient({
        region: region
    });
    return ddb
        .delete({
        })
        .promise()
exports.handler = async ({ arguments: args }) => {
    "auth": {
        "userPoolGroups": {
            "adminGroupRole": "string",
            "operatorGroupRole": "string"
        },
        "safeafe5208f": {
            "IdentityPoolId": "string",
            "IdentityPoolName": "string",
            "UserPoolId": "string",
            "UserPoolArn": "string",
            "UserPoolName": "string",
            "AppClientIDWeb": "string",
            "AppClientID": "string"
        }
    "api": {
        "AdminQueries": {
            "RootUrl": "string",
            "ApiName": "string",
            "ApiId": "string"
        },
        "safegraphql": {
            "GraphQLAPIIdOutput": "string",
            "GraphQLAPIEndpointOutput": "string"
        }
    "function": {
        "AdminQueries4757b5b2": {
            "Name": "string",
            "Arn": "string",
            "Region": "string",
            "LambdaExecutionRole": "string"
        },
        "safeOperatorApi": {
            "Name": "string",
            "Arn": "string",
            "Region": "string",
            "LambdaExecutionRole": "string"
        },
        "safeLoginApi": {
            "Name": "string",
            "Arn": "string",
            "Region": "string",
            "LambdaExecutionRole": "string"
        },
        "safeAdminApi": {
            "Name": "string",
            "Arn": "string",
            "Region": "string",
            "LambdaExecutionRole": "string"
        }
    "custom": {
        "cfnAdminUser": {
            "AdminUserEmailAddress": "string"
        }
      "useexperimentalpipelinedtransformer": false,
      "showfieldauthnotification": false
        if (authStatus === "authenticated") {
  query safeLoginApi($action: String, $paramJson: String) {
  query safeAdminApi($action: String, $paramJson: String) {
  query safeOperatorApi($action: String, $paramJson: String) {
          "args" : [ ],
            "kind" : "OBJECT",
            "name" : "Event",
          "isDeprecated" : false,
          "deprecationReason" : null
          "name" : "onUpdateEvent",
          "args" : [ ],
            "kind" : "OBJECT",
            "name" : "Event",
          "isDeprecated" : false,
          "deprecationReason" : null
        }, {
          "name" : "onDeleteEvent",
          "args" : [ ],
            "kind" : "OBJECT",
            "name" : "Event",
          "isDeprecated" : false,
          "deprecationReason" : null
          "name" : "onCreateConfig",
          "args" : [ ],
            "kind" : "OBJECT",
            "name" : "Config",
          "isDeprecated" : false,
          "deprecationReason" : null
          "name" : "onUpdateConfig",
          "args" : [ ],
            "kind" : "OBJECT",
            "name" : "Config",
          "isDeprecated" : false,
          "deprecationReason" : null
          "name" : "onDeleteConfig",
          "args" : [ ],
            "kind" : "OBJECT",
            "name" : "Config",
          "isDeprecated" : false,
          "deprecationReason" : null
        "inputFields" : null,
        "interfaces" : [ ],
        "name" : "ModelFloatInput",
          "name" : "attributeExists",
            "kind" : "SCALAR",
            "name" : "Boolean",
            "ofType" : null
          "name" : "attributeType",
            "kind" : "ENUM",
            "name" : "ModelAttributeTypes",
            "ofType" : null
        "name" : "ModelBooleanInput",
            "name" : "Boolean",
            "name" : "Boolean",
      }, {
        "name" : "aws_subscribe",
        "description" : "Tells the service which mutation triggers this subscription.",
        "locations" : [ "FIELD_DEFINITION" ],
        "args" : [ {
          "name" : "mutations",
          "description" : "List of mutations which will trigger this subscription when they are called.",
          "type" : {
            "kind" : "LIST",
            "name" : null,
            "ofType" : {
              "kind" : "SCALAR",
              "name" : "String",
              "ofType" : null
            }
          },
          "defaultValue" : null
        } ],
        "onOperation" : false,
        "onFragment" : false,
        "onField" : false
        "name" : "deprecated",
        "description" : null,
        "locations" : [ "FIELD_DEFINITION", "ENUM_VALUE" ],
          "name" : "reason",
          "description" : null,
            "kind" : "SCALAR",
            "name" : "String",
            "ofType" : null
          "defaultValue" : "\"No longer supported\""
        "name" : "aws_cognito_user_pools",
        "description" : "Tells the service this field/object has access authorized by a Cognito User Pools token.",
        "locations" : [ "OBJECT", "FIELD_DEFINITION" ],
          "name" : "cognito_groups",
          "description" : "List of cognito user pool groups which have access on this field",
        "name" : "aws_lambda",
        "description" : "Tells the service this field/object has access authorized by a Lambda Authorizer.",
        "locations" : [ "OBJECT", "FIELD_DEFINITION" ],
        "args" : [ ],
        "onOperation" : false,
        "onFragment" : false,
        "onField" : false
      }, {
        "name" : "aws_publish",
        "description" : "Tells the service which subscriptions will be published to when this mutation is called. This directive is deprecated use @aws_susbscribe directive instead.",
          "name" : "subscriptions",
          "description" : "List of subscriptions which will be published to when this mutation is called.",
        "name" : "aws_iam",
        "description" : "Tells the service this field/object has access authorized by sigv4 signing.",
        "name" : "aws_api_key",
        "description" : "Tells the service this field/object has access authorized by an API key.",
  subscription OnCreateEvent {
    onCreateEvent {
  subscription OnUpdateEvent {
    onUpdateEvent {
  subscription OnDeleteEvent {
    onDeleteEvent {
  subscription OnCreateConfig {
    onCreateConfig {
  subscription OnUpdateConfig {
    onUpdateConfig {
  subscription OnDeleteConfig {
    onDeleteConfig {
                            {Item.eventBudget + " " + Config.BUDGET_CURRENCY}
                            {Item.eventSpend + " " + Config.BUDGET_CURRENCY}
                        cell: (item) => item.eventSpend + " " + Config.BUDGET_CURRENCY
                    {item.eventBudget + " " + Config.BUDGET_CURRENCY}
                    {item.eventSpend + " " + Config.BUDGET_CURRENCY}
                    cell: (item) => item.costAmount.toFixed(2) + " " + Config.BUDGET_CURRENCY
                        <Container header={<Header>AWS service spend in {Config.BUDGET_CURRENCY}</Header>}>
import moment from "moment";
import { fetchAwsLoginUrl } from "../../redux/actions/aws_login";
import { fetchEndUserEvent } from "../../redux/actions/events";
    const Event = useSelector((state) => state.events);
        dispatch({ type: "event/dismiss" });
        dispatch(fetchEndUserEvent(value));
        if (!valueChangedOnce && isEmpty(Event.item) && urlParamEventId && User.isLoggedIn) {
            dispatch(fetchEndUserEvent(urlParamEventId));
    }, [Event.item, urlParamEventId, dispatch, valueChangedOnce, User]);
        if (!Event.item.eventStatus) return;
        switch (Event.item.eventStatus) {
    }, [Event.item, dispatch]);
        dispatch({ type: "event/dismiss" });
                {!Event.item.id ? (
                        <Button variant="primary" onClick={submit} loading={Event.status === "loading"}>
                            Welcome to "{Event.item.eventName}"
                            onClick={() =>
                                dispatch(
                                    fetchAwsLoginUrl({
                                        principalId:
                                            Event.item.id +
                                            Config.EVENT_PRINCIPAL_SEPARATOR +
                                            User.email.replace(/[^a-zA-Z0-9]/g, Config.EVENT_EMAIL_SUBST),
                                        budgetAmount: Event.item.eventBudget,
                                        budgetCurrency: Config.BUDGET_CURRENCY,
                                        user: User.email,
                                        expiresOn: moment
                                            .unix(Event.item.eventOn)
                                            .add(Event.item.eventDays, "days")
                                            .add(Event.item.eventHours, "hours")
                                            .unix(),
                                        maxAccounts: Event.item.maxAccounts,
                                        eventId: Event.item.id
                                    })
                                )
                            }
                        label={"Budget in " + Config.BUDGET_CURRENCY}
            let user = newValue.user.replace(/[^a-zA-Z0-9]/g, Config.EVENT_EMAIL_SUBST);
                newValue.principalId = newValue.eventId + Config.EVENT_PRINCIPAL_SEPARATOR + user;
                        label={"Budget in " + Config.BUDGET_CURRENCY}
                            label={"Budget in " + Config.BUDGET_CURRENCY}
                            label={"Budget in " + Config.BUDGET_CURRENCY}
    url: ""
    BUDGET_CURRENCY: "USD",
    EVENT_PRINCIPAL_SEPARATOR: "__",
    EVENT_EMAIL_SUBST: "+",
        case "event/loading":
            return {
                ...state,
                status: "loading"
            };
            new RegExp("^(" + action.config.EVENT_ID_REGEX + ")" + action.config.EVENT_PRINCIPAL_SEPARATOR + "\\S{5,}$")
                        budgetCurrency: config.BUDGET_CURRENCY
        eventId: item.principalId.includes(action.config.EVENT_PRINCIPAL_SEPARATOR) ? item.principalId.substring(0, action.config.EVENT_ID_LENGTH) : ""

Fixed code:
amplify-codegen-temp/models/models

## [1.1.0] - 2023-11-04
### Added
- no additions.

### Changed
- Updated Lambda functions to Node18 and aws-sdk v3
- Security upgrade: Blocked ListEvents API call for end users to remove potential data leak
- Security upgrade: Blocked API calls requesting an AWS account for a non-existent event id
- Security upgrade: Reduced number of possible parameters for end user API calls to necessary minimum, retrieve event management metadata from backend and auth token only.

### Removed
- nothing removed.


- no changes.
	zip -FSr build-cfn/sandbox-accounts-for-events.zip . -x amplify/#current-cloud-backend/\* build/\* build-cfn/\* \*dist/\* \*.DS_Store\* \*.vscode/\* \*.git/\* src/aws-exports.json\* \*amplify-meta.json\* amplify/team-provider-info.json\* \*awscloudformation\* \*node_modules\* amplify/.config/local-\*
	cd install/cfn-lambda/dceHandleTerraFormDeployment && zip -FSr ../../../build-cfn/sandbox-accounts-for-events-lambda-terraform.zip . && cd -
	cd install/cfn-lambda/dceHandleAmplifyDeployment && zip -FSr ../../../build-cfn/sandbox-accounts-for-events-lambda-amplify.zip . && cd -
        - aws ssm put-parameter --cli-input-json "{\"Type\":\"String\",\"Name\":\"/amplify/${AWS_APP_ID}/main/AMPLIFY_function_safeLoginApi_dceApiGw\",\"Value\":\"${DCE_API_GW}\",\"Overwrite\":true}"
        - aws ssm put-parameter --cli-input-json "{\"Type\":\"String\",\"Name\":\"/amplify/${AWS_APP_ID}/main/AMPLIFY_function_safeOperatorApi_dceApiGw\",\"Value\":\"${DCE_API_GW}\",\"Overwrite\":true}"
        - aws ssm put-parameter --cli-input-json "{\"Type\":\"String\",\"Name\":\"/amplify/${AWS_APP_ID}/main/AMPLIFY_function_safeAdminApi_dceApiGw\",\"Value\":\"${DCE_API_GW}\",\"Overwrite\":true}"
        - aws ssm put-parameter --cli-input-json "{\"Type\":\"String\",\"Name\":\"/amplify/${AWS_APP_ID}/main/AMPLIFY_function_safeOperatorApi_dceLeasesTable\",\"Value\":\"${DCE_LEASES_TABLE}\",\"Overwrite\":true}"
        - aws ssm put-parameter --cli-input-json "{\"Type\":\"String\",\"Name\":\"/amplify/${AWS_APP_ID}/main/AMPLIFY_function_safeAdminApi_dceAccountsTable\",\"Value\":\"${DCE_ACCOUNTS_TABLE}\",\"Overwrite\":true}"
  "Description": "{\"createdOn\":\"Mac\",\"createdBy\":\"Amplify\",\"createdWith\":\"12.7.1\",\"stackType\":\"api-API Gateway\",\"metadata\":{}}",
{
  "version": 1,
  "serviceConfiguration": {
    "serviceName": "AppSync",
    "defaultAuthType": {
      "mode": "AMAZON_COGNITO_USER_POOLS",
      "cognitoUserPoolId": "authsafeafe5208f"
    },
    "conflictResolution": {},
    "apiName": "safegraphql"
  }
}
        ZipFile: | 
          const response = require('cfn-response');
          const { CognitoIdentityProviderClient, DescribeUserPoolClientCommand } = require("@aws-sdk/client-cognito-identity-provider");
          const identity = new CognitoIdentityProviderClient();
          exports.handler = (event, context, callback) => {
            console.log("Lambda invoked with the following parameters: ", event, context);
            if (event.RequestType == "Delete") { 
              response.send(event, context, response.SUCCESS, {})
            }
            if (event.RequestType == "Update" || event.RequestType == "Create") {
              const params = {
                ClientId: event.ResourceProperties.clientId,
                UserPoolId: event.ResourceProperties.userpoolId
              };
              identity.send(new DescribeUserPoolClientCommand(params))
                .then((res) => {
                  response.send(event, context, response.SUCCESS, {"appSecret": res.UserPoolClient.ClientSecret});
                })
                .catch((err) => {
                  response.send(event, context, response.FAILED, {err});
              });
            }
          };
      Runtime: nodejs18.x
  {"createdOn":"Mac","createdBy":"Amplify","createdWith":"12.7.1","stackType":"auth-Cognito","metadata":{}}
                "const { CognitoIdentityClient, SetIdentityPoolRolesCommand } = require('@aws-sdk/client-cognito-identity');",
                "console.log('Lambda invoked with the following parameters: ', event, context);",
                "       const cognitoidentity = new CognitoIdentityClient();",
                "    cognitoidentity.send(new SetIdentityPoolRolesCommand(params));",
        "Runtime": "nodejs18.x",
  "Description": "{\"createdOn\":\"Mac\",\"createdBy\":\"Amplify\",\"createdWith\":\"12.7.1\",\"stackType\":\"auth-Cognito-UserPool-Groups\",\"metadata\":{}}"
          ],
          "category": "auth",
          "resourceName": "safeafe5208f"
          ],
          "category": "function",
          "resourceName": "AdminQueries4757b5b2"
      ],
      "providerPlugin": "awscloudformation",
      "service": "API Gateway"
          "additionalAuthenticationProviders": [],
          }
      },
      "providerPlugin": "awscloudformation",
      "service": "AppSync"
  "auth": {
    "safeafe5208f": {
      "customAuth": false,
      "dependsOn": [],
      "service": "Cognito"
    },
    "userPoolGroups": {
            "UserPoolId",
            "AppClientIDWeb",
            "AppClientID",
            "IdentityPoolId"
          ],
          "category": "auth",
          "resourceName": "safeafe5208f"
      ],
      "service": "Cognito-UserPool-Groups"
          ],
          "category": "auth",
          "resourceName": "safeafe5208f"
          ],
          "category": "auth",
          "resourceName": "userPoolGroups"
        }
      ],
      "providerPlugin": "awscloudformation",
      "service": "customCloudformation"
    }
  },
  "function": {
    "AdminQueries4757b5b2": {
      "build": true,
      "dependsOn": [
        {
          "attributes": [
            "UserPoolId"
          ],
          "category": "auth",
          "resourceName": "safeafe5208f"
        }
      ],
      "providerPlugin": "awscloudformation",
      "service": "Lambda"
    },
    "safeAdminApi": {
      "build": true,
      "dependsOn": [],
      "providerPlugin": "awscloudformation",
      "service": "Lambda"
    },
    "safeLoginApi": {
      "build": true,
      "dependsOn": [],
      "providerPlugin": "awscloudformation",
      "service": "Lambda"
    },
    "safeOperatorApi": {
      "build": true,
      "dependsOn": [],
      "providerPlugin": "awscloudformation",
      "service": "Lambda"
    }
  },
  "parameters": {
    "AMPLIFY_function_AdminQueries4757b5b2_deploymentBucketName": {
      "usedBy": [
        {
          "category": "function",
          "resourceName": "AdminQueries4757b5b2"
        }
      ]
    },
    "AMPLIFY_function_AdminQueries4757b5b2_s3Key": {
      "usedBy": [
        {
          "category": "function",
          "resourceName": "AdminQueries4757b5b2"
        }
      ]
    },
    "AMPLIFY_function_safeAdminApi_dceAccountsTable": {
      "usedBy": [
        {
          "category": "function",
          "resourceName": "safeAdminApi"
        }
      ]
    },
    "AMPLIFY_function_safeAdminApi_dceApiGw": {
      "usedBy": [
        {
          "category": "function",
          "resourceName": "safeAdminApi"
        }
      ]
    },
    "AMPLIFY_function_safeAdminApi_deploymentBucketName": {
      "usedBy": [
        {
          "category": "function",
          "resourceName": "safeAdminApi"
        }
      ]
    },
    "AMPLIFY_function_safeAdminApi_s3Key": {
      "usedBy": [
        {
          "category": "function",
          "resourceName": "safeAdminApi"
        }
      ]
    },
    "AMPLIFY_function_safeLoginApi_dceApiGw": {
      "usedBy": [
        {
          "category": "function",
          "resourceName": "safeLoginApi"
        }
      ]
    },
    "AMPLIFY_function_safeLoginApi_deploymentBucketName": {
      "usedBy": [
        {
          "category": "function",
          "resourceName": "safeLoginApi"
        }
      ]
    },
    "AMPLIFY_function_safeLoginApi_s3Key": {
      "usedBy": [
        {
          "category": "function",
          "resourceName": "safeLoginApi"
        }
      ]
    },
    "AMPLIFY_function_safeOperatorApi_dceApiGw": {
      "usedBy": [
        {
          "category": "function",
          "resourceName": "safeOperatorApi"
        }
      ]
    },
    "AMPLIFY_function_safeOperatorApi_dceLeasesTable": {
      "usedBy": [
        {
          "category": "function",
          "resourceName": "safeOperatorApi"
        }
      ]
    },
    "AMPLIFY_function_safeOperatorApi_deploymentBucketName": {
      "usedBy": [
        {
          "category": "function",
          "resourceName": "safeOperatorApi"
        }
      ]
    },
    "AMPLIFY_function_safeOperatorApi_s3Key": {
      "usedBy": [
        {
          "category": "function",
          "resourceName": "safeOperatorApi"
  "Description": "{\"createdOn\":\"Mac\",\"createdBy\":\"Amplify\",\"createdWith\":\"12.7.1\",\"stackType\":\"custom-customCloudformation\",\"metadata\":{}}"
  "Description": "{\"createdOn\":\"Mac\",\"createdBy\":\"Amplify\",\"createdWith\":\"12.7.1\",\"stackType\":\"function-Lambda\",\"metadata\":{}}",
        "Runtime": "nodejs18.x",
    },
    "LambdaExecutionRoleArn": {
      "Value": {
        "Fn::GetAtt": [
          "LambdaExecutionRole",
          "Arn"
        ]
      }
  "Description": "{\"createdOn\":\"Mac\",\"createdBy\":\"Amplify\",\"createdWith\":\"12.7.1\",\"stackType\":\"function-Lambda\",\"metadata\":{}}",
        "Runtime": "nodejs18.x",
    },
    "LambdaExecutionRoleArn": {
      "Value": {
        "Fn::GetAtt": [
          "LambdaExecutionRole",
          "Arn"
        ]
      }
const { IAMClient, ListAttachedRolePoliciesCommand, ListAccountAliasesCommand } = require('@aws-sdk/client-iam');
const { STSClient, AssumeRoleCommand } = require('@aws-sdk/client-sts');
const { DynamoDBClient } = require('@aws-sdk/client-dynamodb');
const { DynamoDBDocumentClient, UpdateCommand } = require('@aws-sdk/lib-dynamodb');

const stsClient = new STSClient({ region });
const ddbClient = new DynamoDBClient({ region });
const ddbDocClient = DynamoDBDocumentClient.from(ddbClient);

    return stsClient
        .send(new AssumeRoleCommand({
        }))
            const iamClient = new IAMClient({
            return iamClient
                .send(new ListAttachedRolePoliciesCommand({ RoleName: roleName }))
                    return iamClient
                        .send(new ListAccountAliasesCommand({}))
    return ddbDocClient
        .send(new UpdateCommand({
        }))
exports.handler = async (event, context) => {
    console.log("Lambda invoked with the following parameters: ", event, context)
    let args = event.arguments

  },
  {
    "Effect": "Allow",
    "Action": [
        "dynamodb:UpdateItem",
        "dynamodb:GetItem",
        "dynamodb:ListTables"
    ],
    "Resource": ["arn:aws:dynamodb:*:*:table/*"]
  },
  {
    "Effect": "Allow",
    "Action": [
        "cognito-idp:ListUserPools",
        "cognito-idp:AdminGetUser"
    ],
    "Resource": ["*"]
  "Description": "{\"createdOn\":\"Mac\",\"createdBy\":\"Amplify\",\"createdWith\":\"12.7.1\",\"stackType\":\"function-Lambda\",\"metadata\":{}}",
        "Runtime": "nodejs18.x",
    },
    "LambdaExecutionRoleArn": {
      "Value": {
        "Fn::GetAtt": [
          "LambdaExecutionRole",
          "Arn"
        ]
      }
const moment = require("moment");
const { DynamoDBClient, ListTablesCommand } = require('@aws-sdk/client-dynamodb');
const { DynamoDBDocumentClient, GetCommand } = require('@aws-sdk/lib-dynamodb');
const { CognitoIdentityProviderClient, ListUserPoolsCommand, AdminGetUserCommand } = require('@aws-sdk/client-cognito-identity-provider');


const ddbClient = new DynamoDBClient({ region });
const ddbDocClient = DynamoDBDocumentClient.from(ddbClient);
let eventsTable

const cognitoClient = new CognitoIdentityProviderClient({ region })
let userPoolId
const getEndUserEvent = ({ id }) => {
    if (!eventsTable)
        return respondWithError("Failed to get data for event ID " + id + ".")

    return ddbDocClient.send(new GetCommand({ TableName: eventsTable, Key: { id } }))
    .then((response) => {
        if (response.Item) {
            return respondWithSuccess("Successfully got DynamoDB event item",{
                id: response.Item.id,
                eventStatus: response.Item.eventStatus,
                eventName: response.Item.eventName
            })
        } else { 
            return respondWithError('Could not find matching event for event ID "' + id + '". Please double check if your event ID is correct or ask your event operator for help.')
        }
    })
    .catch((error) =>
        respondWithError("Failed to get data for event ID " + id + ".", error)
    );
};


const getAwsLoginUrlForEvent = async ({eventId}, event) => {
    

    if (!userPoolId)
        return respondWithError("Failed to get user authentication pool, cannot claim an AWS account.")

    if (!eventsTable)
        return respondWithError("Failed to get data for event ID " + eventId + ".")

    return cognitoClient.send(new AdminGetUserCommand({
            UserPoolId: userPoolId,
            Username: event.identity.username
        }))
        .then(cognitoResponse => {
            const user = cognitoResponse.UserAttributes.find(attr => attr.Name == "email").Value
            let principalId = eventId + "__" + user.replace(/[^a-zA-Z0-9]/g, "+")
            return ddbDocClient.send(new GetCommand({ TableName: eventsTable, Key: { id: eventId } }))
                .then(response => {
                    if (response.Item) {
                        return invokeApi("leases", "GET")
                            .then((leases) => {
                                if (leases.message) return respondWithError("Failed to list leases.", leases.message);
                    
                                let foundLease = leases.find((item) => item.principalId === principalId);
                                if (foundLease) {
                                    switch (foundLease.leaseStatus) {
                                        case "Active":
                                            return getLeaseLoginUrl(foundLease, user);
                                        case "Expired":
                                            return respondWithError(
                                                "Your AWS account has expired its lifetime and has been terminated now."
                                            );
                                        case "OverBudget":
                                            return respondWithError(
                                                "Your AWS account has reached its maximum budget and has been terminated now."
                                            );
                                        case "Inactive":
                                            return respondWithError("Your AWS account has been manually terminated.");
                                        default:
                                            return respondWithError("Your account is not available for logging in.");
                                    }
                                } else {
                                    if (leases.filter((lease) => lease.principalId.startsWith(eventId)).length >= response.Item.maxAccounts)
                                        return respondWithError("No more free AWS accounts available for this event.");
                                    return invokeApi("leases", "POST", {
                                        budgetAmount: response.Item.budgetAmount,
                                        expiresOn: moment
                                            .unix(response.Item.eventOn)
                                            .add(response.Item.eventDays, "days")
                                            .add(response.Item.eventHours, "hours")
                                            .unix(),
                                        principalId,
                                        budgetNotificationEmails: [user],
                                        budgetCurrency: "USD"
                                    })
                                        .then((newLease) => {
                                            if (newLease.error) {
                                                switch (newLease.error.code) {
                                                    case "ServerError":
                                                        if (newLease.error.message === "No Available accounts at this moment")
                                                            return respondWithError("No more free AWS accounts available.", newLease.error);
                                                        else
                                                            return respondWithError(
                                                                "Failed to create lease for " + user + ".",
                                                                newLease.error
                                                            );
                                                    case "AlreadyExistsError":
                                                        return respondWithError(
                                                            "Found already existing lease for " + user + ".",
                                                            newLease.error
                                                        );
                                                    default:
                                                        return respondWithError(
                                                            "Failed to create lease for " + user + ".",
                                                            newLease.error
                                                        );
                                                }
                                            }
                                            return getLeaseLoginUrl(newLease, user);
                                        })
                                        .catch((error) => respondWithError("Failed to create lease for " + user + ".", error));
                                }
                            })
                            .catch((error) => respondWithError("Failed to list leases.", error));
                
                    } else {
                            "Your EventId " + eventId + " is invalid. Please contact your event operator for help."
                    }
                .catch((error) => respondWithError("Failed to get data for event ID " + eventId + ".", error));
        .catch(error => respondWithError("Failed to get user authentication data, cannot claim an AWS account.", error))
exports.handler = async (event, context) => {
    console.log("Lambda invoked with the following parameters: ", event, context)
    let args = event.arguments

    
    if (!eventsTable) {
        const tables = await ddbClient.send(new ListTablesCommand())
        eventsTable = tables.TableNames.find(name => name.startsWith("Event-"))
    }

    if (!userPoolId) {
        const userPools = await cognitoClient.send(new ListUserPoolsCommand({ MaxResults: 10 }))
        userPoolId = userPools.UserPools.find(userPool => userPool.Name.startsWith("safeafe5208f")).Id
    }
            case "getEndUserEvent":
                return getEndUserEvent(params);
                return getAwsLoginUrlForEvent(params, event);
    },
    "moment": {
      "version": "2.29.4",
      "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
      "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w=="
    "aws4": "^1.11.0",
    "moment": "^2.29.4"
  "Description": "{\"createdOn\":\"Mac\",\"createdBy\":\"Amplify\",\"createdWith\":\"12.7.1\",\"stackType\":\"function-Lambda\",\"metadata\":{}}",
        "Runtime": "nodejs18.x",
    },
    "LambdaExecutionRoleArn": {
      "Value": {
        "Fn::GetAtt": [
          "LambdaExecutionRole",
          "Arn"
        ]
      }
const { DynamoDBClient } = require('@aws-sdk/client-dynamodb');
const { DynamoDBDocumentClient, UpdateCommand, DeleteCommand } = require('@aws-sdk/lib-dynamodb');

const ddbClient = new DynamoDBClient({ region });
const ddbDocClient = DynamoDBDocumentClient.from(ddbClient);

    if (!user) 
        return respondWithError("Internal error while trying to update lease.", "Parameter 'user' missing.");

    return ddbDocClient
        .send(new UpdateCommand({
        }))
    return ddbDocClient
        .send(new DeleteCommand({
        }))
exports.handler = async (event, context) => {
    console.log("Lambda invoked with the following parameters: ", event, context)
    let args = event.arguments

  "api": {
    "AdminQueries": {
      "ApiId": "string",
      "ApiName": "string",
      "RootUrl": "string"
    "safegraphql": {
      "GraphQLAPIEndpointOutput": "string",
      "GraphQLAPIIdOutput": "string"
    }
  },
  "auth": {
    "safeafe5208f": {
      "AppClientID": "string",
      "AppClientIDWeb": "string",
      "IdentityPoolId": "string",
      "IdentityPoolName": "string",
      "UserPoolArn": "string",
      "UserPoolId": "string",
      "UserPoolName": "string"
    },
    "userPoolGroups": {
      "adminGroupRole": "string",
      "operatorGroupRole": "string"
    }
  },
  "custom": {
    "cfnAdminUser": {
      "AdminUserEmailAddress": "string"
    }
  },
  "function": {
    "AdminQueries4757b5b2": {
      "Arn": "string",
      "LambdaExecutionRole": "string",
      "LambdaExecutionRoleArn": "string",
      "Name": "string",
      "Region": "string"
    },
    "safeAdminApi": {
      "Arn": "string",
      "LambdaExecutionRole": "string",
      "LambdaExecutionRoleArn": "string",
      "Name": "string",
      "Region": "string"
    "safeLoginApi": {
      "Arn": "string",
      "LambdaExecutionRole": "string",
      "LambdaExecutionRoleArn": "string",
      "Name": "string",
      "Region": "string"
    "safeOperatorApi": {
      "Arn": "string",
      "LambdaExecutionRole": "string",
      "LambdaExecutionRoleArn": "string",
      "Name": "string",
      "Region": "string"
  }
      "useexperimentalpipelinedtransformer": true,
      "showfieldauthnotification": false,
      "transformerversion": 2,
      "suppressschemamigrationprompt": true,
      "securityEnhancementNotification": false
        if (authStatus === "authenticated" && user) {
      __typename
      __typename
      __typename
      __typename
      __typename
      __typename
  query SafeLoginApi($action: String, $paramJson: String) {
  query SafeAdminApi($action: String, $paramJson: String) {
  query SafeOperatorApi($action: String, $paramJson: String) {
      __typename
        __typename
      __typename
      __typename
        __typename
      __typename
          "args" : [ {
            "name" : "filter",
            "description" : null,
            "type" : {
              "kind" : "INPUT_OBJECT",
              "name" : "ModelSubscriptionEventFilterInput",
              "ofType" : null
            },
            "defaultValue" : null
          } ],
          "type" : {
            "kind" : "OBJECT",
            "name" : "Event",
            "ofType" : null
          },
          "isDeprecated" : false,
          "deprecationReason" : null
        }, {
          "name" : "onUpdateEvent",
          "description" : null,
          "args" : [ {
            "name" : "filter",
            "description" : null,
            "type" : {
              "kind" : "INPUT_OBJECT",
              "name" : "ModelSubscriptionEventFilterInput",
              "ofType" : null
            },
            "defaultValue" : null
          } ],
          "type" : {
            "kind" : "OBJECT",
            "name" : "Event",
            "ofType" : null
          },
          "isDeprecated" : false,
          "deprecationReason" : null
        }, {
          "name" : "onDeleteEvent",
          "description" : null,
          "args" : [ {
            "name" : "filter",
            "description" : null,
            "type" : {
              "kind" : "INPUT_OBJECT",
              "name" : "ModelSubscriptionEventFilterInput",
              "ofType" : null
            },
            "defaultValue" : null
          } ],
          "type" : {
            "kind" : "OBJECT",
            "name" : "Event",
            "ofType" : null
          },
          "isDeprecated" : false,
          "deprecationReason" : null
        }, {
          "name" : "onCreateConfig",
          "description" : null,
          "args" : [ {
            "name" : "filter",
            "description" : null,
            "type" : {
              "kind" : "INPUT_OBJECT",
              "name" : "ModelSubscriptionConfigFilterInput",
              "ofType" : null
            },
            "defaultValue" : null
          } ],
          "type" : {
            "kind" : "OBJECT",
            "name" : "Config",
            "ofType" : null
          },
          "isDeprecated" : false,
          "deprecationReason" : null
        }, {
          "name" : "onUpdateConfig",
          "description" : null,
          "args" : [ {
            "name" : "filter",
            "description" : null,
            "type" : {
              "kind" : "INPUT_OBJECT",
              "name" : "ModelSubscriptionConfigFilterInput",
              "ofType" : null
            },
            "defaultValue" : null
          } ],
          "type" : {
            "kind" : "OBJECT",
            "name" : "Config",
            "ofType" : null
          },
          "isDeprecated" : false,
          "deprecationReason" : null
        }, {
          "name" : "onDeleteConfig",
          "description" : null,
          "args" : [ {
            "name" : "filter",
            "description" : null,
            "type" : {
              "kind" : "INPUT_OBJECT",
              "name" : "ModelSubscriptionConfigFilterInput",
              "ofType" : null
            },
            "defaultValue" : null
          } ],
          "type" : {
            "kind" : "OBJECT",
            "name" : "Config",
            "ofType" : null
          },
          "isDeprecated" : false,
          "deprecationReason" : null
        } ],
        "inputFields" : null,
        "interfaces" : [ ],
        "enumValues" : null,
        "possibleTypes" : null
      }, {
        "kind" : "INPUT_OBJECT",
        "name" : "ModelSubscriptionEventFilterInput",
        "description" : null,
        "fields" : null,
        "inputFields" : [ {
          "name" : "id",
          "description" : null,
          "type" : {
            "kind" : "INPUT_OBJECT",
            "name" : "ModelSubscriptionIDInput",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "eventName",
          "description" : null,
          "type" : {
            "kind" : "INPUT_OBJECT",
            "name" : "ModelSubscriptionStringInput",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "eventOn",
          "description" : null,
          "type" : {
            "kind" : "INPUT_OBJECT",
            "name" : "ModelSubscriptionIntInput",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "eventDays",
          "description" : null,
          "type" : {
            "kind" : "INPUT_OBJECT",
            "name" : "ModelSubscriptionIntInput",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "eventHours",
          "description" : null,
          "type" : {
            "kind" : "INPUT_OBJECT",
            "name" : "ModelSubscriptionIntInput",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "eventOwner",
          "description" : null,
          "type" : {
            "kind" : "INPUT_OBJECT",
            "name" : "ModelSubscriptionStringInput",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "maxAccounts",
          "description" : null,
          "type" : {
            "kind" : "INPUT_OBJECT",
            "name" : "ModelSubscriptionIntInput",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "eventBudget",
          "description" : null,
          "type" : {
            "kind" : "INPUT_OBJECT",
            "name" : "ModelSubscriptionIntInput",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "eventStatus",
          "description" : null,
          "type" : {
            "kind" : "INPUT_OBJECT",
            "name" : "ModelSubscriptionStringInput",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "and",
          "description" : null,
          "type" : {
            "kind" : "LIST",
            "name" : null,
            "ofType" : {
              "kind" : "INPUT_OBJECT",
              "name" : "ModelSubscriptionEventFilterInput",
              "ofType" : null
            }
          },
          "defaultValue" : null
        }, {
          "name" : "or",
          "description" : null,
          "type" : {
            "kind" : "LIST",
            "name" : null,
            "ofType" : {
              "kind" : "INPUT_OBJECT",
              "name" : "ModelSubscriptionEventFilterInput",
              "ofType" : null
            }
          },
          "defaultValue" : null
        } ],
        "interfaces" : null,
        "enumValues" : null,
        "possibleTypes" : null
      }, {
        "kind" : "INPUT_OBJECT",
        "name" : "ModelSubscriptionIDInput",
        "description" : null,
        "fields" : null,
        "inputFields" : [ {
          "name" : "ne",
          "description" : null,
          "type" : {
            "kind" : "SCALAR",
            "name" : "ID",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "eq",
          "description" : null,
          "type" : {
            "kind" : "SCALAR",
            "name" : "ID",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "le",
          "description" : null,
          "type" : {
            "kind" : "SCALAR",
            "name" : "ID",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "lt",
          "description" : null,
          "type" : {
            "kind" : "SCALAR",
            "name" : "ID",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "ge",
          "description" : null,
          "type" : {
            "kind" : "SCALAR",
            "name" : "ID",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "gt",
          "description" : null,
          "type" : {
            "kind" : "SCALAR",
            "name" : "ID",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "contains",
          "description" : null,
          "type" : {
            "kind" : "SCALAR",
            "name" : "ID",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "notContains",
          "description" : null,
          "type" : {
            "kind" : "SCALAR",
            "name" : "ID",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "between",
          "description" : null,
          "type" : {
            "kind" : "LIST",
            "name" : null,
            "ofType" : {
              "kind" : "SCALAR",
              "name" : "ID",
              "ofType" : null
            }
          },
          "defaultValue" : null
        }, {
          "name" : "beginsWith",
          "description" : null,
          "type" : {
            "kind" : "SCALAR",
            "name" : "ID",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "in",
          "description" : null,
          "type" : {
            "kind" : "LIST",
            "name" : null,
            "ofType" : {
              "kind" : "SCALAR",
              "name" : "ID",
              "ofType" : null
            }
          },
          "defaultValue" : null
        }, {
          "name" : "notIn",
          "description" : null,
          "type" : {
            "kind" : "LIST",
            "name" : null,
            "ofType" : {
              "kind" : "SCALAR",
              "name" : "ID",
              "ofType" : null
            }
          },
          "defaultValue" : null
        } ],
        "interfaces" : null,
        "enumValues" : null,
        "possibleTypes" : null
      }, {
        "kind" : "INPUT_OBJECT",
        "name" : "ModelSubscriptionStringInput",
        "description" : null,
        "fields" : null,
        "inputFields" : [ {
          "name" : "ne",
          "description" : null,
          "type" : {
            "kind" : "SCALAR",
            "name" : "String",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "eq",
          "description" : null,
          "type" : {
            "kind" : "SCALAR",
            "name" : "String",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "le",
          "description" : null,
          "type" : {
            "kind" : "SCALAR",
            "name" : "String",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "lt",
          "description" : null,
          "type" : {
            "kind" : "SCALAR",
            "name" : "String",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "ge",
          "description" : null,
          "type" : {
            "kind" : "SCALAR",
            "name" : "String",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "gt",
          "description" : null,
          "type" : {
            "kind" : "SCALAR",
            "name" : "String",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "contains",
          "description" : null,
          "type" : {
            "kind" : "SCALAR",
            "name" : "String",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "notContains",
          "description" : null,
          "type" : {
            "kind" : "SCALAR",
            "name" : "String",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "between",
          "description" : null,
          "type" : {
            "kind" : "LIST",
            "name" : null,
            "ofType" : {
              "kind" : "SCALAR",
              "name" : "String",
              "ofType" : null
            }
          },
          "defaultValue" : null
        }, {
          "name" : "beginsWith",
          "description" : null,
          "type" : {
            "kind" : "SCALAR",
            "name" : "String",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "in",
          "description" : null,
          "type" : {
            "kind" : "LIST",
            "name" : null,
            "ofType" : {
              "kind" : "SCALAR",
              "name" : "String",
              "ofType" : null
            }
          },
          "defaultValue" : null
        }, {
          "name" : "notIn",
          "description" : null,
          "type" : {
            "kind" : "LIST",
            "name" : null,
            "ofType" : {
              "kind" : "SCALAR",
              "name" : "String",
              "ofType" : null
            }
          },
          "defaultValue" : null
        } ],
        "interfaces" : null,
        "enumValues" : null,
        "possibleTypes" : null
      }, {
        "kind" : "INPUT_OBJECT",
        "name" : "ModelSubscriptionIntInput",
        "description" : null,
        "fields" : null,
        "inputFields" : [ {
          "name" : "ne",
          "description" : null,
          "type" : {
            "kind" : "SCALAR",
            "name" : "Int",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "eq",
          "description" : null,
          "type" : {
            "kind" : "SCALAR",
            "name" : "Int",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "le",
          "description" : null,
          "type" : {
            "kind" : "SCALAR",
            "name" : "Int",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "lt",
          "description" : null,
          "type" : {
            "kind" : "SCALAR",
            "name" : "Int",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "ge",
          "description" : null,
          "type" : {
            "kind" : "SCALAR",
            "name" : "Int",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "gt",
          "description" : null,
          "type" : {
            "kind" : "SCALAR",
            "name" : "Int",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "between",
          "description" : null,
          "type" : {
            "kind" : "LIST",
            "name" : null,
            "ofType" : {
              "kind" : "SCALAR",
              "name" : "Int",
              "ofType" : null
            }
          },
          "defaultValue" : null
        }, {
          "name" : "in",
          "description" : null,
          "type" : {
            "kind" : "LIST",
            "name" : null,
            "ofType" : {
              "kind" : "SCALAR",
              "name" : "Int",
              "ofType" : null
            }
          },
          "defaultValue" : null
        }, {
          "name" : "notIn",
          "description" : null,
          "type" : {
            "kind" : "LIST",
            "name" : null,
            "ofType" : {
              "kind" : "SCALAR",
              "name" : "Int",
              "ofType" : null
            }
          },
          "defaultValue" : null
        } ],
        "interfaces" : null,
        "enumValues" : null,
        "possibleTypes" : null
      }, {
        "kind" : "INPUT_OBJECT",
        "name" : "ModelSubscriptionConfigFilterInput",
        "description" : null,
        "fields" : null,
        "inputFields" : [ {
          "name" : "id",
          "description" : null,
          "type" : {
            "kind" : "INPUT_OBJECT",
            "name" : "ModelSubscriptionIDInput",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "config",
          "description" : null,
          "type" : {
            "kind" : "INPUT_OBJECT",
            "name" : "ModelSubscriptionStringInput",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "and",
          "description" : null,
          "type" : {
            "kind" : "LIST",
            "name" : null,
            "ofType" : {
              "kind" : "INPUT_OBJECT",
              "name" : "ModelSubscriptionConfigFilterInput",
              "ofType" : null
            }
          },
          "defaultValue" : null
        }, {
          "name" : "or",
          "description" : null,
          "type" : {
            "kind" : "LIST",
            "name" : null,
            "ofType" : {
              "kind" : "INPUT_OBJECT",
              "name" : "ModelSubscriptionConfigFilterInput",
              "ofType" : null
            }
          },
          "defaultValue" : null
        } ],
        "interfaces" : null,
        "enumValues" : null,
        "possibleTypes" : null
      }, {
        "kind" : "INPUT_OBJECT",
        "name" : "ModelSubscriptionBooleanInput",
        "description" : null,
        "fields" : null,
        "inputFields" : [ {
          "name" : "ne",
          "description" : null,
            "kind" : "SCALAR",
            "name" : "Boolean",
          "defaultValue" : null
          "name" : "eq",
            "kind" : "SCALAR",
            "name" : "Boolean",
          "defaultValue" : null
        } ],
        "interfaces" : null,
        "enumValues" : null,
        "possibleTypes" : null
      }, {
        "kind" : "INPUT_OBJECT",
        "name" : "ModelBooleanInput",
        "description" : null,
        "fields" : null,
        "inputFields" : [ {
          "name" : "ne",
            "kind" : "SCALAR",
            "name" : "Boolean",
          "defaultValue" : null
          "name" : "eq",
            "kind" : "SCALAR",
            "name" : "Boolean",
          "defaultValue" : null
          "name" : "attributeExists",
            "kind" : "SCALAR",
            "name" : "Boolean",
          "defaultValue" : null
          "name" : "attributeType",
            "kind" : "ENUM",
            "name" : "ModelAttributeTypes",
          "defaultValue" : null
        "interfaces" : null,
        "name" : "ModelSubscriptionFloatInput",
          "name" : "in",
            "kind" : "LIST",
            "name" : null,
            "ofType" : {
              "kind" : "SCALAR",
              "name" : "Float",
              "ofType" : null
            }
          "name" : "notIn",
            "kind" : "LIST",
            "name" : null,
            "ofType" : {
              "kind" : "SCALAR",
              "name" : "Float",
              "ofType" : null
            }
        "name" : "ModelFloatInput",
            "name" : "Float",
            "name" : "Float",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "le",
          "description" : null,
          "type" : {
            "kind" : "SCALAR",
            "name" : "Float",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "lt",
          "description" : null,
          "type" : {
            "kind" : "SCALAR",
            "name" : "Float",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "ge",
          "description" : null,
          "type" : {
            "kind" : "SCALAR",
            "name" : "Float",
            "ofType" : null
          },
          "defaultValue" : null
        }, {
          "name" : "gt",
          "description" : null,
          "type" : {
            "kind" : "SCALAR",
            "name" : "Float",
        }, {
          "name" : "between",
          "description" : null,
          "type" : {
            "kind" : "LIST",
            "name" : null,
            "ofType" : {
              "kind" : "SCALAR",
              "name" : "Float",
              "ofType" : null
            }
          },
          "defaultValue" : null
        "name" : "aws_cognito_user_pools",
        "description" : "Tells the service this field/object has access authorized by a Cognito User Pools token.",
        "locations" : [ "OBJECT", "FIELD_DEFINITION" ],
          "name" : "cognito_groups",
          "description" : "List of cognito user pool groups which have access on this field",
            "kind" : "LIST",
            "name" : null,
            "ofType" : {
              "kind" : "SCALAR",
              "name" : "String",
              "ofType" : null
            }
          "defaultValue" : null
        "name" : "aws_publish",
        "description" : "Tells the service which subscriptions will be published to when this mutation is called. This directive is deprecated use @aws_susbscribe directive instead.",
        "locations" : [ "FIELD_DEFINITION" ],
          "name" : "subscriptions",
          "description" : "List of subscriptions which will be published to when this mutation is called.",
      }, {
        "name" : "aws_api_key",
        "description" : "Tells the service this field/object has access authorized by an API key.",
        "locations" : [ "OBJECT", "FIELD_DEFINITION" ],
        "args" : [ ],
        "onOperation" : false,
        "onFragment" : false,
        "onField" : false
        "name" : "aws_subscribe",
        "description" : "Tells the service which mutation triggers this subscription.",
          "name" : "mutations",
          "description" : "List of mutations which will trigger this subscription when they are called.",
        "name" : "aws_lambda",
        "description" : "Tells the service this field/object has access authorized by a Lambda Authorizer.",
        "name" : "aws_iam",
        "description" : "Tells the service this field/object has access authorized by sigv4 signing.",
      }, {
        "name" : "deprecated",
        "description" : null,
        "locations" : [ "FIELD_DEFINITION", "ENUM_VALUE" ],
        "args" : [ {
          "name" : "reason",
          "description" : null,
          "type" : {
            "kind" : "SCALAR",
            "name" : "String",
            "ofType" : null
          },
          "defaultValue" : "\"No longer supported\""
        } ],
        "onOperation" : false,
        "onFragment" : false,
        "onField" : false
  subscription OnCreateEvent($filter: ModelSubscriptionEventFilterInput) {
    onCreateEvent(filter: $filter) {
      __typename
  subscription OnUpdateEvent($filter: ModelSubscriptionEventFilterInput) {
    onUpdateEvent(filter: $filter) {
      __typename
  subscription OnDeleteEvent($filter: ModelSubscriptionEventFilterInput) {
    onDeleteEvent(filter: $filter) {
      __typename
  subscription OnCreateConfig($filter: ModelSubscriptionConfigFilterInput) {
    onCreateConfig(filter: $filter) {
      __typename
  subscription OnUpdateConfig($filter: ModelSubscriptionConfigFilterInput) {
    onUpdateConfig(filter: $filter) {
      __typename
  subscription OnDeleteConfig($filter: ModelSubscriptionConfigFilterInput) {
    onDeleteConfig(filter: $filter) {
      __typename
                            {Item.eventBudget + " USD"}
                            {Item.eventSpend + " USD"}
                        cell: (item) => item.eventSpend + " USD"
                    {item.eventBudget + " USD"}
                    {item.eventSpend + " USD"}
                    cell: (item) => item.costAmount.toFixed(2) + " USD"
                        <Container header={<Header>AWS service spend in USD</Header>}>
import { fetchAwsLoginUrl, getEndUserEvent } from "../../redux/actions/aws_login";
        dispatch({ type: "aws_login/event_dismiss" });
        dispatch(getEndUserEvent(value));
        if (!valueChangedOnce && isEmpty(AwsLogin.event) && urlParamEventId && User.isLoggedIn) {
            dispatch(getEndUserEvent(urlParamEventId));
    }, [AwsLogin.event, urlParamEventId, dispatch, valueChangedOnce, User]);
        if (!AwsLogin.event.eventStatus) return;
        switch (AwsLogin.event.eventStatus) {
    }, [AwsLogin.event, dispatch]);
        dispatch({ type: "aws_login/event_dismiss" });
                {!AwsLogin.event.id ? (
                        <Button variant="primary" onClick={submit} loading={AwsLogin.event_status === "loading"}>
                            Welcome to "{AwsLogin.event.eventName}"
                            onClick={() => dispatch(fetchAwsLoginUrl({ eventId: AwsLogin.event.id })) }
                        label={"Budget in USD"}
            let user = newValue.user.replace(/[^a-zA-Z0-9]/g, "+");
                newValue.principalId = newValue.eventId + "__" + user;
                        label={"Budget in USD"}
                            label={"Budget in USD"}
                            label={"Budget in USD"}
    event_status: "idle",
    url: "",
    event: {}
            return {
                ...state,
                url: "",
                status: "hidden"
            };
                
        case "aws_login/event_loading":
            return {
                ...state,
                event_status: "loading"
            };
        case "aws_login/event_loaded":
            return {
                ...state,
                event_status: "idle",
                event: action.payload
            };
        case "aws_login/event_loadError":
        case "aws_login/event_dismiss":
export const getEndUserEvent = (id) => async (dispatch) => {
    dispatch({ type: "aws_login/event_loading" });
    try {
        const response = await API.graphql(
            graphqlOperation(queries.safeLoginApi, {
                action: "getEndUserEvent",
                paramJson: JSON.stringify({id})
            })
        );
        const payload = JSON.parse(response.data.safeLoginApi);
        if (!payload || payload.status === "error") {
            throw payload;
        }
        dispatch({ type: "aws_login/event_loaded", payload: payload.body });
        dispatch({ type: "notification/dismiss" });
    } catch (error) {
        console.error(error);
        dispatch({ type: "aws_login/event_loadError" });
        dispatch({ type: "notification/error", message: error.message });
    }
};


    if (!data.attributes)
        return
        case "event/loading":
            new RegExp("^(" + action.config.EVENT_ID_REGEX + ")__\\S{5,}$")
                        budgetCurrency: "USD"
        eventId: item.principalId.includes("__") ? item.principalId.substring(0, action.config.EVENT_ID_LENGTH) : ""