Repository: serverless/serverless (JavaScript)
Date: 2020-03-06 02:38:24+00:00
Task type: Bug Fix

Issue:
Please do not hard code ARN partition for websocket 
# Bug Report

## Description

I am using aws china, where I set iamRoleStatement as 
```
  iamRoleStatements:
    - Effect: Allow
      Action:
        - "execute-api:ManageConnections"
      Resource:
        - "arn:aws-cn:execute-api:*:*:**/@connections/*"
```
 however, serverless always add an extra policy as
```
{
  "Effect": "Allow",
  "Action": [
    "execute-api:ManageConnections"
  ],
  "Resource": [
    "arn:aws:execute-api:*:*:*/@connections/*"
  ]
}
```
when I do the deployment, it reports
`ServerlessError: Stack:arn:aws-cn:cloudformation:cn-northwest-1:xxxx is in ROLLBACK_COMPLETE state and can not be updated.`

as I can search in the repository, this line may the cause
https://github.com/serverless/serverless/blob/master/lib/plugins/aws/package/compile/events/websockets/lib/api.js#L42

- #12345

Please do not hard code ARN partition for websocket 
# Bug Report

## Description

I am using aws china, where I set iamRoleStatement as 
```
  iamRoleStatements:
    - Effect: Allow
      Action:
        - "execute-api:ManageConnections"
      Resource:
        - "arn:aws-cn:execute-api:*:*:**/@connections/*"
```
 however, serverless always add an extra policy as
```
{
  "Effect": "Allow",
  "Action": [
    "execute-api:ManageConnections"
  ],
  "Resource": [
    "arn:aws:execute-api:*:*:*/@connections/*"
  ]
}
```
when I do the deployment, it reports
`ServerlessError: Stack:arn:aws-cn:cloudformation:cn-northwest-1:xxxx is in ROLLBACK_COMPLETE state and can not be updated.`

as I can search in the repository, this line may the cause
https://github.com/serverless/serverless/blob/master/lib/plugins/aws/package/compile/events/websockets/lib/api.js#L42

- #12345



Issue discussion:
Furthermore, there are two `execute-api:ManageConnections` in `.serverless/cloudformation-template-update-stack.json`
```
"PolicyDocument": {
  "Version": "2012-10-17",
  "Statement": [
   ...  //log configuration
    {
      "Effect": "Allow",
      "Action": [
        "execute-api:ManageConnections"
      ],
      "Resource": [
        "arn:aws-cn:execute-api:*:*:**/@connections/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "execute-api:ManageConnections"
      ],
      "Resource": [
        "arn:aws:execute-api:*:*:*/@connections/*"
      ]
    }
  ]
}
```
@medikoo: This issue appears to be problematic for all non-default partitions (i.e., currently "aws-cn" and "aws-us-gov"). A number of possible solutions present themselves.

For example, the docs could be updated to indicate that users should specify the partition when using non-standard regions (e.g., they should declare `provider.partition` near `provider.region` in `serverless.yml`); alternatively, L42's context could be given access to a util function that maps regions to partitions, hiding the need to distinguish partitions from the user.

In either case, we could then interpolate; for example, in the former case:
```js
const partition = this.serverless.service.provider.partition || 'aws';
const websocketsPolicy = {
  Effect: 'Allow',
  Action: ['execute-api:ManageConnections'],
  Resource: [`arn:${partition}:execute-api:*:*:*/@connections/*`],
};
```

Potentially related issues:
- https://github.com/serverless/serverless/issues/4102
- https://github.com/serverless/serverless/pull/4219

References:
- https://docs.amazonaws.cn/en_us/general/latest/gr/aws-arns-and-namespaces.html
We're open for PR that fixes this issue
Furthermore, there are two `execute-api:ManageConnections` in `.serverless/cloudformation-template-update-stack.json`
```
"PolicyDocument": {
  "Version": "2012-10-17",
  "Statement": [
   ...  //log configuration
    {
      "Effect": "Allow",
      "Action": [
        "execute-api:ManageConnections"
      ],
      "Resource": [
        "arn:aws-cn:execute-api:*:*:**/@connections/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "execute-api:ManageConnections"
      ],
      "Resource": [
        "arn:aws:execute-api:*:*:*/@connections/*"
      ]
    }
  ]
}
```
@medikoo: This issue appears to be problematic for all non-default partitions (i.e., currently "aws-cn" and "aws-us-gov"). A number of possible solutions present themselves.

For example, the docs could be updated to indicate that users should specify the partition when using non-standard regions (e.g., they should declare `provider.partition` near `provider.region` in `serverless.yml`); alternatively, L42's context could be given access to a util function that maps regions to partitions, hiding the need to distinguish partitions from the user.

In either case, we could then interpolate; for example, in the former case:
```js
const partition = this.serverless.service.provider.partition || 'aws';
const websocketsPolicy = {
  Effect: 'Allow',
  Action: ['execute-api:ManageConnections'],
  Resource: [`arn:${partition}:execute-api:*:*:*/@connections/*`],
};
```

Potentially related issues:
- https://github.com/serverless/serverless/issues/4102
- https://github.com/serverless/serverless/pull/4219

References:
- https://docs.amazonaws.cn/en_us/general/latest/gr/aws-arns-and-namespaces.html
We're open for PR that fixes this issue

Solution patch:
diff --git a/lib/plugins/aws/package/compile/events/websockets/lib/api.js b/lib/plugins/aws/package/compile/events/websockets/lib/api.js
index 5ec6bb1e166..687236acc6b 100644
--- a/lib/plugins/aws/package/compile/events/websockets/lib/api.js
+++ b/lib/plugins/aws/package/compile/events/websockets/lib/api.js
@@ -39,7 +39,7 @@ module.exports = {
       const websocketsPolicy = {
         Effect: 'Allow',
         Action: ['execute-api:ManageConnections'],
-        Resource: ['arn:aws:execute-api:*:*:*/@connections/*'],
+        Resource: [{ 'Fn::Sub': 'arn:${AWS::Partition}:execute-api:*:*:*/@connections/*' }],
       };
 
       this.serverless.service.provider.compiledCloudFormationTemplate.Resources[


Test patch:
diff --git a/lib/plugins/aws/package/compile/events/websockets/lib/api.test.js b/lib/plugins/aws/package/compile/events/websockets/lib/api.test.js
index 86328168a31..c6a6749a839 100644
--- a/lib/plugins/aws/package/compile/events/websockets/lib/api.test.js
+++ b/lib/plugins/aws/package/compile/events/websockets/lib/api.test.js
@@ -78,7 +78,9 @@ describe('#compileApi()', () => {
                   {
                     Action: ['execute-api:ManageConnections'],
                     Effect: 'Allow',
-                    Resource: ['arn:aws:execute-api:*:*:*/@connections/*'],
+                    Resource: [
+                      { 'Fn::Sub': 'arn:${AWS::Partition}:execute-api:*:*:*/@connections/*' },
+                    ],
                   },
                 ],
               },