AWS-SNS-Listener
Amazon Simple Notification Service (SNS) is a managed service that provides message delivery from publishers to subscribers.
Messaging and Conferencing · AWS-SNS-Listener
Details
| ID | AWS-SNS-Listener |
|---|---|
| Provider | Amazon |
| Category | Messaging and Conferencing |
| From Version | 6.10.0 |
| Docker Image | demisto/fastapi:0.125.0.10158186 |
| Supported Modules | Agentix XSIAM |
README
Amazon Simple Notification Service (SNS) is a managed service that provides message delivery from publishers to subscribers.
This integration was integrated and tested with version January 2024 of AWS-SNS-Listener.
Configure AWS-SNS-Listener in Cortex
| Parameter | Description | Required |
|---|---|---|
| Long running instance | Integration is long running by default | |
| Listen Port | Runs the service on this port from within Cortex XSOAR. Requires a unique port for each long-running integration instance. Do not use the same port for multiple instances. Note: If you click the test button more than once, a failure may occur mistakenly indicating that the port is already in use. | False |
| Username | Uses basic authentication for accessing the list. If empty, no authentication is enforced. (For Cortex XSOAR 8 and Cortex XSIAM) Optional for engines, otherwise mandatory. | False |
| Password | False | |
| Endpoint | Set the endpoint of your listener. example: /snsv2 | False |
| Certificate (Required for HTTPS) | (For Cortex XSOAR 6.x) For use with HTTPS - the certificate that the service should use. (For Cortex XSOAR 8 and Cortex XSIAM) Custom certificates are not supported. | False |
| Private Key (Required for HTTPS) | (For Cortex XSOAR 6.x) For use with HTTPS - the private key that the service should use. (For Cortex XSOAR 8 and Cortex XSIAM) When using an engine, configure a private API key. Not supported on the Cortex XSOAR or Cortex XSIAM server. | False |
| Store sample events for mapping | Because this is a push-based integration, it cannot fetch sample events in the mapping wizard. After you finish mapping, it is recommended to turn off the sample events storage to reduce performance overhead. | False |
| Use system proxy settings | False |
Commands
You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.
Configuration parameters
longRunning— Long running instancecredentials— Usernameendpoint— Endpointcertificate— Certificate (Required for HTTPS)key— Private Key (Required for HTTPS)store_samples— Store sample events for mappingproxy— Use system proxy settingslongRunningPort— Listen Port (required)
Commands (0)
This integration defines no commands.
from unittest.mock import MagicMock, patch import pytest import requests from AWSSNSListener import SNSCertificateManager, handle_notification, is_valid_integration_credentials from CommonServerPython import DemistoException VALID_PAYLOAD = { "Type": "Notification", "MessageId": "uuid", "TopicArn": "topicarn", "Subject": "NotificationSubject", "Message": "NotificationMessage", "Timestamp": "2024-02-13T18:03:27.239Z", "SignatureVersion": "1", "Signature": b"sign", "SigningCertURL": "https://sns.example.amazonaws.com", } @pytest.fixture def mock_params(mocker): return mocker.patch("AWSSNSListener.PARAMS", new={"credentials": {"identifier": "foo", "password": "bar"}}, autospec=False) def test_handle_notification_valid(): """ Given a valid SNS notification message When handle_notification is called with the message and raw json Then should parse to a valid incident """ raw_json = {} expected_notification = { "name": "NotificationSubject", "labels": [], "rawJSON": raw_json, "occurred": "2024-02-13T18:03:27.239Z", "details": "ExternalID:uuid TopicArn:topicarn Message:NotificationMessage", "type": "AWS-SNS Notification", } actual_incident = handle_notification(VALID_PAYLOAD, raw_json) assert actual_incident == expected_notification @patch("AWSSNSListener.client") @patch("AWSSNSListener.X509") @patch("M2Crypto.EVP.PKey") def test_is_valid_sns_message(mock_client, mock_x509, mock_PKey): sNSCertificateManager = SNSCertificateManager() mock_resp = requests.models.Response() mock_resp.status_code = 200 response_content = """-----BEGIN VALID CERTIFICATE----- -----END CERTIFICATE-----""" mock_resp._content = str.encode(response_content) mock_client.get.return_value = mock_resp mock_PKey.verify_final.return_value = 1 mock_x509.get_pubkey.return_value = mock_PKey mock_x509.load_cert_string.return_value = mock_x509 mock_x509.get_subject.return_value = MagicMock(CN="sns.amazonaws.com") is_valid = sNSCertificateManager.is_valid_sns_message(VALID_PAYLOAD) assert is_valid @patch("AWSSNSListener.client") @patch("AWSSNSListener.X509") @patch("M2Crypto.EVP.PKey") def test_not_valid_sns_message(mock_client, mock_x509, mock_PKey, capfd): sNSCertificateManager = SNSCertificateManager() mock_resp = requests.models.Response() mock_resp.status_code = 200 response_content = """-----BEGIN INVALID CERTIFICATE----- -----END CERTIFICATE-----""" mock_resp._content = str.encode(response_content) mock_client.get.return_value = mock_resp mock_PKey.verify_final.return_value = 2 mock_x509.get_pubkey.return_value = mock_PKey mock_x509.load_cert_string.return_value = mock_x509 with capfd.disabled(): is_valid = sNSCertificateManager.is_valid_sns_message(VALID_PAYLOAD) assert is_valid is False @patch("fastapi.security.http.HTTPBasicCredentials") def test_valid_credentials(mock_httpBasicCredentials, mock_params): """ Given valid credentials, request headers and token When is_valid_integration_credentials is called Then it should return True, header_name """ mock_httpBasicCredentials.username = "foo" mock_httpBasicCredentials.password = "bar" request_headers = {} token = "sometoken" result, header_name = is_valid_integration_credentials(mock_httpBasicCredentials, request_headers, token) assert result is True assert header_name is None @patch("fastapi.security.http.HTTPBasicCredentials") def test_invalid_credentials(mock_httpBasicCredentials, mock_params): """ Given invalid credentials, request headers and token When is_valid_integration_credentials is called Then it should return True, header_name """ mock_httpBasicCredentials.username = "foot" mock_httpBasicCredentials.password = "bark" request_headers = {} token = "sometoken" result, header_name = is_valid_integration_credentials(mock_httpBasicCredentials, request_headers, token) assert result is False class TestValidateSnsUrl: """Tests for URL format validation in _validate_sns_url.""" def test_valid_aws_sns_url_accepted(self): """Test that a valid AWS SNS URL passes validation.""" from AWSSNSListener import _validate_sns_url _validate_sns_url("https://sns.us-east-1.amazonaws.com/cert.pem", "SigningCertURL") def test_valid_aws_china_url_accepted(self): """Test that a valid AWS China region URL passes validation.""" from AWSSNSListener import _validate_sns_url _validate_sns_url("https://sns.cn-north-1.amazonaws.com.cn/cert.pem", "SigningCertURL") def test_non_https_url_rejected(self): """Test that a non-HTTPS URL is rejected.""" from AWSSNSListener import _validate_sns_url with pytest.raises(DemistoException, match="must use HTTPS"): _validate_sns_url("http://sns.us-east-1.amazonaws.com/cert.pem", "SigningCertURL") def test_non_aws_host_rejected(self): """Test that a non-AWS host is rejected.""" from AWSSNSListener import _validate_sns_url with pytest.raises(DemistoException, match="not an AWS SNS endpoint"): _validate_sns_url("https://attacker.example.com/cert.pem", "SigningCertURL") def test_aws_like_subdomain_rejected(self): """Test that a URL with an AWS-like subdomain on a different host is rejected.""" from AWSSNSListener import _validate_sns_url with pytest.raises(DemistoException, match="not an AWS SNS endpoint"): _validate_sns_url("https://sns.us-east-1.amazonaws.com.evil.com/cert.pem", "SigningCertURL")