Repository: cloud-custodian/cloud-custodian

Issue:
The s3 action "remove-statements" errors out when it encounters a bucket policy statement without a sid
**Describe the bug**
s3.remove-statements fails when a sid-less bucket policy statement is encountered

You can see the key error in the traceback. Bucket policy statements do not require Sids and S3 omits the key from describeBucketPolicy response when it does not exist.

**To Reproduce**
Attempt to use remove-statements to remove a statement from a bucket with a sid-less statement (one example of which is the "aws-sam-cli-managed-default-samclisourcebucket-..." buckets created  by AWS SAM CLI.)

**Expected behavior**
I expected the statement which does not contain a SID to be iterated over as non-matching.

**Background (please complete the following information):**
 - OS: AWS Lambda
 - Python Version:  Python 3.8
 - Custodian Version:  0.9.8
 - Tool Version: n/a
 - Cloud Provider: AWS
 - Policy: [please exclude any account/sensitive information]
```json
        {
          "statement_ids": [
            "denyAccessToBucket"
          ],
          "type": "remove-statements"
        }
```
 - Traceback: [if applicable, please exclude sensitive/account information]
 [ERROR] KeyError: 'Sid'
Traceback (most recent call last):
  File "/var/task/custodian_policy.py", line 4, in run
    return handler.dispatch_event(event, context)
  File "/var/task/c7n/handler.py", line 165, in dispatch_event
    p.push(event, context)
  File "/var/task/c7n/policy.py", line 1140, in push
    return mode.run(event, lambda_ctx)
  File "/var/task/c7n/policy.py", line 853, in run
    resources = super(ConfigRuleMode, self).run(event, lambda_context)
  File "/var/task/c7n/policy.py", line 453, in run
    return self.run_resource_set(event, resources)
  File "/var/task/c7n/policy.py", line 483, in run_resource_set
    results = action.process(resources)
  File "/var/task/c7n/resources/s3.py", line 1272, in process
    results += filter(None, [f.result()])
  File "/var/lang/lib/python3.8/concurrent/futures/_base.py", line 432, in result
    return self.__get_result()
  File "/var/lang/lib/python3.8/concurrent/futures/_base.py", line 388, in __get_result
    raise self._exception
  File "/var/lang/lib/python3.8/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/var/task/c7n/resources/s3.py", line 1282, in process_bucket
    statements, found = self.process_policy(
  File "/var/task/c7n/actions/policy.py", line 21, in process_policy
    return remove_statements(
  File "/var/task/c7n/actions/policy.py", line 37, in remove_statements
    elif s['Sid'] in match_ids:
 - `custodian version --debug` output: n/a

**Additional context**
Add any other context about the problem here.



Discussion:

Resolving patch:
diff --git a/c7n/actions/policy.py b/c7n/actions/policy.py
--- a/c7n/actions/policy.py
+++ b/c7n/actions/policy.py
@@ -31,7 +31,7 @@ def remove_statements(match_ids, statements, matched=()):
         elif match_ids == 'matched':
             if s in matched:
                 s_found = True
-        elif s['Sid'] in match_ids:
+        elif 'Sid' in s and s['Sid'] in match_ids:
             s_found = True
         if s_found:
             found.append(s)


Test patch: