UNPKG

@aws-amplify/graphql-api-construct

Version:

AppSync GraphQL Api Construct using Amplify GraphQL Transformer.

183 lines 30.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.convertAuthorizationModesToTransformerAuthConfig = exports.getAdditionalAuthenticationTypes = exports.validateAuthorizationModes = void 0; const lodash_1 = require("lodash"); const aws_iam_1 = require("aws-cdk-lib/aws-iam"); /** * Validates authorization modes. * * Rules: * 1. Validates that deprecated settings ('iamConfig.authenticatedUserRole', 'iamConfig.unauthenticatedUserRole', * 'iamConfig.identityPoolId', 'iamConfig.allowListedRoles' and 'adminRoles') are mutually exclusive with new settings that * replaced them ('iamConfig.enableIamAuthorizationMode' and any of 'authorizationModes.identityPoolConfig') * 2. If deprecated identity pool settings are used ('iamConfig.authenticatedUserRole', 'iamConfig.unauthenticatedUserRole', * and 'iamConfig.identityPoolId') validate that all are provided. */ const validateAuthorizationModes = (authorizationModes) => { const hasAnyDeprecatedIdentityPoolSetting = authorizationModes.iamConfig?.authenticatedUserRole || authorizationModes.iamConfig?.unauthenticatedUserRole || authorizationModes.iamConfig?.identityPoolId; const hasAllDeprecatedIdentityPoolSettings = authorizationModes.iamConfig?.authenticatedUserRole && authorizationModes.iamConfig?.unauthenticatedUserRole && authorizationModes.iamConfig?.identityPoolId; const hasDeprecatedIamSettings = authorizationModes.iamConfig?.authenticatedUserRole || authorizationModes.iamConfig?.unauthenticatedUserRole || authorizationModes.iamConfig?.identityPoolId || authorizationModes.iamConfig?.allowListedRoles || authorizationModes.adminRoles; const hasUnDeprecatedIamSettings = typeof authorizationModes.iamConfig?.enableIamAuthorizationMode !== 'undefined' || authorizationModes.identityPoolConfig; if (hasDeprecatedIamSettings && hasUnDeprecatedIamSettings) { throw new Error('Invalid authorization modes configuration provided. ' + "Deprecated IAM configuration cannot be used with identity pool configuration or when 'enableIamAuthorizationMode' is specified."); } if (hasAnyDeprecatedIdentityPoolSetting && !hasAllDeprecatedIdentityPoolSettings) { throw new Error("'authorizationModes.iamConfig.authenticatedUserRole', 'authorizationModes.iamConfig.unauthenticatedUserRole' and" + " 'authorizationModes.iamConfig.identityPoolId' must be provided."); } }; exports.validateAuthorizationModes = validateAuthorizationModes; /** * Converts a single auth mode config into the amplify-internal representation. * @param authMode the auth mode to convert into the Appsync CDK representation. */ const convertAuthModeToAuthProvider = (authMode) => { const authenticationType = authMode.type; switch (authMode.type) { case 'API_KEY': return { authenticationType, apiKeyConfig: { description: authMode.description, apiKeyExpirationDays: authMode.expires.toDays(), }, }; case 'AWS_IAM': return { authenticationType }; case 'AMAZON_COGNITO_USER_POOLS': return { authenticationType, userPoolConfig: { userPoolId: authMode.userPool.userPoolId, }, }; case 'OPENID_CONNECT': return { authenticationType, openIDConnectConfig: { name: authMode.oidcProviderName, issuerUrl: authMode.oidcIssuerUrl, clientId: authMode.clientId, iatTTL: authMode.tokenExpiryFromIssue.toMilliseconds(), authTTL: authMode.tokenExpiryFromAuth.toMilliseconds(), }, }; case 'AWS_LAMBDA': return { authenticationType, lambdaAuthorizerConfig: { lambdaArn: authMode.function.functionArn, lambdaFunction: authMode.function.functionName, ttlSeconds: authMode.ttl.toSeconds(), }, }; default: throw new Error(`Unexpected AuthMode type ${authenticationType} encountered.`); } }; /** * Given an appsync auth configuration, convert into appsync auth provider setup. * @param authModes the config to transform * @returns the appsync config object. */ const convertAuthConfigToAppSyncAuth = (authModes) => { // Convert auth modes into an array of appsync configs, and include the type so we can use that for switching and partitioning later. const authConfig = [ authModes.apiKeyConfig ? { type: 'API_KEY', ...authModes.apiKeyConfig } : null, authModes.lambdaConfig ? { type: 'AWS_LAMBDA', ...authModes.lambdaConfig } : null, authModes.oidcConfig ? { type: 'OPENID_CONNECT', ...authModes.oidcConfig } : null, authModes.userPoolConfig ? { type: 'AMAZON_COGNITO_USER_POOLS', ...authModes.userPoolConfig } : null, authModes.iamConfig || authModes.identityPoolConfig ? { type: 'AWS_IAM' } : null, ].filter((mode) => mode); const authProviders = authConfig.map(convertAuthModeToAuthProvider); // Validate inputs make sense, needs at least one mode, and a default mode is required if there are multiple modes. if (authProviders.length === 0) { throw new Error('At least one auth config is required, but none were found.'); } if (authProviders.length > 1 && !authModes.defaultAuthorizationMode) { throw new Error('A defaultAuthorizationMode is required if multiple authorization modes are configured.'); } // Enable appsync to invoke a provided lambda authorizer function authModes.lambdaConfig?.function.addPermission('appsync-auth-invoke', { principal: new aws_iam_1.ServicePrincipal('appsync.amazonaws.com'), action: 'lambda:InvokeFunction', }); // In the case of a single mode, defaultAuthorizationMode is not required, just use the provided value. if (authProviders.length === 1) { return { defaultAuthentication: authProviders[0], additionalAuthenticationProviders: [], }; } // For multi-auth, partition into the defaultMode and non-default modes. return { defaultAuthentication: authProviders.filter((provider) => provider.authenticationType === authModes.defaultAuthorizationMode)[0], additionalAuthenticationProviders: authProviders.filter((provider) => provider.authenticationType !== authModes.defaultAuthorizationMode), }; }; /** * Transforms additionalAuthenticationTypes for storage in CFN output */ const getAdditionalAuthenticationTypes = (cfnGraphqlApi) => { if (!(0, lodash_1.isArray)(cfnGraphqlApi.additionalAuthenticationProviders)) { return undefined; } return cfnGraphqlApi.additionalAuthenticationProviders .map((additionalAuthenticationProvider) => additionalAuthenticationProvider.authenticationType) .join(','); }; exports.getAdditionalAuthenticationTypes = getAdditionalAuthenticationTypes; /** * Convert the list of auth modes into the necessary flags and params (effectively a reducer on the rule list) * @param authModes the list of auth modes configured on the API. * @returns the AuthConfig which the AuthTransformer needs as input. */ const convertAuthorizationModesToTransformerAuthConfig = (authModes) => ({ authConfig: convertAuthConfigToAppSyncAuth(authModes), authSynthParameters: getSynthParameters(authModes), }); exports.convertAuthorizationModesToTransformerAuthConfig = convertAuthorizationModesToTransformerAuthConfig; /** * Merge iamConfig allowListedRoles with deprecated adminRoles property, converting to strings. * @param authModes the auth modes provided to the construct. * @returns the list of admin roles as strings to pass into the transformer */ const getAllowListedRoles = (authModes) => [...(authModes?.iamConfig?.allowListedRoles ?? []), ...(authModes.adminRoles ?? [])].map((roleOrRoleName) => { if (typeof roleOrRoleName === 'string' || roleOrRoleName instanceof String) { return roleOrRoleName; } return roleOrRoleName.roleName; }); /** * Transform the authorization config into the transformer synth parameters pertaining to auth. * @param authModes the auth modes provided to the construct. * @returns a record of params to be consumed by the transformer. */ const getSynthParameters = (authModes) => ({ adminRoles: getAllowListedRoles(authModes), identityPoolId: authModes.identityPoolConfig?.identityPoolId ?? authModes.iamConfig?.identityPoolId, enableIamAccess: authModes.iamConfig?.enableIamAuthorizationMode, ...(authModes.userPoolConfig ? { userPoolId: authModes.userPoolConfig.userPool.userPoolId } : {}), ...(authModes?.identityPoolConfig ? { authenticatedUserRoleName: authModes.identityPoolConfig.authenticatedUserRole.roleName, unauthenticatedUserRoleName: authModes.identityPoolConfig.unauthenticatedUserRole.roleName, } : {}), ...(authModes?.iamConfig && authModes?.iamConfig.authenticatedUserRole && authModes?.iamConfig.unauthenticatedUserRole ? { authenticatedUserRoleName: authModes.iamConfig.authenticatedUserRole?.roleName, unauthenticatedUserRoleName: authModes.iamConfig.unauthenticatedUserRole?.roleName, } : {}), }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aG9yaXphdGlvbi1tb2Rlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9pbnRlcm5hbC9hdXRob3JpemF0aW9uLW1vZGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUVBLG1DQUFpQztBQUNqQyxpREFBOEQ7QUFnQjlEOzs7Ozs7Ozs7R0FTRztBQUNJLE1BQU0sMEJBQTBCLEdBQUcsQ0FBQyxrQkFBc0MsRUFBUSxFQUFFO0lBQ3pGLE1BQU0sbUNBQW1DLEdBQ3ZDLGtCQUFrQixDQUFDLFNBQVMsRUFBRSxxQkFBcUI7UUFDbkQsa0JBQWtCLENBQUMsU0FBUyxFQUFFLHVCQUF1QjtRQUNyRCxrQkFBa0IsQ0FBQyxTQUFTLEVBQUUsY0FBYyxDQUFDO0lBQy9DLE1BQU0sb0NBQW9DLEdBQ3hDLGtCQUFrQixDQUFDLFNBQVMsRUFBRSxxQkFBcUI7UUFDbkQsa0JBQWtCLENBQUMsU0FBUyxFQUFFLHVCQUF1QjtRQUNyRCxrQkFBa0IsQ0FBQyxTQUFTLEVBQUUsY0FBYyxDQUFDO0lBQy9DLE1BQU0sd0JBQXdCLEdBQzVCLGtCQUFrQixDQUFDLFNBQVMsRUFBRSxxQkFBcUI7UUFDbkQsa0JBQWtCLENBQUMsU0FBUyxFQUFFLHVCQUF1QjtRQUNyRCxrQkFBa0IsQ0FBQyxTQUFTLEVBQUUsY0FBYztRQUM1QyxrQkFBa0IsQ0FBQyxTQUFTLEVBQUUsZ0JBQWdCO1FBQzlDLGtCQUFrQixDQUFDLFVBQVUsQ0FBQztJQUNoQyxNQUFNLDBCQUEwQixHQUM5QixPQUFPLGtCQUFrQixDQUFDLFNBQVMsRUFBRSwwQkFBMEIsS0FBSyxXQUFXLElBQUksa0JBQWtCLENBQUMsa0JBQWtCLENBQUM7SUFFM0gsSUFBSSx3QkFBd0IsSUFBSSwwQkFBMEIsRUFBRSxDQUFDO1FBQzNELE1BQU0sSUFBSSxLQUFLLENBQ2Isc0RBQXNEO1lBQ3BELGlJQUFpSSxDQUNwSSxDQUFDO0lBQ0osQ0FBQztJQUVELElBQUksbUNBQW1DLElBQUksQ0FBQyxv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QUF1QixFQUFFLENBQUMsQ0FBQztJQUNsRixVQUFVLEVBQUUsbUJBQW1CLENBQUMsU0FBUyxDQUFDO0lBQzFDLGNBQWMsRUFBRSxTQUFTLENBQUMsa0JBQWtCLEVBQUUsY0FBYyxJQUFJLFNBQVMsQ0FBQyxTQUFTLEVBQUUsY0FBYztJQUNuRyxlQUFlLEVBQUUsU0FBUyxDQUFDLFNBQVMsRUFBRSwwQkFBMEI7SUFDaEUsR0FBRyxDQUFDLFNBQVMsQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLEVBQUUsVUFBVSxFQUFFLFNBQVMsQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDakcsR0FBRyxDQUFDLFNBQVMsRUFBRSxrQkFBa0I7UUFDL0IsQ0FBQyxDQUFDO1lBQ0UseUJBQXlCLEVBQUUsU0FBUyxDQUFDLGtCQUFrQixDQUFDLHFCQUFxQixDQUFDLFFBQVE7WUFDdEYsMkJBQTJCLEVBQUUsU0FBUyxDQUFDLGtCQUFrQixDQUFDLHVCQUF1QixDQUFDLFFBQVE7U0FDM0Y7UUFDSCxDQUFDLENBQUMsRUFBRSxDQUFDO0lBQ1AsR0FBRyxDQUFDLFNBQVMsRUFBRSxTQUFTLElBQUksU0FBUyxFQUFFLFNBQVMsQ0FBQyxxQkFBcUIsSUFBSSxTQUFTLEVBQUUsU0FBUyxDQUFDLHVCQUF1QjtRQUNwSCxDQUFDLENBQUM7WUFDRSx5QkFBeUIsRUFBRSxTQUFTLENBQUMsU0FBUyxDQUFDLHFCQUFxQixFQUFFLFFBQVE7WUFDOUUsMkJBQTJCLEVBQUUsU0FBUyxDQUFDLFNBQVMsQ0FBQyx1QkFBdUIsRUFBRSxRQUFRO1NBQ25GO1FBQ0gsQ0FBQyxDQUFDLEVBQUUsQ0FBQztDQUNSLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFwcFN5bmNBdXRoQ29uZmlndXJhdGlvbiwgQXBwU3luY0F1dGhDb25maWd1cmF0aW9uRW50cnksIFN5bnRoUGFyYW1ldGVycyB9IGZyb20gJ0Bhd3MtYW1wbGlmeS9ncmFwaHFsLXRyYW5zZm9ybWVyLWludGVyZmFjZXMnO1xuaW1wb3J0IHsgQ2ZuR3JhcGhRTEFwaSB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1hcHBzeW5jJztcbmltcG9ydCB7IGlzQXJyYXkgfSBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IHsgSVJvbGUsIFNlcnZpY2VQcmluY2lwYWwgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtaWFtJztcbmltcG9ydCB7XG4gIEF1dGhvcml6YXRpb25Nb2RlcyxcbiAgQXBpS2V5QXV0aG9yaXphdGlvbkNvbmZpZyxcbiAgTGFtYmRhQXV0aG9yaXphdGlvbkNvbmZpZyxcbiAgT0lEQ0F1dGhvcml6YXRpb25Db25maWcsXG4gIFVzZXJQb29sQXV0aG9yaXphdGlvbkNvbmZpZyxcbn0gZnJvbSAnLi4vdHlwZXMnO1xuXG50eXBlIEF1dGhvcml6YXRpb25Db25maWdNb2RlID1cbiAgfCB7IHR5cGU6ICdBV1NfSUFNJyB9XG4gIHwgKFVzZXJQb29sQXV0aG9yaXphdGlvbkNvbmZpZyAmIHsgdHlwZTogJ0FNQVpPTl9DT0dOSVRPX1VTRVJfUE9PTFMnIH0pXG4gIHwgKE9JRENBdXRob3JpemF0aW9uQ29uZmlnICYgeyB0eXBlOiAnT1BFTklEX0NPTk5FQ1QnIH0pXG4gIHwgKEFwaUtleUF1dGhvcml6YXRpb25Db25maWcgJiB7IHR5cGU6ICdBUElfS0VZJyB9KVxuICB8IChMYW1iZGFBdXRob3JpemF0aW9uQ29uZmlnICYgeyB0eXBlOiAnQVdTX0xBTUJEQScgfSk7XG5cbi8qKlxuICogVmFsaWRhdGVzIGF1dGhvcml6YXRpb24gbW9kZXMuXG4gKlxuICogUnVsZXM6XG4gKiAxLiBWYWxpZGF0ZXMgdGhhdCBkZXByZWNhdGVkIHNldHRpbmdzICgnaWFtQ29uZmlnLmF1dGhlbnRpY2F0ZWRVc2VyUm9sZScsICdpYW1Db25maWcudW5hdXRoZW50aWNhdGVkVXNlclJvbGUnLFxuICogICAgJ2lhbUNvbmZpZy5pZGVudGl0eVBvb2xJZCcsICdpYW1Db25maWcuYWxsb3dMaXN0ZWRSb2xlcycgYW5kICdhZG1pblJvbGVzJykgYXJlIG11dHVhbGx5IGV4Y2x1c2l2ZSB3aXRoIG5ldyBzZXR0aW5ncyB0aGF0XG4gKiAgICByZXBsYWNlZCB0aGVtICgnaWFtQ29uZmlnLmVuYWJsZUlhbUF1dGhvcml6YXRpb25Nb2RlJyBhbmQgYW55IG9mICdhdXRob3JpemF0aW9uTW9kZXMuaWRlbnRpdHlQb29sQ29uZmlnJylcbiAqIDIuIElmIGRlcHJlY2F0ZWQgaWRlbnRpdHkgcG9vbCBzZXR0aW5ncyBhcmUgdXNlZCAoJ2lhbUNvbmZpZy5hdXRoZW50aWNhdGVkVXNlclJvbGUnLCAnaWFtQ29uZmlnLnVuYXV0aGVudGljYXRlZFVzZXJSb2xlJyxcbiAqICAgIGFuZCAnaWFtQ29uZmlnLmlkZW50aXR5UG9vbElkJykgdmFsaWRhdGUgdGhhdCBhbGwgYXJlIHByb3ZpZGVkLlxuICovXG5leHBvcnQgY29uc3QgdmFsaWRhdGVBdXRob3JpemF0aW9uTW9kZXMgPSAoYXV0aG9yaXphdGlvbk1vZGVzOiBBdXRob3JpemF0aW9uTW9kZXMpOiB2b2lkID0+IHtcbiAgY29uc3QgaGFzQW55RGVwcmVjYXRlZElkZW50aXR5UG9vbFNldHRpbmcgPVxuICAgIGF1dGhvcml6YXRpb25Nb2Rlcy5pYW1Db25maWc/LmF1dGhlbnRpY2F0ZWRVc2VyUm9sZSB8fFxuICAgIGF1dGhvcml6YXRpb25Nb2Rlcy5pYW1Db25maWc/LnVuYXV0aGVudGljYXRlZFVzZXJSb2xlIHx8XG4gICAgYXV0aG9yaXphdGlvbk1vZGVzLmlhbUNvbmZpZz8uaWRlbnRpdHlQb29sSWQ7XG4gIGNvbnN0IGhhc0FsbERlcHJlY2F0ZWRJZGVudGl0eVBvb2xTZXR0aW5ncyA9XG4gICAgYXV0aG9yaXphdGlvbk1vZGVzLmlhbUNvbmZpZz8uYXV0aGVudGljYXRlZFVzZXJSb2xlICYmXG4gICAgYXV0aG9yaXphdGlvbk1vZGVzLmlhbUNvbmZpZz8udW5hdXRoZW50aWNhdGVkVXNlclJvbGUgJiZcbiAgICBhdXRob3JpemF0aW9uTW9kZXMuaWFtQ29uZmlnPy5pZGVudGl0eVBvb2xJZDtcbiAgY29uc3QgaGFzRGVwcmVjYXRlZElhbVNldHRpbmdzID1cbiAgICBhdXRob3JpemF0aW9uTW9kZXMuaWFtQ29uZmlnPy5hdXRoZW50aWNhdGVkVXNlclJvbGUgfHxcbiAgICBhdXRob3JpemF0aW9uTW9kZXMuaWFtQ29uZmlnPy51bmF1dGhlbnRpY2F0ZWRVc2VyUm9sZSB8fFxuICAgIGF1dGhvcml6YXRpb25Nb2Rlcy5pYW1Db25maWc/LmlkZW50aXR5UG9vbElkIHx8XG4gICAgYXV0aG9yaXphdGlvbk1vZGVzLmlhbUNvbmZpZz8uYWxsb3dMaXN0ZWRSb2xlcyB8fFxuICAgIGF1dGhvcml6YXRpb25Nb2Rlcy5hZG1pblJvbGVzO1xuICBjb25zdCBoYXNVbkRlcHJlY2F0ZWRJYW1TZXR0aW5ncyA9XG4gICAgdHlwZW9mIGF1dGhvcml6YXRpb25Nb2Rlcy5pYW1Db25maWc/LmVuYWJsZUlhbUF1dGhvcml6YXRpb25Nb2RlICE9PSAndW5kZWZpbmVkJyB8fCBhdXRob3JpemF0aW9uTW9kZXMuaWRlbnRpdHlQb29sQ29uZmlnO1xuXG4gIGlmIChoYXNEZXByZWNhdGVkSWFtU2V0dGluZ3MgJiYgaGFzVW5EZXByZWNhdGVkSWFtU2V0dGluZ3MpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAnSW52YWxpZCBhdXRob3JpemF0aW9uIG1vZGVzIGNvbmZpZ3VyYXRpb24gcHJvdmlkZWQuICcgK1xuICAgICAgICBcIkRlcHJlY2F0ZWQgSUFNIGNvbmZpZ3VyYXRpb24gY2Fubm90IGJlIHVzZWQgd2l0aCBpZGVudGl0eSBwb29sIGNvbmZpZ3VyYXRpb24gb3Igd2hlbiAnZW5hYmxlSWFtQXV0aG9yaXphdGlvbk1vZGUnIGlzIHNwZWNpZmllZC5cIixcbiAgICApO1xuICB9XG5cbiAgaWYgKGhhc0FueURlcHJlY2F0ZWRJZGVudGl0eVBvb2xTZXR0aW5nICYmICFoYXNBbGxEZXByZWNhdGVkSWRlbnRpdHlQb29sU2V0dGluZ3MpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBcIidhdXRob3JpemF0aW9uTW9kZXMuaWFtQ29uZmlnLmF1dGhlbnRpY2F0ZWRVc2VyUm9sZScsICdhdXRob3JpemF0aW9uTW9kZXMuaWFtQ29uZmlnLnVuYXV0aGVudGljYXRlZFVzZXJSb2xlJyBhbmRcIiArXG4gICAgICAgIFwiICdhdXRob3JpemF0aW9uTW9kZXMuaWFtQ29uZmlnLmlkZW50aXR5UG9vbElkJyBtdXN0IGJlIHByb3ZpZGVkLlwiLFxuICAgICk7XG4gIH1cbn07XG5cbi8qKlxuICogQ29udmVydHMgYSBzaW5nbGUgYXV0aCBtb2RlIGNvbmZpZyBpbnRvIHRoZSBhbXBsaWZ5LWludGVybmFsIHJlcHJlc2VudGF0aW9uLlxuICogQHBhcmFtIGF1dGhNb2RlIHRoZSBhdXRoIG1vZGUgdG8gY29udmVydCBpbnRvIHRoZSBBcHBzeW5jIENESyByZXByZXNlbnRhdGlvbi5cbiAqL1xuY29uc3QgY29udmVydEF1dGhNb2RlVG9BdXRoUHJvdmlkZXIgPSAoYXV0aE1vZGU6IEF1dGhvcml6YXRpb25Db25maWdNb2RlKTogQXBwU3luY0F1dGhDb25maWd1cmF0aW9uRW50cnkgPT4ge1xuICBjb25zdCBhdXRoZW50aWNhdGlvblR5cGUgPSBhdXRoTW9kZS50eXBlO1xuICBzd2l0Y2ggKGF1dGhNb2RlLnR5cGUpIHtcbiAgICBjYXNlICdBUElfS0VZJzpcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGF1dGhlbnRpY2F0aW9uVHlwZSxcbiAgICAgICAgYXBpS2V5Q29uZmlnOiB7XG4gICAgICAgICAgZGVzY3JpcHRpb246IGF1dGhNb2RlLmRlc2NyaXB0aW9uLFxuICAgICAgICAgIGFwaUtleUV4cGlyYXRpb25EYXlzOiBhdXRoTW9kZS5leHBpcmVzLnRvRGF5cygpLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICBjYXNlICdBV1NfSUFNJzpcbiAgICAgIHJldHVybiB7IGF1dGhlbnRpY2F0aW9uVHlwZSB9O1xuICAgIGNhc2UgJ0FNQVpPTl9DT0dOSVRPX1VTRVJfUE9PTFMnOlxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgYXV0aGVudGljYXRpb25UeXBlLFxuICAgICAgICB1c2VyUG9vbENvbmZpZzoge1xuICAgICAgICAgIHVzZXJQb29sSWQ6IGF1dGhNb2RlLnVzZXJQb29sLnVzZXJQb29sSWQsXG4gICAgICAgIH0sXG4gICAgICB9O1xuICAgIGNhc2UgJ09QRU5JRF9DT05ORUNUJzpcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGF1dGhlbnRpY2F0aW9uVHlwZSxcbiAgICAgICAgb3BlbklEQ29ubmVjdENvbmZpZzoge1xuICAgICAgICAgIG5hbWU6IGF1dGhNb2RlLm9pZGNQcm92aWRlck5hbWUsXG4gICAgICAgICAgaXNzdWVyVXJsOiBhdXRoTW9kZS5vaWRjSXNzdWVyVXJsLFxuICAgICAgICAgIGNsaWVudElkOiBhdXRoTW9kZS5jbGllbnRJZCxcbiAgICAgICAgICBpYXRUVEw6IGF1dGhNb2RlLnRva2VuRXhwaXJ5RnJvbUlzc3VlLnRvTWlsbGlzZWNvbmRzKCksXG4gICAgICAgICAgYXV0aFRUTDogYXV0aE1vZGUudG9rZW5FeHBpcnlGcm9tQXV0aC50b01pbGxpc2Vjb25kcygpLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICBjYXNlICdBV1NfTEFNQkRBJzpcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGF1dGhlbnRpY2F0aW9uVHlwZSxcbiAgICAgICAgbGFtYmRhQXV0aG9yaXplckNvbmZpZzoge1xuICAgICAgICAgIGxhbWJkYUFybjogYXV0aE1vZGUuZnVuY3Rpb24uZnVuY3Rpb25Bcm4sXG4gICAgICAgICAgbGFtYmRhRnVuY3Rpb246IGF1dGhNb2RlLmZ1bmN0aW9uLmZ1bmN0aW9uTmFtZSxcbiAgICAgICAgICB0dGxTZWNvbmRzOiBhdXRoTW9kZS50dGwudG9TZWNvbmRzKCksXG4gICAgICAgIH0sXG4gICAgICB9O1xuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuZXhwZWN0ZWQgQXV0aE1vZGUgdHlwZSAke2F1dGhlbnRpY2F0aW9uVHlwZX0gZW5jb3VudGVyZWQuYCk7XG4gIH1cbn07XG5cbi8qKlxuICogR2l2ZW4gYW4gYXBwc3luYyBhdXRoIGNvbmZpZ3VyYXRpb24sIGNvbnZlcnQgaW50byBhcHBzeW5jIGF1dGggcHJvdmlkZXIgc2V0dXAuXG4gKiBAcGFyYW0gYXV0aE1vZGVzIHRoZSBjb25maWcgdG8gdHJhbnNmb3JtXG4gKiBAcmV0dXJucyB0aGUgYXBwc3luYyBjb25maWcgb2JqZWN0LlxuICovXG5jb25zdCBjb252ZXJ0QXV0aENvbmZpZ1RvQXBwU3luY0F1dGggPSAoYXV0aE1vZGVzOiBBdXRob3JpemF0aW9uTW9kZXMpOiBBcHBTeW5jQXV0aENvbmZpZ3VyYXRpb24gPT4ge1xuICAvLyBDb252ZXJ0IGF1dGggbW9kZXMgaW50byBhbiBhcnJheSBvZiBhcHBzeW5jIGNvbmZpZ3MsIGFuZCBpbmNsdWRlIHRoZSB0eXBlIHNvIHdlIGNhbiB1c2UgdGhhdCBmb3Igc3dpdGNoaW5nIGFuZCBwYXJ0aXRpb25pbmcgbGF0ZXIuXG4gIGNvbnN0IGF1dGhDb25maWcgPSBbXG4gICAgYXV0aE1vZGVzLmFwaUtleUNvbmZpZyA/IHsgdHlwZTogJ0FQSV9LRVknLCAuLi5hdXRoTW9kZXMuYXBpS2V5Q29uZmlnIH0gOiBudWxsLFxuICAgIGF1dGhNb2Rlcy5sYW1iZGFDb25maWcgPyB7IHR5cGU6ICdBV1NfTEFNQkRBJywgLi4uYXV0aE1vZGVzLmxhbWJkYUNvbmZpZyB9IDogbnVsbCxcbiAgICBhdXRoTW9kZXMub2lkY0NvbmZpZyA/IHsgdHlwZTogJ09QRU5JRF9DT05ORUNUJywgLi4uYXV0aE1vZGVzLm9pZGNDb25maWcgfSA6IG51bGwsXG4gICAgYXV0aE1vZGVzLnVzZXJQb29sQ29uZmlnID8geyB0eXBlOiAnQU1BWk9OX0NPR05JVE9fVVNFUl9QT09MUycsIC4uLmF1dGhNb2Rlcy51c2VyUG9vbENvbmZpZyB9IDogbnVsbCxcbiAgICBhdXRoTW9kZXMuaWFtQ29uZmlnIHx8IGF1dGhNb2Rlcy5pZGVudGl0eVBvb2xDb25maWcgPyB7IHR5cGU6ICdBV1NfSUFNJyB9IDogbnVsbCxcbiAgXS5maWx0ZXIoKG1vZGUpID0+IG1vZGUpIGFzIEF1dGhvcml6YXRpb25Db25maWdNb2RlW107XG4gIGNvbnN0IGF1dGhQcm92aWRlcnMgPSBhdXRoQ29uZmlnLm1hcChjb252ZXJ0QXV0aE1vZGVUb0F1dGhQcm92aWRlcik7XG5cbiAgLy8gVmFsaWRhdGUgaW5wdXRzIG1ha2Ugc2Vuc2UsIG5lZWRzIGF0IGxlYXN0IG9uZSBtb2RlLCBhbmQgYSBkZWZhdWx0IG1vZGUgaXMgcmVxdWlyZWQgaWYgdGhlcmUgYXJlIG11bHRpcGxlIG1vZGVzLlxuICBpZiAoYXV0aFByb3ZpZGVycy5sZW5ndGggPT09IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0F0IGxlYXN0IG9uZSBhdXRoIGNvbmZpZyBpcyByZXF1aXJlZCwgYnV0IG5vbmUgd2VyZSBmb3VuZC4nKTtcbiAgfVxuICBpZiAoYXV0aFByb3ZpZGVycy5sZW5ndGggPiAxICYmICFhdXRoTW9kZXMuZGVmYXVsdEF1dGhvcml6YXRpb25Nb2RlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdBIGRlZmF1bHRBdXRob3JpemF0aW9uTW9kZSBpcyByZXF1aXJlZCBpZiBtdWx0aXBsZSBhdXRob3JpemF0aW9uIG1vZGVzIGFyZSBjb25maWd1cmVkLicpO1xuICB9XG5cbiAgLy8gRW5hYmxlIGFwcHN5bmMgdG8gaW52b2tlIGEgcHJvdmlkZWQgbGFtYmRhIGF1dGhvcml6ZXIgZnVuY3Rpb25cbiAgYXV0aE1vZGVzLmxhbWJkYUNvbmZpZz8uZnVuY3Rpb24uYWRkUGVybWlzc2lvbignYXBwc3luYy1hdXRoLWludm9rZScsIHtcbiAgICBwcmluY2lwYWw6IG5ldyBTZXJ2aWNlUHJpbmNpcGFsKCdhcHBzeW5jLmFtYXpvbmF3cy5jb20nKSxcbiAgICBhY3Rpb246ICdsYW1iZGE6SW52b2tlRnVuY3Rpb24nLFxuICB9KTtcblxuICAvLyBJbiB0aGUgY2FzZSBvZiBhIHNpbmdsZSBtb2RlLCBkZWZhdWx0QXV0aG9yaXphdGlvbk1vZGUgaXMgbm90IHJlcXVpcmVkLCBqdXN0IHVzZSB0aGUgcHJvdmlkZWQgdmFsdWUuXG4gIGlmIChhdXRoUHJvdmlkZXJzLmxlbmd0aCA9PT0gMSkge1xuICAgIHJldHVybiB7XG4gICAgICBkZWZhdWx0QXV0aGVudGljYXRpb246IGF1dGhQcm92aWRlcnNbMF0sXG4gICAgICBhZGRpdGlvbmFsQXV0aGVudGljYXRpb25Qcm92aWRlcnM6IFtdLFxuICAgIH07XG4gIH1cblxuICAvLyBGb3IgbXVsdGktYXV0aCwgcGFydGl0aW9uIGludG8gdGhlIGRlZmF1bHRNb2RlIGFuZCBub24tZGVmYXVsdCBtb2Rlcy5cbiAgcmV0dXJuIHtcbiAgICBkZWZhdWx0QXV0aGVudGljYXRpb246IGF1dGhQcm92aWRlcnMuZmlsdGVyKChwcm92aWRlcikgPT4gcHJvdmlkZXIuYXV0aGVudGljYXRpb25UeXBlID09PSBhdXRoTW9kZXMuZGVmYXVsdEF1dGhvcml6YXRpb25Nb2RlKVswXSxcbiAgICBhZGRpdGlvbmFsQXV0aGVudGljYXRpb25Qcm92aWRlcnM6IGF1dGhQcm92aWRlcnMuZmlsdGVyKFxuICAgICAgKHByb3ZpZGVyKSA9PiBwcm92aWRlci5hdXRoZW50aWNhdGlvblR5cGUgIT09IGF1dGhNb2Rlcy5kZWZhdWx0QXV0aG9yaXphdGlvbk1vZGUsXG4gICAgKSxcbiAgfTtcbn07XG5cbnR5cGUgQXV0aFN5bnRoUGFyYW1ldGVycyA9IFBpY2s8XG4gIFN5bnRoUGFyYW1ldGVycyxcbiAgJ3VzZXJQb29sSWQnIHwgJ2F1dGhlbnRpY2F0ZWRVc2VyUm9sZU5hbWUnIHwgJ3VuYXV0aGVudGljYXRlZFVzZXJSb2xlTmFtZScgfCAnaWRlbnRpdHlQb29sSWQnIHwgJ2FkbWluUm9sZXMnIHwgJ2VuYWJsZUlhbUFjY2Vzcydcbj47XG5cbmludGVyZmFjZSBBdXRoQ29uZmlnIHtcbiAgLyoqXG4gICAqIHVzZWQgbWFpbmx5IGluIHRoZSBiZWZvcmUgc3RlcCB0byBwYXNzIHRoZSBhdXRoQ29uZmlnIGZyb20gdGhlIHRyYW5zZm9ybWVyIGNvcmUgZG93biB0byB0aGUgZGlyZWN0aXZlXG4gICAqL1xuICBhdXRoQ29uZmlnPzogQXBwU3luY0F1dGhDb25maWd1cmF0aW9uO1xuXG4gIC8qKlxuICAgKiBQYXJhbXMgdG8gaW5jbHVkZSB0aGUgdHJhbnNmb3JtZXIuXG4gICAqL1xuICBhdXRoU3ludGhQYXJhbWV0ZXJzOiBBdXRoU3ludGhQYXJhbWV0ZXJzO1xufVxuXG4vKipcbiAqIFRyYW5zZm9ybXMgYWRkaXRpb25hbEF1dGhlbnRpY2F0aW9uVHlwZXMgZm9yIHN0b3JhZ2UgaW4gQ0ZOIG91dHB1dFxuICovXG5leHBvcnQgY29uc3QgZ2V0QWRkaXRpb25hbEF1dGhlbnRpY2F0aW9uVHlwZXMgPSAoY2ZuR3JhcGhxbEFwaTogQ2ZuR3JhcGhRTEFwaSk6IHN0cmluZyB8IHVuZGVmaW5lZCA9PiB7XG4gIGlmICghaXNBcnJheShjZm5HcmFwaHFsQXBpLmFkZGl0aW9uYWxBdXRoZW50aWNhdGlvblByb3ZpZGVycykpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgcmV0dXJuIChjZm5HcmFwaHFsQXBpLmFkZGl0aW9uYWxBdXRoZW50aWNhdGlvblByb3ZpZGVycyBhcyBDZm5HcmFwaFFMQXBpLkFkZGl0aW9uYWxBdXRoZW50aWNhdGlvblByb3ZpZGVyUHJvcGVydHlbXSlcbiAgICAubWFwKFxuICAgICAgKGFkZGl0aW9uYWxBdXRoZW50aWNhdGlvblByb3ZpZGVyOiBDZm5HcmFwaFFMQXBpLkFkZGl0aW9uYWxBdXRoZW50aWNhdGlvblByb3ZpZGVyUHJvcGVydHkpID0+XG4gICAgICAgIGFkZGl0aW9uYWxBdXRoZW50aWNhdGlvblByb3ZpZGVyLmF1dGhlbnRpY2F0aW9uVHlwZSxcbiAgICApXG4gICAgLmpvaW4oJywnKTtcbn07XG5cbi8qKlxuICogQ29udmVydCB0aGUgbGlzdCBvZiBhdXRoIG1vZGVzIGludG8gdGhlIG5lY2Vzc2FyeSBmbGFncyBhbmQgcGFyYW1zIChlZmZlY3RpdmVseSBhIHJlZHVjZXIgb24gdGhlIHJ1bGUgbGlzdClcbiAqIEBwYXJhbSBhdXRoTW9kZXMgdGhlIGxpc3Qgb2YgYXV0aCBtb2RlcyBjb25maWd1cmVkIG9uIHRoZSBBUEkuXG4gKiBAcmV0dXJucyB0aGUgQXV0aENvbmZpZyB3aGljaCB0aGUgQXV0aFRyYW5zZm9ybWVyIG5lZWRzIGFzIGlucHV0LlxuICovXG5leHBvcnQgY29uc3QgY29udmVydEF1dGhvcml6YXRpb25Nb2Rlc1RvVHJhbnNmb3JtZXJBdXRoQ29uZmlnID0gKGF1dGhNb2RlczogQXV0aG9yaXphdGlvbk1vZGVzKTogQXV0aENvbmZpZyA9PiAoe1xuICBhdXRoQ29uZmlnOiBjb252ZXJ0QXV0aENvbmZpZ1RvQXBwU3luY0F1dGgoYXV0aE1vZGVzKSxcbiAgYXV0aFN5bnRoUGFyYW1ldGVyczogZ2V0U3ludGhQYXJhbWV0ZXJzKGF1dGhNb2RlcyksXG59KTtcblxuLyoqXG4gKiBNZXJnZSBpYW1Db25maWcgYWxsb3dMaXN0ZWRSb2xlcyB3aXRoIGRlcHJlY2F0ZWQgYWRtaW5Sb2xlcyBwcm9wZXJ0eSwgY29udmVydGluZyB0byBzdHJpbmdzLlxuICogQHBhcmFtIGF1dGhNb2RlcyB0aGUgYXV0aCBtb2RlcyBwcm92aWRlZCB0byB0aGUgY29uc3RydWN0LlxuICogQHJldHVybnMgdGhlIGxpc3Qgb2YgYWRtaW4gcm9sZXMgYXMgc3RyaW5ncyB0byBwYXNzIGludG8gdGhlIHRyYW5zZm9ybWVyXG4gKi9cbmNvbnN0IGdldEFsbG93TGlzdGVkUm9sZXMgPSAoYXV0aE1vZGVzOiBBdXRob3JpemF0aW9uTW9kZXMpOiBzdHJpbmdbXSA9PlxuICBbLi4uKGF1dGhNb2Rlcz8uaWFtQ29uZmlnPy5hbGxvd0xpc3RlZFJvbGVzID8/IFtdKSwgLi4uKGF1dGhNb2Rlcy5hZG1pblJvbGVzID8/IFtdKV0ubWFwKChyb2xlT3JSb2xlTmFtZTogSVJvbGUgfCBzdHJpbmcpID0+IHtcbiAgICBpZiAodHlwZW9mIHJvbGVPclJvbGVOYW1lID09PSAnc3RyaW5nJyB8fCByb2xlT3JSb2xlTmFtZSBpbnN0YW5jZW9mIFN0cmluZykge1xuICAgICAgcmV0dXJuIHJvbGVPclJvbGVOYW1lIGFzIHN0cmluZztcbiAgICB9XG4gICAgcmV0dXJuIHJvbGVPclJvbGVOYW1lLnJvbGVOYW1lO1xuICB9KTtcblxuLyoqXG4gKiBUcmFuc2Zvcm0gdGhlIGF1dGhvcml6YXRpb24gY29uZmlnIGludG8gdGhlIHRyYW5zZm9ybWVyIHN5bnRoIHBhcmFtZXRlcnMgcGVydGFpbmluZyB0byBhdXRoLlxuICogQHBhcmFtIGF1dGhNb2RlcyB0aGUgYXV0aCBtb2RlcyBwcm92aWRlZCB0byB0aGUgY29uc3RydWN0LlxuICogQHJldHVybnMgYSByZWNvcmQgb2YgcGFyYW1zIHRvIGJlIGNvbnN1bWVkIGJ5IHRoZSB0cmFuc2Zvcm1lci5cbiAqL1xuY29uc3QgZ2V0U3ludGhQYXJhbWV0ZXJzID0gKGF1dGhNb2RlczogQXV0aG9yaXphdGlvbk1vZGVzKTogQXV0aFN5bnRoUGFyYW1ldGVycyA9PiAoe1xuICBhZG1pblJvbGVzOiBnZXRBbGxvd0xpc3RlZFJvbGVzKGF1dGhNb2RlcyksXG4gIGlkZW50aXR5UG9vbElkOiBhdXRoTW9kZXMuaWRlbnRpdHlQb29sQ29uZmlnPy5pZGVudGl0eVBvb2xJZCA/PyBhdXRoTW9kZXMuaWFtQ29uZmlnPy5pZGVudGl0eVBvb2xJZCxcbiAgZW5hYmxlSWFtQWNjZXNzOiBhdXRoTW9kZXMuaWFtQ29uZmlnPy5lbmFibGVJYW1BdXRob3JpemF0aW9uTW9kZSxcbiAgLi4uKGF1dGhNb2Rlcy51c2VyUG9vbENvbmZpZyA/IHsgdXNlclBvb2xJZDogYXV0aE1vZGVzLnVzZXJQb29sQ29uZmlnLnVzZXJQb29sLnVzZXJQb29sSWQgfSA6IHt9KSxcbiAgLi4uKGF1dGhNb2Rlcz8uaWRlbnRpdHlQb29sQ29uZmlnXG4gICAgPyB7XG4gICAgICAgIGF1dGhlbnRpY2F0ZWRVc2VyUm9sZU5hbWU6IGF1dGhNb2Rlcy5pZGVudGl0eVBvb2xDb25maWcuYXV0aGVudGljYXRlZFVzZXJSb2xlLnJvbGVOYW1lLFxuICAgICAgICB1bmF1dGhlbnRpY2F0ZWRVc2VyUm9sZU5hbWU6IGF1dGhNb2Rlcy5pZGVudGl0eVBvb2xDb25maWcudW5hdXRoZW50aWNhdGVkVXNlclJvbGUucm9sZU5hbWUsXG4gICAgICB9XG4gICAgOiB7fSksXG4gIC4uLihhdXRoTW9kZXM/LmlhbUNvbmZpZyAmJiBhdXRoTW9kZXM/LmlhbUNvbmZpZy5hdXRoZW50aWNhdGVkVXNlclJvbGUgJiYgYXV0aE1vZGVzPy5pYW1Db25maWcudW5hdXRoZW50aWNhdGVkVXNlclJvbGVcbiAgICA/IHtcbiAgICAgICAgYXV0aGVudGljYXRlZFVzZXJSb2xlTmFtZTogYXV0aE1vZGVzLmlhbUNvbmZpZy5hdXRoZW50aWNhdGVkVXNlclJvbGU/LnJvbGVOYW1lLFxuICAgICAgICB1bmF1dGhlbnRpY2F0ZWRVc2VyUm9sZU5hbWU6IGF1dGhNb2Rlcy5pYW1Db25maWcudW5hdXRoZW50aWNhdGVkVXNlclJvbGU/LnJvbGVOYW1lLFxuICAgICAgfVxuICAgIDoge30pLFxufSk7XG4iXX0=