diff --git a/packages/amplify-e2e-core/src/categories/api.ts b/packages/amplify-e2e-core/src/categories/api.ts index 7b0df2bd681..fec220903d8 100644 --- a/packages/amplify-e2e-core/src/categories/api.ts +++ b/packages/amplify-e2e-core/src/categories/api.ts @@ -8,7 +8,7 @@ import { EOL } from 'os'; import { modifiedApi } from './resources/modified-api-index'; export function getSchemaPath(schemaName: string): string { - return `${__dirname}/../../../amplify-e2e-tests/schemas/${schemaName}`; + return path.join(__dirname, '..', '..', '..', 'amplify-e2e-tests', 'schemas', schemaName); } export function apiGqlCompile(cwd: string, testingWithLatestCodebase: boolean = false) { diff --git a/packages/amplify-e2e-tests/schemas/iam_simple_model.graphql b/packages/amplify-e2e-tests/schemas/iam_simple_model.graphql new file mode 100644 index 00000000000..d16dedda823 --- /dev/null +++ b/packages/amplify-e2e-tests/schemas/iam_simple_model.graphql @@ -0,0 +1,5 @@ +type Todo @model @auth(rules: [{ allow: private, provider: iam }]) { + id: ID! + name: String! + description: String +} diff --git a/packages/amplify-e2e-tests/src/__tests__/function_9.test.ts b/packages/amplify-e2e-tests/src/__tests__/function_9.test.ts index cd7df53717e..299820c1010 100644 --- a/packages/amplify-e2e-tests/src/__tests__/function_9.test.ts +++ b/packages/amplify-e2e-tests/src/__tests__/function_9.test.ts @@ -1,33 +1,24 @@ import { addApiWithoutSchema, addApi, - addAuthWithDefault, addDDBWithTrigger, addFunction, - addS3StorageWithSettings, addSimpleDDB, - AddStorageSettings, amplifyPush, amplifyPushAuth, - amplifyPushForce, createNewProjectDir, deleteProject, deleteProjectDir, getBackendAmplifyMeta, - getFunctionSrcNode, getProjectMeta, initJSProjectWithProfile, invokeFunction, - overrideFunctionSrcNode, addNodeDependencies, readJsonFile, updateFunction, overrideFunctionCodeNode, getBackendConfig, addFeatureFlag, - addAuthWithGroupsAndAdminAPI, - getFunction, - loadFunctionTestFile, updateApiSchema, createRandomName, } from 'amplify-e2e-core'; @@ -35,6 +26,8 @@ import fs from 'fs-extra'; import path from 'path'; import _ from 'lodash'; +const GraphQLTransformerLatestVersion = 2; + describe('nodejs', () => { describe('amplify add function with additional permissions', () => { let projRoot: string; @@ -262,6 +255,66 @@ describe('nodejs', () => { expect(gqlResponse.data.createTodo.description).toEqual('sampleDesc'); }); + it('should be able to query AppSync with minimal permissions with featureFlag for function and vNext GraphQL API', async () => { + const appName = 'functiongqlvnext'; + const random = Math.floor(Math.random() * 10000); + const fnName = `apienvvar${random}`; + const createTodo = ` + mutation CreateTodo($input: CreateTodoInput!) { + createTodo(input: $input) { + id + name + description + createdAt + updatedAt + } + }`; + await initJSProjectWithProfile(projRoot, { name: appName }); + addFeatureFlag(projRoot, 'graphqltransformer', 'transformerversion', GraphQLTransformerLatestVersion); + await addApi(projRoot, { + IAM: {}, + }); + updateApiSchema(projRoot, appName, 'iam_simple_model.graphql'); + const beforeMeta = getBackendConfig(projRoot); + const apiName = Object.keys(beforeMeta.api)[0]; + await addFunction( + projRoot, + { + name: fnName, + functionTemplate: 'Hello World', + additionalPermissions: { + permissions: ['api'], + choices: ['api'], + resources: [apiName], + operations: ['Mutation'], + }, + }, + 'nodejs', + ); + // Pin aws-appsync to 4.0.3 until https://github.com/awslabs/aws-mobile-appsync-sdk-js/issues/647 is fixed. + addNodeDependencies(projRoot, fnName, ['aws-appsync@4.0.3', 'isomorphic-fetch', 'graphql-tag']); + overrideFunctionCodeNode(projRoot, fnName, 'mutation-appsync.js'); + await amplifyPush(projRoot); + const meta = getProjectMeta(projRoot); + const { Region: region, Name: functionName } = Object.keys(meta.function).map(key => meta.function[key])[0].output; + const lambdaCFN = readJsonFile( + path.join(projRoot, 'amplify', 'backend', 'function', fnName, `${fnName}-cloudformation-template.json`), + ); + const urlKey = Object.keys(lambdaCFN.Resources.LambdaFunction.Properties.Environment.Variables).filter(value => + value.endsWith('GRAPHQLAPIENDPOINTOUTPUT'), + )[0]; + const payloadObj = { urlKey, mutation: createTodo, variables: { input: { name: 'todo', description: 'sampleDesc' } } }; + const fnResponse = await invokeFunction(functionName, JSON.stringify(payloadObj), region); + + expect(fnResponse.StatusCode).toBe(200); + expect(fnResponse.Payload).toBeDefined(); + const gqlResponse = JSON.parse(fnResponse.Payload as string); + + expect(gqlResponse.data).toBeDefined(); + expect(gqlResponse.data.createTodo.name).toEqual('todo'); + expect(gqlResponse.data.createTodo.description).toEqual('sampleDesc'); + }); + it('should be able to make console calls with feature flag turned off', async () => { const random = Math.floor(Math.random() * 10000); const fnName = `apienvvar${random}`; diff --git a/packages/amplify-graphql-auth-transformer/src/__tests__/__snapshots__/amplify-admin-auth.test.ts.snap b/packages/amplify-graphql-auth-transformer/src/__tests__/__snapshots__/amplify-admin-auth.test.ts.snap new file mode 100644 index 00000000000..578284985c2 --- /dev/null +++ b/packages/amplify-graphql-auth-transformer/src/__tests__/__snapshots__/amplify-admin-auth.test.ts.snap @@ -0,0 +1,98 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Test simple model with AdminUI enabled should add IAM policy only for fields that have explicit IAM auth 1`] = ` +"## [Start] Authorization Steps. ** +$util.qr($ctx.stash.put(\\"hasAuth\\", true)) +#set( $inputFields = $util.parseJson($util.toJson($ctx.args.input.keySet())) ) +#set( $isAuthorized = false ) +#set( $allowedFields = [] ) +#if( $util.authType() == \\"IAM Authorization\\" ) + #set( $adminRoles = [\\"us-fake-1_uuid_Full-access/CognitoIdentityCredentials\\",\\"us-fake-1_uuid_Manage-only/CognitoIdentityCredentials\\"] ) + #foreach( $adminRole in $adminRoles ) + #if( $ctx.identity.userArn.contains($adminRole) ) + #return($util.toJson({})) + #end + #end +$util.unauthorized() +#end +#if( $util.authType() == \\"User Pool Authorization\\" ) + +#end +#if( !$isAuthorized && $allowedFields.isEmpty() ) +$util.unauthorized() +#end +#if( !$isAuthorized ) + #set( $deniedFields = $util.list.copyAndRemoveAll($inputFields, $allowedFields) ) + #if( $deniedFields.size() > 0 ) + $util.error(\\"Unauthorized on \${deniedFields}\\", \\"Unauthorized\\") + #end +#end +$util.toJson({\\"version\\":\\"2018-05-29\\",\\"payload\\":{}}) +## [End] Authorization Steps. **" +`; + +exports[`Test simple model with AdminUI enabled should add IAM policy only for fields that have explicit IAM auth 2`] = ` +"## [Start] Authorization Steps. ** +$util.qr($ctx.stash.put(\\"hasAuth\\", true)) +#if( $ctx.error ) + $util.error($ctx.error.message, $ctx.error.type) +#end +#set( $inputFields = $util.parseJson($util.toJson($ctx.args.input.keySet())) ) +#set( $isAuthorized = false ) +#set( $allowedFields = [] ) +#set( $nullAllowedFields = [] ) +#set( $deniedFields = {} ) +#if( $util.authType() == \\"IAM Authorization\\" ) + #set( $adminRoles = [\\"us-fake-1_uuid_Full-access/CognitoIdentityCredentials\\",\\"us-fake-1_uuid_Manage-only/CognitoIdentityCredentials\\"] ) + #foreach( $adminRole in $adminRoles ) + #if( $ctx.identity.userArn.contains($adminRole) ) + #return($util.toJson({})) + #end + #end +$util.unauthorized() +#end +#if( $util.authType() == \\"User Pool Authorization\\" ) + +#end +#if( !$isAuthorized && $allowedFields.isEmpty() && $nullAllowedFields.isEmpty() ) +$util.unauthorized() +#end +#if( !$isAuthorized ) + #foreach( $entry in $util.map.copyAndRetainAllKeys($ctx.args.input, $inputFields).entrySet() ) + #if( $util.isNull($entry.value) && !$nullAllowedFields.contains($entry.key) ) + $util.qr($deniedFields.put($entry.key, \\"\\")) + #end + #end + #foreach( $deniedField in $util.list.copyAndRemoveAll($inputFields, $allowedFields) ) + $util.qr($deniedFields.put($deniedField, \\"\\")) + #end +#end +#if( $deniedFields.keySet().size() > 0 ) + $util.error(\\"Unauthorized on \${deniedFields.keySet()}\\", \\"Unauthorized\\") +#end +$util.toJson({}) +## [End] Authorization Steps. **" +`; + +exports[`Test simple model with AdminUI enabled should add IAM policy only for fields that have explicit IAM auth 3`] = ` +"## [Start] Authorization Steps. ** +$util.qr($ctx.stash.put(\\"hasAuth\\", true)) +#set( $isAuthorized = false ) +#if( $util.authType() == \\"IAM Authorization\\" ) + #set( $adminRoles = [\\"us-fake-1_uuid_Full-access/CognitoIdentityCredentials\\",\\"us-fake-1_uuid_Manage-only/CognitoIdentityCredentials\\"] ) + #foreach( $adminRole in $adminRoles ) + #if( $ctx.identity.userArn.contains($adminRole) ) + #return($util.toJson({})) + #end + #end +$util.unauthorized() +#end +#if( $util.authType() == \\"User Pool Authorization\\" ) + +#end +#if( !$isAuthorized ) +$util.unauthorized() +#end +$util.toJson({\\"version\\":\\"2018-05-29\\",\\"payload\\":{}}) +## [End] Authorization Steps. **" +`; diff --git a/packages/amplify-graphql-auth-transformer/src/__tests__/amplify-admin-auth.test.ts b/packages/amplify-graphql-auth-transformer/src/__tests__/amplify-admin-auth.test.ts index 2ca7f2e4098..e6b1921b6de 100644 --- a/packages/amplify-graphql-auth-transformer/src/__tests__/amplify-admin-auth.test.ts +++ b/packages/amplify-graphql-auth-transformer/src/__tests__/amplify-admin-auth.test.ts @@ -3,6 +3,8 @@ import { ModelTransformer } from '@aws-amplify/graphql-model-transformer'; import { GraphQLTransform } from '@aws-amplify/graphql-transformer-core'; import _ from 'lodash'; +const ADMIN_UI_ROLES = ['us-fake-1_uuid_Full-access/CognitoIdentityCredentials', 'us-fake-1_uuid_Manage-only/CognitoIdentityCredentials']; + test('test simple model with public auth rule and amplify admin app is present', () => { const validSchema = ` type Post @model @auth(rules: [{allow: public}]) { @@ -25,8 +27,7 @@ test('test simple model with public auth rule and amplify admin app is present', transformers: [ new ModelTransformer(), new AuthTransformer({ - addAwsIamAuthInOutputSchema: true, - adminUserPoolID: 'us-fake-1_uuid', + adminRoles: ADMIN_UI_ROLES, }), ], }); @@ -51,12 +52,7 @@ test('Test simple model with public auth rule and amplify admin app is not enabl }, additionalAuthenticationProviders: [], }, - transformers: [ - new ModelTransformer(), - new AuthTransformer({ - addAwsIamAuthInOutputSchema: false, - }), - ], + transformers: [new ModelTransformer(), new AuthTransformer()], }); const out = transformer.transform(validSchema); expect(out).toBeDefined(); @@ -86,8 +82,7 @@ test('Test model with public auth rule without all operations and amplify admin transformers: [ new ModelTransformer(), new AuthTransformer({ - addAwsIamAuthInOutputSchema: true, - adminUserPoolID: 'us-fake-1_uuid', + adminRoles: ADMIN_UI_ROLES, }), ], }); @@ -127,8 +122,7 @@ test('Test simple model with private auth rule and amplify admin app is present' transformers: [ new ModelTransformer(), new AuthTransformer({ - addAwsIamAuthInOutputSchema: true, - adminUserPoolID: 'us-fake-1_uuid', + adminRoles: ADMIN_UI_ROLES, }), ], }); @@ -157,12 +151,7 @@ test('Test simple model with private auth rule and amplify admin app not enabled }, ], }, - transformers: [ - new ModelTransformer(), - new AuthTransformer({ - addAwsIamAuthInOutputSchema: false, - }), - ], + transformers: [new ModelTransformer(), new AuthTransformer()], }); const out = transformer.transform(validSchema); expect(out).toBeDefined(); @@ -192,18 +181,7 @@ test('Test simple model with private auth rule, few operations, and amplify admi transformers: [ new ModelTransformer(), new AuthTransformer({ - authConfig: { - defaultAuthentication: { - authenticationType: 'AMAZON_COGNITO_USER_POOLS', - }, - additionalAuthenticationProviders: [ - { - authenticationType: 'AWS_IAM', - }, - ], - }, - addAwsIamAuthInOutputSchema: true, - adminUserPoolID: 'us-fake-1_uuid', + adminRoles: ADMIN_UI_ROLES, }), ], }); @@ -245,12 +223,7 @@ test('Test simple model with private IAM auth rule, few operations, and amplify }, ], }, - transformers: [ - new ModelTransformer(), - new AuthTransformer({ - addAwsIamAuthInOutputSchema: false, - }), - ], + transformers: [new ModelTransformer(), new AuthTransformer()], }); const out = transformer.transform(validSchema); expect(out).toBeDefined(); @@ -288,8 +261,7 @@ test('Test simple model with AdminUI enabled should add IAM policy only for fiel transformers: [ new ModelTransformer(), new AuthTransformer({ - addAwsIamAuthInOutputSchema: true, - adminUserPoolID: 'us-fake-1_uuid', + adminRoles: ADMIN_UI_ROLES, }), ], }); @@ -325,13 +297,6 @@ test('Test simple model with AdminUI enabled should add IAM policy only for fiel ]); // should throw unauthorized if it's not signed by the admin ui iam role ['Mutation.createPost.auth.1.req.vtl', 'Mutation.updatePost.auth.1.res.vtl', 'Mutation.deletePost.auth.1.res.vtl'].forEach(r => { - expect(out.pipelineFunctions[r]).toContain( - '#if( $util.authType() == "IAM Authorization" )\n' + - ' #if( $ctx.identity.userArn.contains("us-fake-1_uuid_Full-access/CognitoIdentityCredentials") || $ctx.identity.userArn.contains("us-fake-1_uuid_Manage-only/CognitoIdentityCredentials") )\n' + - ' #return($util.toJson({})\n' + - ' #end\n' + - '$util.unauthorized()\n' + - '#end', - ); + expect(out.pipelineFunctions[r]).toMatchSnapshot(); }); }); diff --git a/packages/amplify-graphql-auth-transformer/src/__tests__/custom-auth.test.ts b/packages/amplify-graphql-auth-transformer/src/__tests__/custom-auth.test.ts index dc5c378481e..a99b935fb7d 100644 --- a/packages/amplify-graphql-auth-transformer/src/__tests__/custom-auth.test.ts +++ b/packages/amplify-graphql-auth-transformer/src/__tests__/custom-auth.test.ts @@ -24,13 +24,7 @@ test('happy case with lambda auth mode as default auth mode', () => { }`; const transformer = new GraphQLTransform({ authConfig, - transformers: [ - new ModelTransformer(), - new AuthTransformer({ - authConfig, - addAwsIamAuthInOutputSchema: false, - }), - ], + transformers: [new ModelTransformer(), new AuthTransformer()], }); const out = transformer.transform(validSchema); expect(out).toBeDefined(); @@ -61,17 +55,14 @@ test('happy case with lambda auth mode as additional auth mode', () => { }`; const transformer = new GraphQLTransform({ authConfig, - transformers: [ - new ModelTransformer(), - new AuthTransformer({ - authConfig, - addAwsIamAuthInOutputSchema: false, - }), - ], + transformers: [new ModelTransformer(), new AuthTransformer()], }); const out = transformer.transform(validSchema); expect(out).toBeDefined(); - expect(out.rootStack!.Resources![ResourceConstants.RESOURCES.GraphQLAPILogicalID].Properties.AdditionalAuthenticationProviders[0].AuthenticationType).toEqual('AWS_LAMBDA'); + expect( + out.rootStack!.Resources![ResourceConstants.RESOURCES.GraphQLAPILogicalID].Properties.AdditionalAuthenticationProviders[0] + .AuthenticationType, + ).toEqual('AWS_LAMBDA'); }); test('allow: custom defaults provider to function', () => { @@ -94,13 +85,7 @@ test('allow: custom defaults provider to function', () => { }`; const transformer = new GraphQLTransform({ authConfig, - transformers: [ - new ModelTransformer(), - new AuthTransformer({ - authConfig, - addAwsIamAuthInOutputSchema: false, - }), - ], + transformers: [new ModelTransformer(), new AuthTransformer()], }); const out = transformer.transform(validSchema); expect(out).toBeDefined(); @@ -123,13 +108,7 @@ test('allow: custom error out when there is no lambda auth mode defined', () => }`; const transformer = new GraphQLTransform({ authConfig, - transformers: [ - new ModelTransformer(), - new AuthTransformer({ - authConfig, - addAwsIamAuthInOutputSchema: false, - }), - ], + transformers: [new ModelTransformer(), new AuthTransformer()], }); expect(() => transformer.transform(validSchema)).toThrowError( `@auth directive with 'function' provider found, but the project has no Lambda authentication provider configured.`, @@ -156,13 +135,7 @@ test('allow: custom and provider: iam error out for invalid combination', () => }`; const transformer = new GraphQLTransform({ authConfig, - transformers: [ - new ModelTransformer(), - new AuthTransformer({ - authConfig, - addAwsIamAuthInOutputSchema: false, - }), - ], + transformers: [new ModelTransformer(), new AuthTransformer()], }); expect(() => transformer.transform(validSchema)).toThrowError( `@auth directive with 'custom' strategy only supports 'function' (default) provider, but found 'iam' assigned.`, @@ -189,15 +162,9 @@ test('allow: non-custom and provider: function error out for invalid combination }`; const transformer = new GraphQLTransform({ authConfig, - transformers: [ - new ModelTransformer(), - new AuthTransformer({ - authConfig, - addAwsIamAuthInOutputSchema: false, - }), - ], + transformers: [new ModelTransformer(), new AuthTransformer()], }); expect(() => transformer.transform(validSchema)).toThrowError( `@auth directive with 'public' strategy only supports 'apiKey' (default) and 'iam' providers, but found 'function' assigned.`, ); -}); \ No newline at end of file +}); diff --git a/packages/amplify-graphql-auth-transformer/src/__tests__/field-auth-argument.test.ts b/packages/amplify-graphql-auth-transformer/src/__tests__/field-auth-argument.test.ts index d952d2acc32..be7c2095bba 100644 --- a/packages/amplify-graphql-auth-transformer/src/__tests__/field-auth-argument.test.ts +++ b/packages/amplify-graphql-auth-transformer/src/__tests__/field-auth-argument.test.ts @@ -25,13 +25,7 @@ test('subscriptions are only generated if the respective mutation operation exis }; const transformer = new GraphQLTransform({ authConfig, - transformers: [ - new ModelTransformer(), - new AuthTransformer({ - authConfig, - addAwsIamAuthInOutputSchema: false, - }), - ], + transformers: [new ModelTransformer(), new AuthTransformer()], }); const out = transformer.transform(validSchema); // expect to generate subscription resolvers for create and update only @@ -59,13 +53,7 @@ test('per-field @auth without @model', () => { }; const transformer = new GraphQLTransform({ authConfig, - transformers: [ - new ModelTransformer(), - new AuthTransformer({ - authConfig, - addAwsIamAuthInOutputSchema: false, - }), - ], + transformers: [new ModelTransformer(), new AuthTransformer()], }); const out = transformer.transform(validSchema); expect(out).toBeDefined(); diff --git a/packages/amplify-graphql-auth-transformer/src/__tests__/group-auth.test.ts b/packages/amplify-graphql-auth-transformer/src/__tests__/group-auth.test.ts index 0496dec03b8..0e83106c76e 100644 --- a/packages/amplify-graphql-auth-transformer/src/__tests__/group-auth.test.ts +++ b/packages/amplify-graphql-auth-transformer/src/__tests__/group-auth.test.ts @@ -20,13 +20,7 @@ test('happy case with static groups', () => { }`; const transformer = new GraphQLTransform({ authConfig, - transformers: [ - new ModelTransformer(), - new AuthTransformer({ - authConfig, - addAwsIamAuthInOutputSchema: false, - }), - ], + transformers: [new ModelTransformer(), new AuthTransformer()], }); const out = transformer.transform(validSchema); expect(out).toBeDefined(); @@ -53,13 +47,7 @@ test('happy case with dynamic groups', () => { `; const transformer = new GraphQLTransform({ authConfig, - transformers: [ - new ModelTransformer(), - new AuthTransformer({ - authConfig, - addAwsIamAuthInOutputSchema: false, - }), - ], + transformers: [new ModelTransformer(), new AuthTransformer()], }); const out = transformer.transform(validSchema); expect(out).toBeDefined(); @@ -85,13 +73,7 @@ test('validation on @auth on a non-@model type', () => { }`; const transformer = new GraphQLTransform({ authConfig, - transformers: [ - new ModelTransformer(), - new AuthTransformer({ - authConfig, - addAwsIamAuthInOutputSchema: false, - }), - ], + transformers: [new ModelTransformer(), new AuthTransformer()], }); expect(() => transformer.transform(invalidSchema)).toThrowError('Types annotated with @auth must also be annotated with @model.'); }); diff --git a/packages/amplify-graphql-auth-transformer/src/__tests__/multi-auth.test.ts b/packages/amplify-graphql-auth-transformer/src/__tests__/multi-auth.test.ts index 3584c818a07..775eecb0160 100644 --- a/packages/amplify-graphql-auth-transformer/src/__tests__/multi-auth.test.ts +++ b/packages/amplify-graphql-auth-transformer/src/__tests__/multi-auth.test.ts @@ -166,13 +166,7 @@ const getRecursiveSchemaWithDiffModesOnParentType = (authDir1: string, authDir2: const getTransformer = (authConfig: AppSyncAuthConfiguration) => new GraphQLTransform({ authConfig, - transformers: [ - new ModelTransformer(), - new AuthTransformer({ - authConfig, - addAwsIamAuthInOutputSchema: false, - }), - ], + transformers: [new ModelTransformer(), new AuthTransformer()], }); const getObjectType = (doc: DocumentNode, type: string): ObjectTypeDefinitionNode | undefined => { diff --git a/packages/amplify-graphql-auth-transformer/src/__tests__/owner-auth.test.ts b/packages/amplify-graphql-auth-transformer/src/__tests__/owner-auth.test.ts index 3cd649b0647..15510c52d0f 100644 --- a/packages/amplify-graphql-auth-transformer/src/__tests__/owner-auth.test.ts +++ b/packages/amplify-graphql-auth-transformer/src/__tests__/owner-auth.test.ts @@ -22,13 +22,7 @@ test('auth transformer validation happy case', () => { }`; const transformer = new GraphQLTransform({ authConfig, - transformers: [ - new ModelTransformer(), - new AuthTransformer({ - authConfig, - addAwsIamAuthInOutputSchema: false, - }), - ], + transformers: [new ModelTransformer(), new AuthTransformer()], }); const out = transformer.transform(validSchema); expect(out).toBeDefined(); @@ -54,13 +48,7 @@ test('ownerfield with subscriptions', () => { }`; const transformer = new GraphQLTransform({ authConfig, - transformers: [ - new ModelTransformer(), - new AuthTransformer({ - authConfig, - addAwsIamAuthInOutputSchema: false, - }), - ], + transformers: [new ModelTransformer(), new AuthTransformer()], }); const out = transformer.transform(validSchema); expect(out).toBeDefined(); @@ -104,13 +92,7 @@ test('multiple owner rules with subscriptions', () => { }; const transformer = new GraphQLTransform({ authConfig, - transformers: [ - new ModelTransformer(), - new AuthTransformer({ - authConfig, - addAwsIamAuthInOutputSchema: false, - }), - ], + transformers: [new ModelTransformer(), new AuthTransformer()], }); const out = transformer.transform(validSchema); expect(out).toBeDefined(); @@ -152,13 +134,7 @@ test('implicit owner fields get added to the type', () => { }; const transformer = new GraphQLTransform({ authConfig, - transformers: [ - new ModelTransformer(), - new AuthTransformer({ - authConfig, - addAwsIamAuthInOutputSchema: false, - }), - ], + transformers: [new ModelTransformer(), new AuthTransformer()], }); const validSchema = ` type Post @model @@ -206,13 +182,7 @@ test('implicit owner fields from field level auth get added to the type', () => }; const transformer = new GraphQLTransform({ authConfig, - transformers: [ - new ModelTransformer(), - new AuthTransformer({ - authConfig, - addAwsIamAuthInOutputSchema: false, - }), - ], + transformers: [new ModelTransformer(), new AuthTransformer()], }); const out = transformer.transform(validSchema); expect(out).toBeDefined(); diff --git a/packages/amplify-graphql-auth-transformer/src/__tests__/searchable-auth.test.ts b/packages/amplify-graphql-auth-transformer/src/__tests__/searchable-auth.test.ts index 4cfd3491014..0419d7a9473 100644 --- a/packages/amplify-graphql-auth-transformer/src/__tests__/searchable-auth.test.ts +++ b/packages/amplify-graphql-auth-transformer/src/__tests__/searchable-auth.test.ts @@ -46,14 +46,7 @@ test('auth logic is enabled on owner/static rules in es request', () => { }; const transformer = new GraphQLTransform({ authConfig, - transformers: [ - new ModelTransformer(), - new SearchableModelTransformer(), - new AuthTransformer({ - authConfig, - addAwsIamAuthInOutputSchema: false, - }), - ], + transformers: [new ModelTransformer(), new SearchableModelTransformer(), new AuthTransformer()], }); const out = transformer.transform(validSchema); // expect response resolver to contain auth logic for owner rule @@ -100,14 +93,7 @@ test('auth logic is enabled for iam/apiKey auth rules', () => { }; const transformer = new GraphQLTransform({ authConfig, - transformers: [ - new ModelTransformer(), - new SearchableModelTransformer(), - new AuthTransformer({ - authConfig, - addAwsIamAuthInOutputSchema: false, - }), - ], + transformers: [new ModelTransformer(), new SearchableModelTransformer(), new AuthTransformer()], }); const out = transformer.transform(validSchema); expect(out).toBeDefined(); diff --git a/packages/amplify-graphql-auth-transformer/src/graphql-auth-transformer.ts b/packages/amplify-graphql-auth-transformer/src/graphql-auth-transformer.ts index c7a7f241dce..e733b173f76 100644 --- a/packages/amplify-graphql-auth-transformer/src/graphql-auth-transformer.ts +++ b/packages/amplify-graphql-auth-transformer/src/graphql-auth-transformer.ts @@ -113,7 +113,7 @@ export class AuthTransformer extends TransformerAuthBase implements TransformerA private authPolicyResources = new Set(); private unauthPolicyResources = new Set(); - constructor(config: AuthTransformerConfig = { addAwsIamAuthInOutputSchema: false }) { + constructor(config: AuthTransformerConfig = { adminRoles: [] }) { super('amplify-auth-transformer', authDirectiveDefinition); this.config = config; this.modelDirectiveConfig = new Map(); @@ -845,7 +845,7 @@ Static group authorization should perform as expected.`, for (let role of roles) { providers.add(this.roleMap.get(role)!.provider); } - if (this.configuredAuthProviders.hasAdminUIEnabled) { + if (this.configuredAuthProviders.hasAdminRolesEnabled) { providers.add('iam'); } return Array.from(providers); @@ -965,7 +965,9 @@ Static group authorization should perform as expected.`, * @returns boolean */ private shouldAddDefaultServiceDirective(): boolean { - return this.configuredAuthProviders.hasAdminUIEnabled && this.config.authConfig.defaultAuthentication.authenticationType !== 'AWS_IAM'; + return ( + this.configuredAuthProviders.hasAdminRolesEnabled && this.config.authConfig.defaultAuthentication.authenticationType !== 'AWS_IAM' + ); } /* IAM Helpers @@ -976,7 +978,7 @@ Static group authorization should perform as expected.`, // Sanity check to make sure we're not generating invalid policies, where no resources are defined. if (this.authPolicyResources.size === 0) { // When AdminUI is enabled, IAM auth is added but it does not need any policies to be generated - if (!this.configuredAuthProviders.hasAdminUIEnabled) { + if (!this.configuredAuthProviders.hasAdminRolesEnabled) { throw new TransformerContractError('AuthRole policies should be generated, but no resources were added.'); } } else { diff --git a/packages/amplify-graphql-auth-transformer/src/resolvers/field.ts b/packages/amplify-graphql-auth-transformer/src/resolvers/field.ts index 3e1fe630096..af94a10e6b6 100644 --- a/packages/amplify-graphql-auth-transformer/src/resolvers/field.ts +++ b/packages/amplify-graphql-auth-transformer/src/resolvers/field.ts @@ -32,7 +32,15 @@ import { IS_AUTHORIZED_FLAG, API_KEY_AUTH_TYPE, } from '../utils'; -import { getOwnerClaim, generateStaticRoleExpression, apiKeyExpression, iamExpression, emptyPayload, lambdaExpression, getIdentityClaimExp } from './helpers'; +import { + getOwnerClaim, + generateStaticRoleExpression, + apiKeyExpression, + iamExpression, + emptyPayload, + lambdaExpression, + getIdentityClaimExp, +} from './helpers'; // Field Read VTL Functions const generateDynamicAuthReadExpression = (roles: Array, fields: ReadonlyArray) => { @@ -89,7 +97,8 @@ export const generateAuthExpressionForField = ( roles: Array, fields: ReadonlyArray, ): string => { - const { cogntoStaticRoles, cognitoDynamicRoles, oidcStaticRoles, oidcDynamicRoles, iamRoles, apiKeyRoles, lambdaRoles } = splitRoles(roles); + const { cogntoStaticRoles, cognitoDynamicRoles, oidcStaticRoles, oidcDynamicRoles, iamRoles, apiKeyRoles, lambdaRoles } = + splitRoles(roles); const totalAuthExpressions: Array = [set(ref(IS_AUTHORIZED_FLAG), bool(false))]; if (provider.hasApiKey) { totalAuthExpressions.push(apiKeyExpression(apiKeyRoles)); @@ -98,7 +107,7 @@ export const generateAuthExpressionForField = ( totalAuthExpressions.push(lambdaExpression(lambdaRoles)); } if (provider.hasIAM) { - totalAuthExpressions.push(iamExpression(iamRoles, provider.hasAdminUIEnabled, provider.adminUserPoolID)); + totalAuthExpressions.push(iamExpression(iamRoles, provider.hasAdminRolesEnabled, provider.adminRoles)); } if (provider.hasUserPools) { totalAuthExpressions.push( diff --git a/packages/amplify-graphql-auth-transformer/src/resolvers/helpers.ts b/packages/amplify-graphql-auth-transformer/src/resolvers/helpers.ts index 720f3ff95eb..ff4a7842af3 100644 --- a/packages/amplify-graphql-auth-transformer/src/resolvers/helpers.ts +++ b/packages/amplify-graphql-auth-transformer/src/resolvers/helpers.ts @@ -17,7 +17,6 @@ import { forEach, list, equals, - or, } from 'graphql-mapping-template'; import { NONE_VALUE } from 'graphql-transformer-common'; import { @@ -27,9 +26,7 @@ import { ALLOWED_FIELDS, API_KEY_AUTH_TYPE, LAMBDA_AUTH_TYPE, - ADMIN_ROLE, IAM_AUTH_TYPE, - MANAGE_ROLE, } from '../utils'; // note in the resolver that operation is protected by auth @@ -112,37 +109,40 @@ export const apiKeyExpression = (roles: Array) => { equals(ref('util.authType()'), str(API_KEY_AUTH_TYPE)), compoundExpression([...(roles.length > 0 ? [set(ref(IS_AUTHORIZED_FLAG), bool(true))] : [])]), ); -} +}; export const lambdaExpression = (roles: Array) => { return iff( equals(ref('util.authType()'), str(LAMBDA_AUTH_TYPE)), compoundExpression([...(roles.length > 0 ? [set(ref(IS_AUTHORIZED_FLAG), bool(true))] : [])]), ); -} +}; -export const iamExpression = (roles: Array, adminuiEnabled: boolean = false, adminUserPoolID?: string) => { +export const iamExpression = (roles: Array, adminRolesEnabled: boolean, adminRoles: Array = []) => { const expression = new Array(); - // allow if using admin ui - if (adminuiEnabled) { - expression.push( - iff( - or([ - methodCall(ref('ctx.identity.userArn.contains'), str(`${adminUserPoolID}${ADMIN_ROLE}`)), - methodCall(ref('ctx.identity.userArn.contains'), str(`${adminUserPoolID}${MANAGE_ROLE}`)), - ]), - raw('#return($util.toJson({})'), - ), - ); + // allow if using an admin role + if (adminRolesEnabled) { + expression.push(iamAdminRoleCheckExpression(adminRoles)); } if (roles.length > 0) { for (let role of roles) { expression.push(iff(not(ref(IS_AUTHORIZED_FLAG)), iamCheck(role.claim!, set(ref(IS_AUTHORIZED_FLAG), bool(true))))); } + } else { + expression.push(ref('util.unauthorized()')); } return iff(equals(ref('util.authType()'), str(IAM_AUTH_TYPE)), compoundExpression(expression)); }; +export const iamAdminRoleCheckExpression = (adminRoles: Array): Expression => { + return compoundExpression([ + set(ref('adminRoles'), raw(JSON.stringify(adminRoles))), + forEach(/*for */ ref('adminRole'), /* in */ ref('adminRoles'), [ + iff(methodCall(ref('ctx.identity.userArn.contains'), ref('adminRole')), raw('#return($util.toJson({}))')), + ]), + ]); +}; + // Get Request for Update and Delete export const generateAuthRequestExpression = () => { const statements = [ diff --git a/packages/amplify-graphql-auth-transformer/src/resolvers/mutation.create.ts b/packages/amplify-graphql-auth-transformer/src/resolvers/mutation.create.ts index 9b65f6f8f68..6b858f97c6e 100644 --- a/packages/amplify-graphql-auth-transformer/src/resolvers/mutation.create.ts +++ b/packages/amplify-graphql-auth-transformer/src/resolvers/mutation.create.ts @@ -17,7 +17,6 @@ import { forEach, equals, str, - or, printBlock, } from 'graphql-mapping-template'; import { @@ -28,15 +27,14 @@ import { emptyPayload, setHasAuthExpression, iamCheck, + iamAdminRoleCheckExpression, } from './helpers'; import { - ADMIN_ROLE, API_KEY_AUTH_TYPE, LAMBDA_AUTH_TYPE, COGNITO_AUTH_TYPE, ConfiguredAuthProviders, IAM_AUTH_TYPE, - MANAGE_ROLE, OIDC_AUTH_TYPE, RoleDefinition, splitRoles, @@ -69,19 +67,11 @@ const apiKeyExpression = (roles: Array) => { * @param roles * @returns */ -const iamExpression = (roles: Array, hasAdminUIEnabled: boolean = false, adminUserPoolID?: string) => { +const iamExpression = (roles: Array, hasAdminRolesEnabled: boolean = false, adminRoles: Array = []) => { const expression = new Array(); - // allow if using admin ui - if (hasAdminUIEnabled) { - expression.push( - iff( - or([ - methodCall(ref('ctx.identity.userArn.contains'), str(`${adminUserPoolID!}${ADMIN_ROLE}`)), - methodCall(ref('ctx.identity.userArn.contains'), str(`${adminUserPoolID!}${MANAGE_ROLE}`)), - ]), - raw('#return($util.toJson({})'), - ), - ); + // allow if using an admin role + if (hasAdminRolesEnabled) { + expression.push(iamAdminRoleCheckExpression(adminRoles)); } if (roles.length > 0) { for (let role of roles) { @@ -104,7 +94,7 @@ const iamExpression = (roles: Array, hasAdminUIEnabled: boolean * @param roles * @returns Expression | null */ - const lambdaExpression = (roles: Array) => { +const lambdaExpression = (roles: Array) => { const expression = new Array(); if (roles.length === 0) { return iff(equals(ref('util.authType()'), str(LAMBDA_AUTH_TYPE)), ref('util.unauthorized()')); @@ -253,7 +243,7 @@ export const generateAuthExpressionForCreate = ( totalAuthExpressions.push(apiKeyExpression(apiKeyRoles)); } if (providers.hasIAM) { - totalAuthExpressions.push(iamExpression(iamRoles, providers.hasAdminUIEnabled, providers.adminUserPoolID)); + totalAuthExpressions.push(iamExpression(iamRoles, providers.hasAdminRolesEnabled, providers.adminRoles)); } if (providers.hasLambda) { totalAuthExpressions.push(lambdaExpression(lambdaRoles)); diff --git a/packages/amplify-graphql-auth-transformer/src/resolvers/mutation.delete.ts b/packages/amplify-graphql-auth-transformer/src/resolvers/mutation.delete.ts index 49c2d09e121..a6c1e8546ad 100644 --- a/packages/amplify-graphql-auth-transformer/src/resolvers/mutation.delete.ts +++ b/packages/amplify-graphql-auth-transformer/src/resolvers/mutation.delete.ts @@ -11,15 +11,13 @@ import { set, str, methodCall, - or, forEach, list, not, nul, } from 'graphql-mapping-template'; -import { emptyPayload, getIdentityClaimExp, getOwnerClaim, iamCheck, setHasAuthExpression } from './helpers'; +import { emptyPayload, getIdentityClaimExp, getOwnerClaim, iamAdminRoleCheckExpression, iamCheck, setHasAuthExpression } from './helpers'; import { - ADMIN_ROLE, API_KEY_AUTH_TYPE, COGNITO_AUTH_TYPE, LAMBDA_AUTH_TYPE, @@ -27,7 +25,6 @@ import { fieldIsList, IAM_AUTH_TYPE, IS_AUTHORIZED_FLAG, - MANAGE_ROLE, OIDC_AUTH_TYPE, RoleDefinition, splitRoles, @@ -52,19 +49,11 @@ const apiKeyExpression = (roles: Array) => { * @param roles * @returns */ -const iamExpression = (roles: Array, hasAdminUIEnabled: boolean = false, adminUserPoolID?: string) => { +const iamExpression = (roles: Array, hasAdminRolesEnabled: boolean = false, adminRoles: Array = []) => { const expression = new Array(); - // allow if using admin ui - if (hasAdminUIEnabled) { - expression.push( - iff( - or([ - methodCall(ref('ctx.identity.userArn.contains'), str(`${adminUserPoolID}${ADMIN_ROLE}`)), - methodCall(ref('ctx.identity.userArn.contains'), str(`${adminUserPoolID}${MANAGE_ROLE}`)), - ]), - raw('#return($util.toJson({})'), - ), - ); + // allow if using an admin role + if (hasAdminRolesEnabled) { + expression.push(iamAdminRoleCheckExpression(adminRoles)); } if (roles.length > 0) { for (let role of roles) { @@ -81,7 +70,7 @@ const iamExpression = (roles: Array, hasAdminUIEnabled: boolean * @param roles * @returns Expression | null */ - const lambdaExpression = (roles: Array) => { +const lambdaExpression = (roles: Array) => { const expression = new Array(); if (roles.length === 0) { return iff(equals(ref('util.authType()'), str(LAMBDA_AUTH_TYPE)), ref('util.unauthorized()')); @@ -172,13 +161,14 @@ export const geneateAuthExpressionForDelete = ( roles: Array, fields: ReadonlyArray, ) => { - const { cogntoStaticRoles, cognitoDynamicRoles, oidcStaticRoles, oidcDynamicRoles, apiKeyRoles, iamRoles, lambdaRoles } = splitRoles(roles); + const { cogntoStaticRoles, cognitoDynamicRoles, oidcStaticRoles, oidcDynamicRoles, apiKeyRoles, iamRoles, lambdaRoles } = + splitRoles(roles); const totalAuthExpressions: Array = [setHasAuthExpression, set(ref(IS_AUTHORIZED_FLAG), bool(false))]; if (providers.hasApiKey) { totalAuthExpressions.push(apiKeyExpression(apiKeyRoles)); } if (providers.hasIAM) { - totalAuthExpressions.push(iamExpression(iamRoles, providers.hasAdminUIEnabled, providers.adminUserPoolID)); + totalAuthExpressions.push(iamExpression(iamRoles, providers.hasAdminRolesEnabled, providers.adminRoles)); } if (providers.hasLambda) { totalAuthExpressions.push(lambdaExpression(lambdaRoles)); diff --git a/packages/amplify-graphql-auth-transformer/src/resolvers/mutation.update.ts b/packages/amplify-graphql-auth-transformer/src/resolvers/mutation.update.ts index 75107b7ff58..e083c86108e 100644 --- a/packages/amplify-graphql-auth-transformer/src/resolvers/mutation.update.ts +++ b/packages/amplify-graphql-auth-transformer/src/resolvers/mutation.update.ts @@ -23,13 +23,11 @@ import { or, } from 'graphql-mapping-template'; import { - ADMIN_ROLE, API_KEY_AUTH_TYPE, COGNITO_AUTH_TYPE, LAMBDA_AUTH_TYPE, ConfiguredAuthProviders, IAM_AUTH_TYPE, - MANAGE_ROLE, OIDC_AUTH_TYPE, RoleDefinition, splitRoles, @@ -39,7 +37,15 @@ import { NULL_ALLOWED_FIELDS, DENIED_FIELDS, } from '../utils'; -import { getIdentityClaimExp, responseCheckForErrors, getOwnerClaim, getInputFields, setHasAuthExpression, iamCheck } from './helpers'; +import { + getIdentityClaimExp, + responseCheckForErrors, + getOwnerClaim, + getInputFields, + setHasAuthExpression, + iamCheck, + iamAdminRoleCheckExpression, +} from './helpers'; /** * There is only one role for ApiKey we can use the first index @@ -67,7 +73,7 @@ const apiKeyExpression = (roles: Array) => { * @param roles * @returns Expression | null */ - const lambdaExpression = (roles: Array) => { +const lambdaExpression = (roles: Array) => { const expression = new Array(); if (roles.length === 0) { return iff(equals(ref('util.authType()'), str(LAMBDA_AUTH_TYPE)), ref('util.unauthorized()')); @@ -83,19 +89,11 @@ const apiKeyExpression = (roles: Array) => { return iff(equals(ref('util.authType()'), str(LAMBDA_AUTH_TYPE)), compoundExpression(expression)); }; -const iamExpression = (roles: Array, hasAdminUIEnabled: boolean = false, adminUserPoolID?: string) => { +const iamExpression = (roles: Array, hasAdminRolesEnabled: boolean = false, adminRoles: Array = []) => { const expression = new Array(); - // allow if using admin ui - if (hasAdminUIEnabled) { - expression.push( - iff( - or([ - methodCall(ref('ctx.identity.userArn.contains'), str(`${adminUserPoolID}${ADMIN_ROLE}`)), - methodCall(ref('ctx.identity.userArn.contains'), str(`${adminUserPoolID}${MANAGE_ROLE}`)), - ]), - raw('#return($util.toJson({})'), - ), - ); + // allow if using an admin role + if (hasAdminRolesEnabled) { + expression.push(iamAdminRoleCheckExpression(adminRoles)); } if (roles.length > 0) { for (let role of roles) { @@ -276,7 +274,8 @@ export const generateAuthExpressionForUpdate = ( roles: Array, fields: ReadonlyArray, ) => { - const { cogntoStaticRoles, cognitoDynamicRoles, oidcStaticRoles, oidcDynamicRoles, apiKeyRoles, iamRoles, lambdaRoles } = splitRoles(roles); + const { cogntoStaticRoles, cognitoDynamicRoles, oidcStaticRoles, oidcDynamicRoles, apiKeyRoles, iamRoles, lambdaRoles } = + splitRoles(roles); const totalAuthExpressions: Array = [ setHasAuthExpression, responseCheckForErrors(), @@ -293,7 +292,7 @@ export const generateAuthExpressionForUpdate = ( totalAuthExpressions.push(lambdaExpression(lambdaRoles)); } if (providers.hasIAM) { - totalAuthExpressions.push(iamExpression(iamRoles, providers.hasAdminUIEnabled, providers.adminUserPoolID)); + totalAuthExpressions.push(iamExpression(iamRoles, providers.hasAdminRolesEnabled, providers.adminRoles)); } if (providers.hasUserPools) { totalAuthExpressions.push( diff --git a/packages/amplify-graphql-auth-transformer/src/resolvers/query.ts b/packages/amplify-graphql-auth-transformer/src/resolvers/query.ts index ff307694790..4ffde264f74 100644 --- a/packages/amplify-graphql-auth-transformer/src/resolvers/query.ts +++ b/packages/amplify-graphql-auth-transformer/src/resolvers/query.ts @@ -20,7 +20,15 @@ import { ifElse, nul, } from 'graphql-mapping-template'; -import { getIdentityClaimExp, getOwnerClaim, apiKeyExpression, iamExpression, lambdaExpression, emptyPayload, setHasAuthExpression } from './helpers'; +import { + getIdentityClaimExp, + getOwnerClaim, + apiKeyExpression, + iamExpression, + lambdaExpression, + emptyPayload, + setHasAuthExpression, +} from './helpers'; import { COGNITO_AUTH_TYPE, OIDC_AUTH_TYPE, @@ -248,7 +256,8 @@ export const generateAuthExpressionForQueries = ( primaryFields: Array, isIndexQuery = false, ): string => { - const { cogntoStaticRoles, cognitoDynamicRoles, oidcStaticRoles, oidcDynamicRoles, apiKeyRoles, iamRoles, lambdaRoles } = splitRoles(roles); + const { cogntoStaticRoles, cognitoDynamicRoles, oidcStaticRoles, oidcDynamicRoles, apiKeyRoles, iamRoles, lambdaRoles } = + splitRoles(roles); const getNonPrimaryFieldRoles = (roles: RoleDefinition[]) => roles.filter(roles => !primaryFields.includes(roles.entity)); const totalAuthExpressions: Array = [ setHasAuthExpression, @@ -262,7 +271,7 @@ export const generateAuthExpressionForQueries = ( totalAuthExpressions.push(lambdaExpression(lambdaRoles)); } if (providers.hasIAM) { - totalAuthExpressions.push(iamExpression(iamRoles, providers.hasAdminUIEnabled, providers.adminUserPoolID)); + totalAuthExpressions.push(iamExpression(iamRoles, providers.hasAdminRolesEnabled, providers.adminRoles)); } if (providers.hasUserPools) { totalAuthExpressions.push( @@ -303,7 +312,8 @@ export const generateAuthExpressionForRelationQuery = ( fields: ReadonlyArray, primaryFieldMap: RelationalPrimaryMapConfig, ) => { - const { cogntoStaticRoles, cognitoDynamicRoles, oidcStaticRoles, oidcDynamicRoles, apiKeyRoles, iamRoles, lambdaRoles } = splitRoles(roles); + const { cogntoStaticRoles, cognitoDynamicRoles, oidcStaticRoles, oidcDynamicRoles, apiKeyRoles, iamRoles, lambdaRoles } = + splitRoles(roles); const getNonPrimaryFieldRoles = (roles: RoleDefinition[]) => roles.filter(roles => !primaryFieldMap.has(roles.entity)); const totalAuthExpressions: Array = [ setHasAuthExpression, @@ -317,7 +327,7 @@ export const generateAuthExpressionForRelationQuery = ( totalAuthExpressions.push(lambdaExpression(lambdaRoles)); } if (providers.hasIAM) { - totalAuthExpressions.push(iamExpression(iamRoles, providers.hasAdminUIEnabled, providers.adminUserPoolID)); + totalAuthExpressions.push(iamExpression(iamRoles, providers.hasAdminRolesEnabled, providers.adminRoles)); } if (providers.hasUserPools) { totalAuthExpressions.push( diff --git a/packages/amplify-graphql-auth-transformer/src/resolvers/search.ts b/packages/amplify-graphql-auth-transformer/src/resolvers/search.ts index cb1e820d642..0c700b8cf33 100644 --- a/packages/amplify-graphql-auth-transformer/src/resolvers/search.ts +++ b/packages/amplify-graphql-auth-transformer/src/resolvers/search.ts @@ -19,9 +19,8 @@ import { raw, set, ifElse, - or, } from 'graphql-mapping-template'; -import { getIdentityClaimExp, getOwnerClaim, emptyPayload, setHasAuthExpression, iamCheck } from './helpers'; +import { getIdentityClaimExp, getOwnerClaim, emptyPayload, setHasAuthExpression, iamCheck, iamAdminRoleCheckExpression } from './helpers'; import { COGNITO_AUTH_TYPE, OIDC_AUTH_TYPE, @@ -31,10 +30,8 @@ import { ConfiguredAuthProviders, IS_AUTHORIZED_FLAG, fieldIsList, - ADMIN_ROLE, API_KEY_AUTH_TYPE, IAM_AUTH_TYPE, - MANAGE_ROLE, } from '../utils'; import { NONE_VALUE } from 'graphql-transformer-common'; @@ -72,19 +69,11 @@ const lambdaExpression = (roles: Array): Expression => { return iff(equals(ref('util.authType()'), str(LAMBDA_AUTH_TYPE)), compoundExpression(expression)); }; -const iamExpression = (roles: Array, adminuiEnabled: boolean = false, adminUserPoolID?: string) => { +const iamExpression = (roles: Array, hasAdminRolesEnabled: boolean = false, adminRoles: Array = []) => { const expression = new Array(); - // allow if using admin ui - if (adminuiEnabled) { - expression.push( - iff( - or([ - methodCall(ref('ctx.identity.userArn.contains'), str(`${adminUserPoolID}${ADMIN_ROLE}`)), - methodCall(ref('ctx.identity.userArn.contains'), str(`${adminUserPoolID}${MANAGE_ROLE}`)), - ]), - raw('#return($util.toJson({})'), - ), - ); + // allow if using an admin role + if (hasAdminRolesEnabled) { + expression.push(iamAdminRoleCheckExpression(adminRoles)); } if (roles.length === 0) { expression.push(ref('util.unauthorized()')); @@ -244,7 +233,8 @@ export const generateAuthExpressionForSearchQueries = ( fields: ReadonlyArray, allowedAggFields: Array, ): string => { - const { cogntoStaticRoles, cognitoDynamicRoles, oidcStaticRoles, oidcDynamicRoles, apiKeyRoles, iamRoles, lambdaRoles } = splitRoles(roles); + const { cogntoStaticRoles, cognitoDynamicRoles, oidcStaticRoles, oidcDynamicRoles, apiKeyRoles, iamRoles, lambdaRoles } = + splitRoles(roles); const totalAuthExpressions: Array = [ setHasAuthExpression, set(ref(IS_AUTHORIZED_FLAG), bool(false)), @@ -258,7 +248,7 @@ export const generateAuthExpressionForSearchQueries = ( totalAuthExpressions.push(lambdaExpression(lambdaRoles)); } if (providers.hasIAM) { - totalAuthExpressions.push(iamExpression(iamRoles, providers.hasAdminUIEnabled, providers.adminUserPoolID)); + totalAuthExpressions.push(iamExpression(iamRoles, providers.hasAdminRolesEnabled, providers.adminRoles)); } if (providers.hasUserPools) { totalAuthExpressions.push( diff --git a/packages/amplify-graphql-auth-transformer/src/resolvers/subscriptions.ts b/packages/amplify-graphql-auth-transformer/src/resolvers/subscriptions.ts index 0f739bcf00f..f9567c8e13c 100644 --- a/packages/amplify-graphql-auth-transformer/src/resolvers/subscriptions.ts +++ b/packages/amplify-graphql-auth-transformer/src/resolvers/subscriptions.ts @@ -45,7 +45,8 @@ const dynamicRoleExpression = (roles: Array): Array }; export const generateAuthExpressionForSubscriptions = (providers: ConfiguredAuthProviders, roles: Array): string => { - const { cogntoStaticRoles, cognitoDynamicRoles, oidcStaticRoles, oidcDynamicRoles, iamRoles, apiKeyRoles, lambdaRoles } = splitRoles(roles); + const { cogntoStaticRoles, cognitoDynamicRoles, oidcStaticRoles, oidcDynamicRoles, iamRoles, apiKeyRoles, lambdaRoles } = + splitRoles(roles); const totalAuthExpressions: Array = [setHasAuthExpression, set(ref(IS_AUTHORIZED_FLAG), bool(false))]; if (providers.hasApiKey) { totalAuthExpressions.push(apiKeyExpression(apiKeyRoles)); @@ -54,7 +55,7 @@ export const generateAuthExpressionForSubscriptions = (providers: ConfiguredAuth totalAuthExpressions.push(lambdaExpression(lambdaRoles)); } if (providers.hasIAM) { - totalAuthExpressions.push(iamExpression(iamRoles, providers.hasAdminUIEnabled, providers.adminUserPoolID)); + totalAuthExpressions.push(iamExpression(iamRoles, providers.hasAdminRolesEnabled, providers.adminRoles)); } if (providers.hasUserPools) totalAuthExpressions.push( diff --git a/packages/amplify-graphql-auth-transformer/src/utils/constants.ts b/packages/amplify-graphql-auth-transformer/src/utils/constants.ts index 392b70fda95..48785e438b9 100644 --- a/packages/amplify-graphql-auth-transformer/src/utils/constants.ts +++ b/packages/amplify-graphql-auth-transformer/src/utils/constants.ts @@ -27,9 +27,6 @@ export const IS_AUTHORIZED_FLAG = 'isAuthorized'; export const ALLOWED_FIELDS = 'allowedFields'; export const NULL_ALLOWED_FIELDS = 'nullAllowedFields'; export const DENIED_FIELDS = 'deniedFields'; -// Admin Roles -export const ADMIN_ROLE = '_Full-access/CognitoIdentityCredentials'; -export const MANAGE_ROLE = '_Manage-only/CognitoIdentityCredentials'; // resolver export const NONE_DS = 'NONE_DS'; // relational directives diff --git a/packages/amplify-graphql-auth-transformer/src/utils/definitions.ts b/packages/amplify-graphql-auth-transformer/src/utils/definitions.ts index 1254af08b68..3aebb42b235 100644 --- a/packages/amplify-graphql-auth-transformer/src/utils/definitions.ts +++ b/packages/amplify-graphql-auth-transformer/src/utils/definitions.ts @@ -58,14 +58,14 @@ export interface ConfiguredAuthProviders { hasOIDC: boolean; hasIAM: boolean; hasLambda: boolean; - hasAdminUIEnabled: boolean; + hasAdminRolesEnabled: boolean; + adminRoles: Array; adminUserPoolID?: string; } export interface AuthTransformerConfig { - addAwsIamAuthInOutputSchema: boolean; + adminRoles?: Array; authConfig?: AppSyncAuthConfiguration; - adminUserPoolID?: string; } export const authDirectiveDefinition = ` diff --git a/packages/amplify-graphql-auth-transformer/src/utils/index.ts b/packages/amplify-graphql-auth-transformer/src/utils/index.ts index 58467db0b70..c5dcd381796 100644 --- a/packages/amplify-graphql-auth-transformer/src/utils/index.ts +++ b/packages/amplify-graphql-auth-transformer/src/utils/index.ts @@ -100,8 +100,8 @@ export const getConfiguredAuthProviders = (config: AuthTransformerConfig): Confi const configuredProviders: ConfiguredAuthProviders = { default: getAuthProvider(config.authConfig.defaultAuthentication.authenticationType), onlyDefaultAuthProviderConfigured: config.authConfig.additionalAuthenticationProviders.length === 0, - hasAdminUIEnabled: hasIAM && config.addAwsIamAuthInOutputSchema, - adminUserPoolID: config.adminUserPoolID!, + hasAdminRolesEnabled: hasIAM && config.adminRoles.length > 0, + adminRoles: config.adminRoles, hasApiKey: providers.some(p => p === 'API_KEY'), hasUserPools: providers.some(p => p === 'AMAZON_COGNITO_USER_POOLS'), hasOIDC: providers.some(p => p === 'OPENID_CONNECT'), diff --git a/packages/amplify-graphql-relational-transformer/src/__tests__/amplify-graphql-many-to-many-transformer.test.ts b/packages/amplify-graphql-relational-transformer/src/__tests__/amplify-graphql-many-to-many-transformer.test.ts index d91541dc2d1..2888a6ba154 100644 --- a/packages/amplify-graphql-relational-transformer/src/__tests__/amplify-graphql-many-to-many-transformer.test.ts +++ b/packages/amplify-graphql-relational-transformer/src/__tests__/amplify-graphql-many-to-many-transformer.test.ts @@ -298,7 +298,7 @@ function createTransformer() { }, additionalAuthenticationProviders: [{ authenticationType: 'AWS_IAM' }], }; - const authTransformer = new AuthTransformer({ authConfig, addAwsIamAuthInOutputSchema: false }); + const authTransformer = new AuthTransformer(); const modelTransformer = new ModelTransformer(); const indexTransformer = new IndexTransformer(); const hasOneTransformer = new HasOneTransformer(); diff --git a/packages/amplify-graphql-relational-transformer/src/__tests__/relational-auth.test.ts b/packages/amplify-graphql-relational-transformer/src/__tests__/relational-auth.test.ts index 7523c593ad5..7255849c275 100644 --- a/packages/amplify-graphql-relational-transformer/src/__tests__/relational-auth.test.ts +++ b/packages/amplify-graphql-relational-transformer/src/__tests__/relational-auth.test.ts @@ -40,14 +40,7 @@ test('per-field auth on relational field', () => { }; const transformer = new GraphQLTransform({ authConfig, - transformers: [ - new ModelTransformer(), - new HasManyTransformer(), - new AuthTransformer({ - authConfig, - addAwsIamAuthInOutputSchema: false, - }), - ], + transformers: [new ModelTransformer(), new HasManyTransformer(), new AuthTransformer()], }); const out = transformer.transform(validSchema); expect(out).toBeDefined(); @@ -141,10 +134,7 @@ const getTransformer = (authConfig: AppSyncAuthConfiguration) => { new IndexTransformer(), new HasManyTransformer(), new BelongsToTransformer(), - new AuthTransformer({ - authConfig, - addAwsIamAuthInOutputSchema: false, - }), + new AuthTransformer(), ], }); }; diff --git a/packages/amplify-provider-awscloudformation/src/graphql-transformer/transform-graphql-schema.ts b/packages/amplify-provider-awscloudformation/src/graphql-transformer/transform-graphql-schema.ts index 01f5a169c61..70d344b2819 100644 --- a/packages/amplify-provider-awscloudformation/src/graphql-transformer/transform-graphql-schema.ts +++ b/packages/amplify-provider-awscloudformation/src/graphql-transformer/transform-graphql-schema.ts @@ -27,15 +27,14 @@ import { SearchableModelTransformer } from '@aws-amplify/graphql-searchable-tran import { DefaultValueTransformer } from '@aws-amplify/graphql-default-value-transformer'; import { destructiveUpdatesFlag, ProviderName as providerName } from '../constants'; import { hashDirectory } from '../upload-appsync-files'; -import { mergeUserConfigWithTransformOutput, writeDeploymentToDisk } from './utils'; +import { getAdminRoles, mergeUserConfigWithTransformOutput, writeDeploymentToDisk } from './utils'; import { loadProject as readTransformerConfiguration } from './transform-config'; import { getSanityCheckRules, loadProject } from 'graphql-transformer-core'; import { Template } from '@aws-amplify/graphql-transformer-core/lib/config/project-config'; import { AmplifyCLIFeatureFlagAdapter } from '../utils/amplify-cli-feature-flag-adapter'; -import { JSONUtilities, stateManager, $TSContext } from 'amplify-cli-core'; +import { JSONUtilities, $TSContext } from 'amplify-cli-core'; import { searchablePushChecks } from '../transform-graphql-schema'; import { ResourceConstants } from 'graphql-transformer-common'; -import { isAmplifyAdminApp } from '../utils/admin-helpers'; import { showGlobalSandboxModeWarning, showSandboxModePrompts, @@ -77,23 +76,11 @@ function getTransformerFactory( // TODO: Build dependency mechanism into transformers. Auth runs last // so any resolvers that need to be protected will already be created. - let adminUserPoolID: string; - try { - const amplifyMeta = stateManager.getMeta(); - const appId = amplifyMeta?.providers?.[providerName]?.AmplifyAppId; - const res = await isAmplifyAdminApp(appId); - adminUserPoolID = res.userPoolID; - } catch (err) { - console.info('App not deployed yet.'); - } - const modelTransformer = new ModelTransformer(); const indexTransformer = new IndexTransformer(); const hasOneTransformer = new HasOneTransformer(); const authTransformer = new AuthTransformer({ - authConfig: options?.authConfig, - addAwsIamAuthInOutputSchema: !!adminUserPoolID, - adminUserPoolID, + adminRoles: options.authAdminIAMRoles ?? [], }); const transformerList: TransformerPluginProvider[] = [ modelTransformer, @@ -186,6 +173,7 @@ function getTransformerFactory( } export async function transformGraphQLSchema(context, options) { + let resourceName: string; const backEndDir = context.amplify.pathManager.getBackendDirPath(); const flags = context.parameters.options; if (flags['no-gql-override']) { @@ -238,7 +226,8 @@ export async function transformGraphQLSchema(context, options) { if (resource.providerPlugin !== providerName) { return; } - const { category, resourceName } = resource; + const { category } = resource; + resourceName = resource.resourceName; const cloudBackendRootDir = context.amplify.pathManager.getCurrentCloudBackendDirPath(); /* eslint-disable */ previouslyDeployedBackendDir = path.normalize(path.join(cloudBackendRootDir, category, resourceName)); @@ -277,6 +266,8 @@ export async function transformGraphQLSchema(context, options) { } } + // for auth check which functions have access to the api + const adminRoles = await getAdminRoles(context, resourceName); // for the predictions directive get storage config const s3Resource = s3ResourceAlreadyExists(context); const storageConfig = s3Resource ? getBucketName(context, s3Resource, backEndDir) : undefined; @@ -346,7 +337,12 @@ export async function transformGraphQLSchema(context, options) { buildParameters, projectDirectory: resourceDir, transformersFactory: transformerListFactory, - transformersFactoryArgs: { addSearchableTransformer: searchableTransformerFlag, storageConfig, authConfig }, + transformersFactoryArgs: { + addSearchableTransformer: searchableTransformerFlag, + storageConfig, + authConfig, + authAdminIAMRoles: adminRoles, + }, rootStackFileName: 'cloudformation-template.json', currentCloudBackendDirectory: previouslyDeployedBackendDir, minify: options.minify, @@ -441,6 +437,7 @@ type TransformerFactoryArgs = { addSearchableTransformer: boolean; authConfig: any; storageConfig?: any; + authAdminIAMRoles?: Array; }; export type ProjectOptions = { buildParameters: { diff --git a/packages/amplify-provider-awscloudformation/src/graphql-transformer/utils.ts b/packages/amplify-provider-awscloudformation/src/graphql-transformer/utils.ts index e656f56ad9e..b936dbd2a0f 100644 --- a/packages/amplify-provider-awscloudformation/src/graphql-transformer/utils.ts +++ b/packages/amplify-provider-awscloudformation/src/graphql-transformer/utils.ts @@ -2,13 +2,18 @@ import fs from 'fs-extra'; import * as path from 'path'; import { TransformerProjectConfig, DeploymentResources } from '@aws-amplify/graphql-transformer-core'; import rimraf from 'rimraf'; -import { JSONUtilities } from 'amplify-cli-core'; +import { ProviderName as providerName } from '../constants'; +import { $TSContext, JSONUtilities, stateManager } from 'amplify-cli-core'; import { CloudFormation, Template, Fn } from 'cloudform'; import { Diff, diff as getDiffs } from 'deep-diff'; import { ResourceConstants } from 'graphql-transformer-common'; +import { pullAllBy } from 'lodash'; +import { isAmplifyAdminApp } from '../utils/admin-helpers'; const ROOT_STACK_FILE_NAME = 'cloudformation-template.json'; const PARAMETERS_FILE_NAME = 'parameters.json'; +const AMPLIFY_ADMIN_ROLE = '_Full-access/CognitoIdentityCredentials'; +const AMPLIFY_MANAGE_ROLE = '_Manage-only/CognitoIdentityCredentials'; export interface DiffableProject { stacks: { [stackName: string]: Template; @@ -24,6 +29,31 @@ export interface GQLDiff { current: DiffableProject; } +export const getAdminRoles = async (ctx: $TSContext, apiResourceName: string): Promise> => { + const currentEnv = ctx.amplify.getEnvInfo().envName; + const adminRoles = new Array(); + //admin ui roles + try { + const amplifyMeta = stateManager.getMeta(); + const appId = amplifyMeta?.providers?.[providerName]?.AmplifyAppId; + const res = await isAmplifyAdminApp(appId); + if (res.userPoolID) { + adminRoles.push(`${res.userPoolID}${AMPLIFY_ADMIN_ROLE}`, `${res.userPoolID}${AMPLIFY_MANAGE_ROLE}`); + } + } catch (err) { + console.info('App not deployed yet.'); + // no need to error if not admin ui app + } + + // lambda functions which have access to the api + const { allResources, resourcesToBeDeleted } = await ctx.amplify.getResourceStatus('function'); + const resources = pullAllBy(allResources, resourcesToBeDeleted, 'resourceName') + .filter((r: any) => r.dependsOn.some(d => d.resourceName === apiResourceName)) + .map((r: any) => `${r.resourceName}-${currentEnv}`); + adminRoles.push(...resources); + return adminRoles; +}; + export const getGQLDiff = (currentBackendDir: string, cloudBackendDir: string): GQLDiff => { const currentBuildDir = path.join(currentBackendDir, 'build'); const cloudBuildDir = path.join(cloudBackendDir, 'build'); diff --git a/packages/graphql-transformers-e2e-tests/src/__tests__/AuthV2Transformer.e2e.test.ts b/packages/graphql-transformers-e2e-tests/src/__tests__/AuthV2Transformer.e2e.test.ts index 5721d076abd..8aa3c0e74a9 100644 --- a/packages/graphql-transformers-e2e-tests/src/__tests__/AuthV2Transformer.e2e.test.ts +++ b/packages/graphql-transformers-e2e-tests/src/__tests__/AuthV2Transformer.e2e.test.ts @@ -221,10 +221,7 @@ describe('@model with @auth', () => { new PrimaryKeyTransformer(), new IndexTransformer(), new HasOneTransformer(), - new AuthTransformer({ - authConfig, - addAwsIamAuthInOutputSchema: false, - }), + new AuthTransformer(), ], }); const userPoolResponse = await createUserPool(cognitoClient, `UserPool${STACK_NAME}`); diff --git a/packages/graphql-transformers-e2e-tests/src/__tests__/IndexWithAuthV2.e2e.test.ts b/packages/graphql-transformers-e2e-tests/src/__tests__/IndexWithAuthV2.e2e.test.ts index 6480ac22034..ba148ab5ab5 100644 --- a/packages/graphql-transformers-e2e-tests/src/__tests__/IndexWithAuthV2.e2e.test.ts +++ b/packages/graphql-transformers-e2e-tests/src/__tests__/IndexWithAuthV2.e2e.test.ts @@ -90,12 +90,7 @@ beforeAll(async () => { }, additionalAuthenticationProviders: [], }, - transformers: [ - new ModelTransformer(), - new PrimaryKeyTransformer(), - new IndexTransformer(), - new AuthTransformer({ addAwsIamAuthInOutputSchema: false }), - ], + transformers: [new ModelTransformer(), new PrimaryKeyTransformer(), new IndexTransformer(), new AuthTransformer()], }); const out = transformer.transform(validSchema); const finishedStack = await deploy( diff --git a/packages/graphql-transformers-e2e-tests/src/__tests__/MultiAuthV2Transformer.e2e.test.ts b/packages/graphql-transformers-e2e-tests/src/__tests__/MultiAuthV2Transformer.e2e.test.ts index 09a8d1d7ba1..fe0dfcb5838 100644 --- a/packages/graphql-transformers-e2e-tests/src/__tests__/MultiAuthV2Transformer.e2e.test.ts +++ b/packages/graphql-transformers-e2e-tests/src/__tests__/MultiAuthV2Transformer.e2e.test.ts @@ -295,9 +295,7 @@ beforeAll(async () => { new PrimaryKeyTransformer(), new HasOneTransformer(), new HasManyTransformer(), - new AuthTransformer({ - addAwsIamAuthInOutputSchema: false, - }), + new AuthTransformer(), ], }); diff --git a/packages/graphql-transformers-e2e-tests/src/__tests__/NonModelAuthV2Function.e2e.test.ts b/packages/graphql-transformers-e2e-tests/src/__tests__/NonModelAuthV2Function.e2e.test.ts index ffb0f95e34f..f588db504ae 100644 --- a/packages/graphql-transformers-e2e-tests/src/__tests__/NonModelAuthV2Function.e2e.test.ts +++ b/packages/graphql-transformers-e2e-tests/src/__tests__/NonModelAuthV2Function.e2e.test.ts @@ -107,13 +107,7 @@ beforeAll(async () => { }, ], }, - transformers: [ - new ModelTransformer(), - new FunctionTransformer(), - new AuthTransformer({ - addAwsIamAuthInOutputSchema: false, - }), - ], + transformers: [new ModelTransformer(), new FunctionTransformer(), new AuthTransformer()], }); const out = transformer.transform(validSchema); diff --git a/packages/graphql-transformers-e2e-tests/src/__tests__/PerFieldAuthV2Transformer.e2e.test.ts b/packages/graphql-transformers-e2e-tests/src/__tests__/PerFieldAuthV2Transformer.e2e.test.ts index 6126e08fc93..f311acd859a 100644 --- a/packages/graphql-transformers-e2e-tests/src/__tests__/PerFieldAuthV2Transformer.e2e.test.ts +++ b/packages/graphql-transformers-e2e-tests/src/__tests__/PerFieldAuthV2Transformer.e2e.test.ts @@ -178,12 +178,7 @@ beforeAll(async () => { }, additionalAuthenticationProviders: [], }, - transformers: [ - new ModelTransformer(), - new AuthTransformer({ - addAwsIamAuthInOutputSchema: false, - }), - ], + transformers: [new ModelTransformer(), new AuthTransformer()], }); const userPoolResponse = await createUserPool(cognitoClient, `UserPool${STACK_NAME}`); USER_POOL_ID = userPoolResponse.UserPool.Id; diff --git a/packages/graphql-transformers-e2e-tests/src/__tests__/RelationalTransformers.e2e.test.ts b/packages/graphql-transformers-e2e-tests/src/__tests__/RelationalTransformers.e2e.test.ts index 6223d8e1c38..9b36f8bee4d 100644 --- a/packages/graphql-transformers-e2e-tests/src/__tests__/RelationalTransformers.e2e.test.ts +++ b/packages/graphql-transformers-e2e-tests/src/__tests__/RelationalTransformers.e2e.test.ts @@ -127,7 +127,7 @@ type Course @model { }, additionalAuthenticationProviders: [], }; - const authTransformer = new AuthTransformer({ authConfig, addAwsIamAuthInOutputSchema: false }); + const authTransformer = new AuthTransformer(); const modelTransformer = new ModelTransformer(); const indexTransformer = new IndexTransformer(); const hasOneTransformer = new HasOneTransformer(); diff --git a/packages/graphql-transformers-e2e-tests/src/__tests__/RelationalWithAuthV2.e2e.test.ts b/packages/graphql-transformers-e2e-tests/src/__tests__/RelationalWithAuthV2.e2e.test.ts index cc325ee5d47..700f08a0c72 100644 --- a/packages/graphql-transformers-e2e-tests/src/__tests__/RelationalWithAuthV2.e2e.test.ts +++ b/packages/graphql-transformers-e2e-tests/src/__tests__/RelationalWithAuthV2.e2e.test.ts @@ -116,7 +116,7 @@ beforeAll(async () => { const modelTransformer = new ModelTransformer(); const indexTransformer = new IndexTransformer(); const hasOneTransformer = new HasOneTransformer(); - const authTransformer = new AuthTransformer({ addAwsIamAuthInOutputSchema: false }); + const authTransformer = new AuthTransformer(); const transformer = new GraphQLTransform({ authConfig: { defaultAuthentication: { diff --git a/packages/graphql-transformers-e2e-tests/src/__tests__/SearchableWithAuthV2.e2e.test.ts b/packages/graphql-transformers-e2e-tests/src/__tests__/SearchableWithAuthV2.e2e.test.ts index a4918323d9c..6d46719d187 100644 --- a/packages/graphql-transformers-e2e-tests/src/__tests__/SearchableWithAuthV2.e2e.test.ts +++ b/packages/graphql-transformers-e2e-tests/src/__tests__/SearchableWithAuthV2.e2e.test.ts @@ -167,7 +167,7 @@ beforeAll(async () => { }, ], }, - transformers: [new ModelTransformer(), new SearchableModelTransformer(), new AuthTransformer({ addAwsIamAuthInOutputSchema: false })], + transformers: [new ModelTransformer(), new SearchableModelTransformer(), new AuthTransformer()], }); const userPoolResponse = await createUserPool(cognitoClient, `UserPool${STACK_NAME}`); USER_POOL_ID = userPoolResponse.UserPool.Id; diff --git a/packages/graphql-transformers-e2e-tests/src/__tests__/SubscriptionsWithAuthV2.e2e.test.ts b/packages/graphql-transformers-e2e-tests/src/__tests__/SubscriptionsWithAuthV2.e2e.test.ts index ed08239d920..d3135db8766 100644 --- a/packages/graphql-transformers-e2e-tests/src/__tests__/SubscriptionsWithAuthV2.e2e.test.ts +++ b/packages/graphql-transformers-e2e-tests/src/__tests__/SubscriptionsWithAuthV2.e2e.test.ts @@ -222,7 +222,7 @@ beforeAll(async () => { }, ], }, - transformers: [new ModelTransformer(), new AuthTransformer({ addAwsIamAuthInOutputSchema: false })], + transformers: [new ModelTransformer(), new AuthTransformer()], }); try {