aws / chalice

Python Serverless Microframework for AWS
Apache License 2.0
10.67k stars 1.01k forks source link

DeleteConflict error with custom policy file #2006

Open cjmcmurtrie opened 1 year ago

cjmcmurtrie commented 1 year ago

With the same call to chalice deploy I am deploying a REST API and a lambda function. This is so that I can run the Lambda function asynchronously after responding to the request.

@app.route('/v1/lambdaTest')
def test_endpoint():
    _ = lambda_client.invoke(
        FunctionName='mvp-api-dev-testFunction',
        InvocationType='Event',
        Payload="{}"
    )

    return {'status_code': 200}

@app.lambda_function(name='testFunction')
def test_lambda_function(event, context):
    time.sleep(20)

The deployed API Lambda does not have permission automatically to invoke api-dev-testFunction. This can be fixed by updating the policy in the AWS console but it must be done on every deployment.

To avoid this, I created a policy file .chalice/policy-dev.json with the policy configuration, which is like this:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": "arn:*:logs:*:*:*"
        },
        {
            "Sid": "InvokePermission",
            "Effect": "Allow",
            "Action": [
                "lambda:InvokeFunction"
            ],
            "Resource": "*"
        }
    ]
}

The .chalice/config.json looks like this, with autogen_policy set to false, and pointing to the above policy file policy-dev.json:

{
  "version": "2.0",
  "app_name": "mvp-api",
  "stages": {
    "dev": {
      "lambda_memory_size": 3008,
      "api_gateway_stage": "api",
      "autogen_policy": false,
      "iam_policy_file": "policy-dev.json"
    }
  }
}

After chalice deploy, the API works as expected, but an error is reported in the console. Here is the stack trace:

(-----) user@system:~/projects/mvp-api$ chalice deploy
/home/-----/anaconda3/envs/mvp38/lib/python3.8/site-packages/_distutils_hack/__init__.py:30: UserWarning: Setuptools is replacing distutils.
  warnings.warn("Setuptools is replacing distutils.")
Creating deployment package.
Reusing existing deployment package.
Updating policy for IAM role: mvp-api-dev-testFunction
Updating lambda function: mvp-api-dev-testFunction
Updating policy for IAM role: mvp-api-dev-api_handler
Updating lambda function: mvp-api-dev
Updating rest API
Deleting IAM role: mvp-api-dev
Traceback (most recent call last):
  File "/home/-----/anaconda3/envs/mvp38/lib/python3.8/site-packages/chalice/deploy/deployer.py", line 376, in deploy
    return self._deploy(config, chalice_stage_name)
  File "/home/-----/anaconda3/envs/mvp38/lib/python3.8/site-packages/chalice/deploy/deployer.py", line 392, in _deploy
    self._executor.execute(plan)
  File "/home/-----/anaconda3/envs/mvp38/lib/python3.8/site-packages/chalice/deploy/executor.py", line 42, in execute
    getattr(self, '_do_%s' % instruction.__class__.__name__.lower(),
  File "/home/-----/anaconda3/envs/mvp38/lib/python3.8/site-packages/chalice/deploy/executor.py", line 55, in _do_apicall
    result = method(**final_kwargs)
  File "/home/-----/anaconda3/envs/mvp38/lib/python3.8/site-packages/chalice/awsclient.py", line 1062, in delete_role
    client.delete_role(RoleName=name)
  File "/home/-----/anaconda3/envs/mvp38/lib/python3.8/site-packages/botocore/client.py", line 508, in _api_call
    return self._make_api_call(operation_name, kwargs)
  File "/home/-----/anaconda3/envs/mvp38/lib/python3.8/site-packages/botocore/client.py", line 915, in _make_api_call
    raise error_class(parsed_response, operation_name)
botocore.errorfactory.DeleteConflictException: An error occurred (DeleteConflict) when calling the DeleteRole operation: Cannot delete entity, must detach all policies first.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/-----/anaconda3/envs/mvp38/lib/python3.8/site-packages/chalice/cli/__init__.py", line 636, in main
    return cli(obj={})
  File "/home/-----/anaconda3/envs/mvp38/lib/python3.8/site-packages/click/core.py", line 1130, in __call__
    return self.main(*args, **kwargs)
  File "/home/-----/anaconda3/envs/mvp38/lib/python3.8/site-packages/click/core.py", line 1055, in main
    rv = self.invoke(ctx)
  File "/home/-----/anaconda3/envs/mvp38/lib/python3.8/site-packages/click/core.py", line 1657, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/home/-----/anaconda3/envs/mvp38/lib/python3.8/site-packages/click/core.py", line 1404, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/home/-----/anaconda3/envs/mvp38/lib/python3.8/site-packages/click/core.py", line 760, in invoke
    return __callback(*args, **kwargs)
  File "/home/-----/anaconda3/envs/mvp38/lib/python3.8/site-packages/click/decorators.py", line 26, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/home/-----/anaconda3/envs/mvp38/lib/python3.8/site-packages/chalice/cli/__init__.py", line 189, in deploy
    deployed_values = d.deploy(config, chalice_stage_name=stage)
  File "/home/-----/anaconda3/envs/mvp38/lib/python3.8/site-packages/chalice/deploy/deployer.py", line 378, in deploy
    raise ChaliceDeploymentError(e)
chalice.deploy.deployer.ChaliceDeploymentError: ERROR - While deploying your chalice application, received the following error:

 An error occurred (DeleteConflict) when calling the DeleteRole operation: 
 Cannot delete entity, must detach all policies first.

Any ideas on the meaning of this error, and how to correct it?

Many thanks to you!

cjmcmurtrie commented 1 year ago

Think I got to the bottom of this. There were some policies attached to the role (which I had attached to it at some time in the past in the AWS console), and these were preventing deployer from deleting the role, to then construct the new one with the custom policy.

By removing the policies in the console I was able to deploy successfully.

Is this behaviour you expect and want to keep? Would you like to close this, or is any other info or discussion helpful to you?