Skip to content

Commit

Permalink
fix(amplify-category-function): check for new function when adding pe…
Browse files Browse the repository at this point in the history
…rmissions (#8017)

* fix(amplify-category-function): check for new function when adding permissions

it is handled as new function when function not found in amplify meta

fix #7970

* test(amplify-category-function): remove unnecessary line

* Update packages/amplify-category-function/src/provider-utils/awscloudformation/service-walkthroughs/execPermissionsWalkthrough.ts

Co-authored-by: John Hockett <jhockett@users.noreply.github.com>

Co-authored-by: John Hockett <jhockett@users.noreply.github.com>
  • Loading branch information
fossamagna and jhockett authored Aug 25, 2021
1 parent 6ee02d9 commit 7af3b0d
Show file tree
Hide file tree
Showing 3 changed files with 277 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,129 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`askExecRolePermissionsQuestions returns permissions for exists function 1`] = `
Object {
"categoryPolicies": Array [
Object {
"Action": Array [
"lambda:Get*",
"lambda:List*",
"lambda:Invoke*",
],
"Effect": "Allow",
"Resource": Array [
Object {
"Fn::Join": Array [
"",
Array [
"arn:aws:lambda:",
Object {
"Ref": "AWS::Region",
},
":",
Object {
"Ref": "AWS::AccountId",
},
":function:",
Object {
"Ref": "functionlambda2Name",
},
],
],
},
],
},
],
"dependsOn": Array [
Object {
"attributes": Array [
"Name",
],
"category": "function",
"resourceName": "lambda2",
},
],
"environmentMap": Object {
"FUNCTION_LAMBDA2_NAME": Object {
"Ref": "functionlambda2Name",
},
},
"mutableParametersState": Object {
"permissions": Object {
"function": Object {
"lambda2": Array [
"read",
],
},
},
},
"topLevelComment": "/* Amplify Params - DO NOT EDIT
FUNCTION_LAMBDA2_NAME
Amplify Params - DO NOT EDIT */",
}
`;

exports[`askExecRolePermissionsQuestions returns permissions for function that be about to add right 1`] = `
Object {
"categoryPolicies": Array [
Object {
"Action": Array [
"lambda:Get*",
"lambda:List*",
"lambda:Invoke*",
],
"Effect": "Allow",
"Resource": Array [
Object {
"Fn::Join": Array [
"",
Array [
"arn:aws:lambda:",
Object {
"Ref": "AWS::Region",
},
":",
Object {
"Ref": "AWS::AccountId",
},
":function:",
Object {
"Ref": "functionlambda2Name",
},
],
],
},
],
},
],
"dependsOn": Array [
Object {
"attributes": Array [
"Name",
],
"category": "function",
"resourceName": "lambda2",
},
],
"environmentMap": Object {
"FUNCTION_LAMBDA2_NAME": Object {
"Ref": "functionlambda2Name",
},
},
"mutableParametersState": Object {
"permissions": Object {
"function": Object {
"lambda2": Array [
"read",
],
},
},
},
"topLevelComment": "/* Amplify Params - DO NOT EDIT
FUNCTION_LAMBDA2_NAME
Amplify Params - DO NOT EDIT */",
}
`;

exports[`check CFN resources 1`] = `
Object {
"cfnResources": Array [
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,39 @@
import { $TSContext } from 'amplify-cli-core';
import {
getResourcesForCfn,
generateEnvVariablesForCfn,
askExecRolePermissionsQuestions,
} from '../../../../provider-utils/awscloudformation/service-walkthroughs/execPermissionsWalkthrough';
import {
constructCFModelTableNameComponent,
constructCFModelTableArnComponent,
} from '../../../../provider-utils/awscloudformation/utils/cloudformationHelpers';
import { stateManager } from 'amplify-cli-core';
import { CRUDOperation } from '../../../../constants';
import inquirer from 'inquirer';

const backendDirPathStub = 'backendDirPath';

jest.mock('../../../../provider-utils/awscloudformation/utils/cloudformationHelpers');

jest.mock('amplify-cli-core', () => ({
stateManager: {
getMeta: jest.fn(),
},
FeatureFlags: {
getBoolean: jest.fn().mockReturnValue(false),
},
pathManager: {
getBackendDirPath: jest.fn(() => backendDirPathStub),
},
}));

jest.mock('inquirer', () => {
return {
prompt: jest.fn(),
};
});

export const appsyncTableSuffix = '@model(appsync)';

const constructCFModelTableNameComponent_mock = constructCFModelTableNameComponent as jest.MockedFunction<
Expand Down Expand Up @@ -103,3 +128,126 @@ test('env resources for CFN for auth and storage for api', async () => {
];
expect(await generateEnvVariablesForCfn(contextStub, resources, {})).toMatchSnapshot();
});

describe('askExecRolePermissionsQuestions', () => {
beforeEach(() => {
const stateManagerMock = stateManager as jest.Mocked<typeof stateManager>;
stateManagerMock.getMeta.mockReturnValue({
providers: {
awscloudformation: {},
},
function: {
lambda1: {
service: 'Lambda',
providerPlugin: 'awscloudformation',
},
lambda2: {
service: 'Lambda',
providerPlugin: 'awscloudformation',
lastPushTimeStamp: '2021-07-12T00:41:17.966Z',
},
},
auth: {
authResourceName: {
service: 'Cognito',
serviceType: 'imported',
providerPlugin: 'awscloudformation',
},
},
storage: {
s3Bucket: {
service: 'S3',
serviceType: 'imported',
providerPlugin: 'awscloudformation',
},
},
});
});

it('returns permissions for function that be about to add right', async () => {
const inquirerMock = inquirer as jest.Mocked<typeof inquirer>;

inquirerMock.prompt.mockResolvedValueOnce({ categories: ['function'] });
inquirerMock.prompt.mockResolvedValueOnce({ resources: ['lambda2'] });
inquirerMock.prompt.mockResolvedValueOnce({ options: [CRUDOperation.READ] });

const resourceAttributes = [
{
attributes: ['Name'],
category: 'function',
resourceName: 'lambda2',
},
];
const permissionPolicies = [
{
Action: ['lambda:Get*', 'lambda:List*', 'lambda:Invoke*'],
Effect: 'Allow',
Resource: [
{
'Fn::Join': [
'',
['arn:aws:lambda:', { Ref: 'AWS::Region' }, ':', { Ref: 'AWS::AccountId' }, ':function:', { Ref: 'functionlambda2Name' }],
],
},
],
},
];
const contextStub = {
print: {
warning: jest.fn(),
info: jest.fn(),
},
usageData: {
emitError: jest.fn(),
},
amplify: {
invokePluginMethod: jest.fn().mockResolvedValueOnce({ permissionPolicies, resourceAttributes }),
},
};
const answers = await askExecRolePermissionsQuestions(contextStub as unknown as $TSContext, 'lambda3', undefined);
expect(answers).toMatchSnapshot();
});

it('returns permissions for exists function', async () => {
const inquirerMock = inquirer as jest.Mocked<typeof inquirer>;

inquirerMock.prompt.mockResolvedValueOnce({ categories: ['function'] });
inquirerMock.prompt.mockResolvedValueOnce({ options: [CRUDOperation.READ] });

const resourceAttributes = [
{
attributes: ['Name'],
category: 'function',
resourceName: 'lambda2',
},
];
const permissionPolicies = [
{
Action: ['lambda:Get*', 'lambda:List*', 'lambda:Invoke*'],
Effect: 'Allow',
Resource: [
{
'Fn::Join': [
'',
['arn:aws:lambda:', { Ref: 'AWS::Region' }, ':', { Ref: 'AWS::AccountId' }, ':function:', { Ref: 'functionlambda2Name' }],
],
},
],
},
];
const contextStub = {
print: {
warning: jest.fn(),
info: jest.fn(),
},
usageData: {
emitError: jest.fn(),
},
amplify: {
invokePluginMethod: jest.fn().mockResolvedValueOnce({ permissionPolicies, resourceAttributes }),
},
};
const answers = await askExecRolePermissionsQuestions(contextStub as unknown as $TSContext, 'lambda1', undefined);
expect(answers).toMatchSnapshot();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,14 @@ export const askExecRolePermissionsQuestions = async (
// A Lambda function cannot depend on itself
// Lambda layer dependencies are handled seperately, also apply the filter if the selected resource is within the function category
// but serviceName argument was no passed in
const selectedResource = _.get(amplifyMeta, [categoryName, resourceNameToUpdate]);

if (serviceName === ServiceName.LambdaFunction || selectedCategory === categoryName) {
const selectedResource = _.get(amplifyMeta, [categoryName, resourceNameToUpdate]);
// A new function resource does not exist in amplifyMeta yet
const isNewFunctionResource = !selectedResource;
resourcesList = resourcesList.filter(
resourceName =>
resourceName !== resourceNameToUpdate && amplifyMeta[selectedCategory][resourceName].service === selectedResource.service,
resourceName !== resourceNameToUpdate &&
(isNewFunctionResource || amplifyMeta[selectedCategory][resourceName].service === selectedResource.service),
);
} else {
resourcesList = resourcesList.filter(
Expand Down

0 comments on commit 7af3b0d

Please sign in to comment.