diff --git a/package/lib/compileFunctions.js b/package/lib/compileFunctions.js index b318d47..d24afbf 100644 --- a/package/lib/compileFunctions.js +++ b/package/lib/compileFunctions.js @@ -24,7 +24,6 @@ module.exports = { validateHandlerProperty(funcObject, functionName); validateEventsProperty(funcObject, functionName); validateVpcConnectorProperty(funcObject, functionName); - validateIamProperty(funcObject, functionName); const funcTemplate = getFunctionTemplate( funcObject, @@ -52,11 +51,6 @@ module.exports = { _.get(this, 'serverless.service.provider.environment'), funcObject.environment // eslint-disable-line comma-dangle ); - funcTemplate.accessControl.gcpIamPolicy.bindings = _.unionBy( - _.get(funcObject, 'iam.bindings'), - _.get(this, 'serverless.service.provider.iam.bindings'), - 'role' - ); if (!funcTemplate.properties.serviceAccountEmail) { delete funcTemplate.properties.serviceAccountEmail; @@ -89,14 +83,6 @@ module.exports = { funcTemplate.properties.httpsTrigger = {}; funcTemplate.properties.httpsTrigger.url = url; - - if (funcObject.allowUnauthenticated) { - funcTemplate.accessControl.gcpIamPolicy.bindings = _.unionBy( - [{ role: 'roles/cloudfunctions.invoker', members: ['allUsers'] }], - funcTemplate.accessControl.gcpIamPolicy.bindings, - 'role' - ); - } } if (eventType === 'event') { const type = funcObject.events[0].event.eventType; @@ -109,10 +95,6 @@ module.exports = { funcTemplate.properties.eventTrigger.resource = resource; } - if (!funcTemplate.accessControl.gcpIamPolicy.bindings.length) { - delete funcTemplate.accessControl; - } - this.serverless.service.provider.compiledConfigurationTemplate.resources.push(funcTemplate); }); @@ -175,29 +157,6 @@ const validateVpcConnectorProperty = (funcObject, functionName) => { } }; -const validateIamProperty = (funcObject, functionName) => { - if (_.get(funcObject, 'iam.bindings') && funcObject.iam.bindings.length > 0) { - funcObject.iam.bindings.forEach((binding) => { - if (!binding.role) { - const errorMessage = [ - `The function "${functionName}" has no role specified for an IAM binding.`, - ' Each binding requires a role. For details on supported roles, see the documentation', - ' at: https://cloud.google.com/iam/docs/understanding-roles', - ].join(''); - throw new Error(errorMessage); - } - if (!Array.isArray(binding.members) || !binding.members.length) { - const errorMessage = [ - `The function "${functionName}" has no members specified for an IAM binding.`, - ' Each binding requires at least one member to be assigned. See the IAM documentation', - ' for details on configuring members: https://cloud.google.com/iam/docs/overview', - ].join(''); - throw new Error(errorMessage); - } - }); - } -}; - const getFunctionTemplate = (funcObject, projectName, region, sourceArchiveUrl) => { //eslint-disable-line return { @@ -212,10 +171,5 @@ const getFunctionTemplate = (funcObject, projectName, region, sourceArchiveUrl) function: funcObject.name, sourceArchiveUrl, }, - accessControl: { - gcpIamPolicy: { - bindings: [], - }, - }, }; }; diff --git a/package/lib/compileFunctions.test.js b/package/lib/compileFunctions.test.js index a4c764d..cfdc6f4 100644 --- a/package/lib/compileFunctions.test.js +++ b/package/lib/compileFunctions.test.js @@ -766,460 +766,5 @@ describe('CompileFunctions', () => { ).toEqual(compiledResources); }); }); - - it('should throw an error if an IAM policy binding has no role', () => { - googlePackage.serverless.service.functions = { - func1: { - handler: 'func1', - events: [{ http: 'foo' }], - iam: { - bindings: [ - { - members: ['foobar'], - }, - ], - }, - }, - }; - - expect(() => googlePackage.compileFunctions()).toThrow(Error); - }); - - it('should throw an error if an IAM policy binding has no members defined', () => { - googlePackage.serverless.service.functions = { - func1: { - handler: 'func1', - events: [{ http: 'foo' }], - iam: { - bindings: [ - { - role: 'foobar', - }, - ], - }, - }, - }; - - expect(() => googlePackage.compileFunctions()).toThrow(Error); - }); - - it('should throw an error if an IAM policy binding has 0 members', () => { - googlePackage.serverless.service.functions = { - func1: { - handler: 'func1', - events: [{ http: 'foo' }], - iam: { - bindings: [ - { - role: 'foobar', - members: [], - }, - ], - }, - }, - }; - - expect(() => googlePackage.compileFunctions()).toThrow(Error); - }); - - it('should add the cloudfunctions.invoker role for allUsers when allowUnauthenticated is set for "http" event', () => { - googlePackage.serverless.service.functions = { - func1: { - handler: 'func1', - events: [{ http: 'foo' }], - allowUnauthenticated: true, - }, - }; - - const compiledResources = [ - { - type: 'gcp-types/cloudfunctions-v1:projects.locations.functions', - name: 'my-service-dev-func1', - properties: { - parent: 'projects/myProject/locations/us-central1', - runtime: 'nodejs8', - function: 'my-service-dev-func1', - entryPoint: 'func1', - availableMemoryMb: 256, - timeout: '60s', - sourceArchiveUrl: 'gs://sls-my-service-dev-12345678/some-path/artifact.zip', - httpsTrigger: { - url: 'foo', - }, - labels: {}, - }, - accessControl: { - gcpIamPolicy: { - bindings: [ - { - role: 'roles/cloudfunctions.invoker', - members: ['allUsers'], - }, - ], - }, - }, - }, - ]; - - return googlePackage.compileFunctions().then(() => { - expect(consoleLogStub.calledOnce).toEqual(true); - expect( - googlePackage.serverless.service.provider.compiledConfigurationTemplate.resources - ).toEqual(compiledResources); - }); - }); - - it('should not add the cloudfunctions.invoker role for allUsers when allowUnauthenticated is set for "event" event', () => { - googlePackage.serverless.service.functions = { - func1: { - handler: 'func1', - events: [ - { - event: { - eventType: 'foo', - resource: 'some-resource', - }, - }, - ], - allowUnauthenticated: true, - }, - }; - - const compiledResources = [ - { - type: 'gcp-types/cloudfunctions-v1:projects.locations.functions', - name: 'my-service-dev-func1', - properties: { - parent: 'projects/myProject/locations/us-central1', - runtime: 'nodejs8', - function: 'my-service-dev-func1', - entryPoint: 'func1', - availableMemoryMb: 256, - timeout: '60s', - sourceArchiveUrl: 'gs://sls-my-service-dev-12345678/some-path/artifact.zip', - eventTrigger: { - eventType: 'foo', - resource: 'some-resource', - }, - labels: {}, - }, - }, - ]; - - return googlePackage.compileFunctions().then(() => { - expect(consoleLogStub.calledOnce).toEqual(true); - expect( - googlePackage.serverless.service.provider.compiledConfigurationTemplate.resources - ).toEqual(compiledResources); - }); - }); - - it('should add the custom IAM policy bindings based on function configuration', () => { - googlePackage.serverless.service.functions = { - func1: { - handler: 'func1', - events: [{ http: 'foo' }], - iam: { - bindings: [ - { - role: 'roles/foobar', - members: ['some-user'], - }, - ], - }, - }, - }; - - const compiledResources = [ - { - type: 'gcp-types/cloudfunctions-v1:projects.locations.functions', - name: 'my-service-dev-func1', - properties: { - parent: 'projects/myProject/locations/us-central1', - runtime: 'nodejs8', - function: 'my-service-dev-func1', - entryPoint: 'func1', - availableMemoryMb: 256, - timeout: '60s', - sourceArchiveUrl: 'gs://sls-my-service-dev-12345678/some-path/artifact.zip', - httpsTrigger: { - url: 'foo', - }, - labels: {}, - }, - accessControl: { - gcpIamPolicy: { - bindings: [ - { - role: 'roles/foobar', - members: ['some-user'], - }, - ], - }, - }, - }, - ]; - - return googlePackage.compileFunctions().then(() => { - expect(consoleLogStub.calledOnce).toEqual(true); - expect( - googlePackage.serverless.service.provider.compiledConfigurationTemplate.resources - ).toEqual(compiledResources); - }); - }); - - it('should add the custom IAM policy bindings based on the provider configuration', () => { - googlePackage.serverless.service.functions = { - func1: { - handler: 'func1', - events: [{ http: 'foo' }], - }, - }; - googlePackage.serverless.service.provider.iam = { - bindings: [ - { - role: 'roles/foobar', - members: ['some-user'], - }, - ], - }; - - const compiledResources = [ - { - type: 'gcp-types/cloudfunctions-v1:projects.locations.functions', - name: 'my-service-dev-func1', - properties: { - parent: 'projects/myProject/locations/us-central1', - runtime: 'nodejs8', - function: 'my-service-dev-func1', - entryPoint: 'func1', - availableMemoryMb: 256, - timeout: '60s', - sourceArchiveUrl: 'gs://sls-my-service-dev-12345678/some-path/artifact.zip', - httpsTrigger: { - url: 'foo', - }, - labels: {}, - }, - accessControl: { - gcpIamPolicy: { - bindings: [ - { - role: 'roles/foobar', - members: ['some-user'], - }, - ], - }, - }, - }, - ]; - - return googlePackage.compileFunctions().then(() => { - expect(consoleLogStub.calledOnce).toEqual(true); - expect( - googlePackage.serverless.service.provider.compiledConfigurationTemplate.resources - ).toEqual(compiledResources); - }); - }); - - it('should add the custom IAM policy bindings based on the merged provider and function configuration', () => { - googlePackage.serverless.service.functions = { - func1: { - handler: 'func1', - events: [{ http: 'foo' }], - iam: { - bindings: [ - { - role: 'role2', - members: ['user1'], - }, - { - role: 'role3', - members: ['user4', 'user2'], - }, - ], - }, - }, - }; - googlePackage.serverless.service.provider.iam = { - bindings: [ - { - role: 'role1', - members: ['user1'], - }, - { - role: 'role2', - members: ['user1', 'user2', 'user3'], - }, - ], - }; - - const compiledResources = [ - { - type: 'gcp-types/cloudfunctions-v1:projects.locations.functions', - name: 'my-service-dev-func1', - properties: { - parent: 'projects/myProject/locations/us-central1', - runtime: 'nodejs8', - function: 'my-service-dev-func1', - entryPoint: 'func1', - availableMemoryMb: 256, - timeout: '60s', - sourceArchiveUrl: 'gs://sls-my-service-dev-12345678/some-path/artifact.zip', - httpsTrigger: { - url: 'foo', - }, - labels: {}, - }, - accessControl: { - gcpIamPolicy: { - bindings: [ - { - role: 'role2', - members: ['user1'], - }, - { - role: 'role3', - members: ['user4', 'user2'], - }, - { - role: 'role1', - members: ['user1'], - }, - ], - }, - }, - }, - ]; - - return googlePackage.compileFunctions().then(() => { - expect(consoleLogStub.calledOnce).toEqual(true); - expect( - googlePackage.serverless.service.provider.compiledConfigurationTemplate.resources - ).toEqual(compiledResources); - }); - }); - - it('should merge the allowUnauthenticated binding with custom bindings', () => { - googlePackage.serverless.service.functions = { - func1: { - handler: 'func1', - events: [{ http: 'foo' }], - allowUnauthenticated: true, - iam: { - bindings: [ - { - role: 'role1', - members: ['user1'], - }, - ], - }, - }, - }; - - const compiledResources = [ - { - type: 'gcp-types/cloudfunctions-v1:projects.locations.functions', - name: 'my-service-dev-func1', - properties: { - parent: 'projects/myProject/locations/us-central1', - runtime: 'nodejs8', - function: 'my-service-dev-func1', - entryPoint: 'func1', - availableMemoryMb: 256, - timeout: '60s', - sourceArchiveUrl: 'gs://sls-my-service-dev-12345678/some-path/artifact.zip', - httpsTrigger: { - url: 'foo', - }, - labels: {}, - }, - accessControl: { - gcpIamPolicy: { - bindings: [ - { - role: 'roles/cloudfunctions.invoker', - members: ['allUsers'], - }, - { - role: 'role1', - members: ['user1'], - }, - ], - }, - }, - }, - ]; - - return googlePackage.compileFunctions().then(() => { - expect(consoleLogStub.calledOnce).toEqual(true); - expect( - googlePackage.serverless.service.provider.compiledConfigurationTemplate.resources - ).toEqual(compiledResources); - }); - }); - - it('should merge the allowUnauthenticated binding with custom bindings with same role', () => { - googlePackage.serverless.service.functions = { - func1: { - handler: 'func1', - events: [{ http: 'foo' }], - allowUnauthenticated: true, - iam: { - bindings: [ - { - role: 'role1', - members: ['user1'], - }, - { - role: 'roles/cloudfunctions.invoker', - members: ['user1', 'user2'], - }, - ], - }, - }, - }; - - const compiledResources = [ - { - type: 'gcp-types/cloudfunctions-v1:projects.locations.functions', - name: 'my-service-dev-func1', - properties: { - parent: 'projects/myProject/locations/us-central1', - runtime: 'nodejs8', - function: 'my-service-dev-func1', - entryPoint: 'func1', - availableMemoryMb: 256, - timeout: '60s', - sourceArchiveUrl: 'gs://sls-my-service-dev-12345678/some-path/artifact.zip', - httpsTrigger: { - url: 'foo', - }, - labels: {}, - }, - accessControl: { - gcpIamPolicy: { - bindings: [ - { - role: 'roles/cloudfunctions.invoker', - members: ['allUsers'], - }, - { - role: 'role1', - members: ['user1'], - }, - ], - }, - }, - }, - ]; - - return googlePackage.compileFunctions().then(() => { - expect(consoleLogStub.calledOnce).toEqual(true); - expect( - googlePackage.serverless.service.provider.compiledConfigurationTemplate.resources - ).toEqual(compiledResources); - }); - }); }); });