Repository: localstack/localstack

Issue:
bug: SNS publish batch should fail when publishing to invalid topic
### Is there an existing issue for this?

- [X] I have searched the existing issues

### Current Behavior

When publishing a batch of messages to SNS using publish-batch command the result is always success, regardless of the topic being present.

Example result:
```
{
    "Successful": [
        {
            "Id": "1",
            "MessageId": "539277ec-2053-4e30-bc97-2f7075687cbd"
        }
    ],
    "Failed": []
}
```

### Expected Behavior

Publishing a batch of messages to a non-existing topic should return an error, as done by real implementation.

Expected Result
```
An error occurred (NotFound) when calling the PublishBatch operation: Topic does not exist
```

### How are you starting LocalStack?

With a docker-compose file

### Steps To Reproduce

#### How are you starting localstack (e.g., `bin/localstack` command, arguments, or `docker-compose.yml`)

    docker compose up -d

Docker-compose file:
```
services:
  localstack:
    image: 256612512925.dkr.ecr.eu-central-1.amazonaws.com/localstack:1.0.1
    ports:
      - "4576:4566"
    environment:
      - SERVICES=sns,sqs
      - AWS_DEFAULT_REGION=eu-central-1
      - DATA_DIR=/tmp/localstack/data
      - DEBUG=1
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /docker/localstack/data:/tmp/localstack/data
      - ./docker/localstack/init:/docker-entrypoint-initaws.d
```

#### Client commands (e.g., AWS SDK code snippet, or sequence of "awslocal" commands)

    awslocal sns publish-batch --topic-arn "arn:aws:sns:eu-central-1:000000000000:invalid.fifo" --publish-batch-request-entries Id=1,Message=hi,MessageGroupId=1234


### Environment

```markdown
- OS: MacOS Monterey 12.5
- LocalStack: 1.0.1
```


### Anything else?

_No response_


Discussion:
Welcome to LocalStack! Thanks for reporting your first issue and our team will be working towards fixing the issue for you or reach out for more background information. We recommend joining our [Slack Community](https://localstack.cloud/contact/) for real-time help and drop a message to LocalStack Pro Support if you are a Pro user! If you are willing to contribute towards fixing this issue, please have a look at our [contributing guidelines](https://github.com/localstack/.github/blob/main/CONTRIBUTING.md) and our [developer guide](https://docs.localstack.cloud/developer-guide/).

Resolving patch:
diff --git a/localstack/services/sns/provider.py b/localstack/services/sns/provider.py
--- a/localstack/services/sns/provider.py
+++ b/localstack/services/sns/provider.py
@@ -472,6 +472,12 @@ def publish_batch(
                         "Invalid parameter: The topic should either have ContentBasedDeduplication enabled or MessageDeduplicationId provided explicitly",
                     )
 
+        sns_backend = SNSBackend.get()
+        if topic_arn not in sns_backend.sns_subscriptions:
+            raise NotFoundException(
+                "Topic does not exist",
+            )
+
         response = {"Successful": [], "Failed": []}
         for entry in publish_batch_request_entries:
             message_id = str(uuid.uuid4())


Test patch:
diff --git a/tests/integration/test_sns.py b/tests/integration/test_sns.py
--- a/tests/integration/test_sns.py
+++ b/tests/integration/test_sns.py
@@ -1281,6 +1281,29 @@ def get_messages():
         messages.sort(key=itemgetter("Body"))
         snapshot.match("messages", {"Messages": messages})
 
+    @pytest.mark.aws_validated
+    def test_publish_batch_messages_without_topic(
+        self,
+        sns_client,
+        sns_create_topic,
+        snapshot,
+    ):
+        topic_arn = sns_create_topic()["TopicArn"]
+        fake_topic_arn = topic_arn + "fake-topic"
+
+        with pytest.raises(ClientError) as e:
+            sns_client.publish_batch(
+                TopicArn=fake_topic_arn,
+                PublishBatchRequestEntries=[
+                    {
+                        "Id": "1",
+                        "Message": "Test Message with two attributes",
+                        "Subject": "Subject",
+                    }
+                ],
+            )
+        snapshot.match("publish-batch-no-topic", e.value.response)
+
     @pytest.mark.aws_validated
     @pytest.mark.skip_snapshot_verify(
         paths=[
@@ -1290,7 +1313,7 @@ def get_messages():
             "$.topic-attrs.Attributes.EffectiveDeliveryPolicy",
             "$.topic-attrs.Attributes.Policy.Statement..Action",  # SNS:Receive is added by moto but not returned in AWS
             "$..Messages..Attributes.SequenceNumber",
-            "$..Successful..SequenceNumber",  # sequence number are not added
+            "$..Successful..SequenceNumber",  # not added, need to be managed by SNS, different from SQS received
         ]
     )
     @pytest.mark.parametrize("content_based_deduplication", [True, False])
diff --git a/tests/integration/test_sns.snapshot.json b/tests/integration/test_sns.snapshot.json
--- a/tests/integration/test_sns.snapshot.json
+++ b/tests/integration/test_sns.snapshot.json
@@ -2015,5 +2015,21 @@
         }
       }
     }
+  },
+  "tests/integration/test_sns.py::TestSNSProvider::test_publish_batch_messages_without_topic": {
+    "recorded-date": "01-09-2022, 20:49:54",
+    "recorded-content": {
+      "publish-batch-no-topic": {
+        "Error": {
+          "Code": "NotFound",
+          "Message": "Topic does not exist",
+          "Type": "Sender"
+        },
+        "ResponseMetadata": {
+          "HTTPHeaders": {},
+          "HTTPStatusCode": 404
+        }
+      }
+    }
   }
 }