packages feed

aws-sns-verify-0.0.0.3: tests/Amazon/SNS/Verify/ValidateSpec.hs

module Amazon.SNS.Verify.ValidateSpec
  ( spec
  ) where

import Amazon.SNS.Verify.TestPrelude

import Amazon.SNS.Verify.Payload
import Amazon.SNS.Verify.Validate
import Data.X509.Validation (SignatureFailure (..))

spec :: Spec
spec = around_ useCertServer $ do
  describe "validateSnsMessage" $ do
    it "successfully validates an SNS notification" $ do
      let message = "Some message"
      x <-
        validateSnsMessage
          $ SNSPayload
            { snsMessage = message
            , snsMessageId = "78d4d7a0-a3eb-5c4d-834f-8d5fa9813ab6"
            , snsTimestamp = "2022-05-18T14:52:26.952Z"
            , snsTopicArn = "arn:aws:sns:us-west-2:123456789012:MyTopic"
            , snsType = "Notification"
            , snsSignatureVersion = "1"
            , snsSignature =
                "Dg24trcOUiLjclt5JwyJS0JEOnEEbi6P30XS6KBxMCwzZ08a04UwjaFTW9Ae8xurhBS5YESz1fY28vTwvEmxh/20WmB3bWIDOMp9v5RI8XSZOvpMm+hdQJ43VqGhEDyAvRU6iCDLihDlZNc/sBCwl9X0H4kh/8vIElRif9gFBbYI94ZHGgqEV+Zc3gVKo9Udrl/MxNvMVadsO/+/oPVUeWibQr3xfGK95oc/ocuNAgi0MOxZmLVnibHu36KOTSvy2qSLonnRRFcbaauYZJ4js7oTq+1ujXNO72oPLaeG3pVJ2grqMc5z8tKQxFnSTE3es7wQarU/CLrbO8j0isbnWw=="
            , snsSigningCertURL = cert
            , snsTypePayload =
                Notification
                  $ SNSNotification
                    { snsSubject =
                        Just
                          "SynthesisTaskNotification { TaskId: 680a1f1b-f3ae-4474-aa8f-3b6dfe52e656, Status: COMPLETED }"
                    }
            }
      x `shouldBe` Right (SNSMessage message)

    it "fails to validate a currupt SNS notification" $ do
      let go =
            validateSnsMessage
              $ SNSPayload
                { snsMessage = "Some message"
                , snsMessageId = "corrupt"
                , snsTimestamp = "2022-05-18T14:52:26.952Z"
                , snsTopicArn = "arn:aws:sns:us-west-2:123456789012:MyTopic"
                , snsType = "Notification"
                , snsSignatureVersion = "1"
                , snsSignature =
                    "Dg24trcOUiLjclt5JwyJS0JEOnEEbi6P30XS6KBxMCwzZ08a04UwjaFTW9Ae8xurhBS5YESz1fY28vTwvEmxh/20WmB3bWIDOMp9v5RI8XSZOvpMm+hdQJ43VqGhEDyAvRU6iCDLihDlZNc/sBCwl9X0H4kh/8vIElRif9gFBbYI94ZHGgqEV+Zc3gVKo9Udrl/MxNvMVadsO/+/oPVUeWibQr3xfGK95oc/ocuNAgi0MOxZmLVnibHu36KOTSvy2qSLonnRRFcbaauYZJ4js7oTq+1ujXNO72oPLaeG3pVJ2grqMc5z8tKQxFnSTE3es7wQarU/CLrbO8j0isbnWw=="
                , snsSigningCertURL = cert
                , snsTypePayload =
                    Notification
                      $ SNSNotification
                        { snsSubject =
                            Just
                              "SynthesisTaskNotification { TaskId: 680a1f1b-f3ae-4474-aa8f-3b6dfe52e656, Status: COMPLETED }"
                        }
                }
      go `shouldReturn` Left (InvalidPayload SignatureInvalid)

    it "fails to validate a bad PEM" $ do
      let go =
            validateSnsMessage
              $ SNSPayload
                { snsMessage = "Some message"
                , snsMessageId = "corrupt"
                , snsTimestamp = "2022-05-18T14:52:26.952Z"
                , snsTopicArn = "arn:aws:sns:us-west-2:123456789012:MyTopic"
                , snsType = "Notification"
                , snsSignatureVersion = "1"
                , snsSignature =
                    "Dg24trcOUiLjclt5JwyJS0JEOnEEbi6P30XS6KBxMCwzZ08a04UwjaFTW9Ae8xurhBS5YESz1fY28vTwvEmxh/20WmB3bWIDOMp9v5RI8XSZOvpMm+hdQJ43VqGhEDyAvRU6iCDLihDlZNc/sBCwl9X0H4kh/8vIElRif9gFBbYI94ZHGgqEV+Zc3gVKo9Udrl/MxNvMVadsO/+/oPVUeWibQr3xfGK95oc/ocuNAgi0MOxZmLVnibHu36KOTSvy2qSLonnRRFcbaauYZJ4js7oTq+1ujXNO72oPLaeG3pVJ2grqMc5z8tKQxFnSTE3es7wQarU/CLrbO8j0isbnWw=="
                , snsSigningCertURL = "http://localhost:3000/404"
                , snsTypePayload =
                    Notification
                      $ SNSNotification
                        { snsSubject =
                            Just
                              "SynthesisTaskNotification { TaskId: 680a1f1b-f3ae-4474-aa8f-3b6dfe52e656, Status: COMPLETED }"
                        }
                }
      go `shouldReturn` Left (BadPem "Empty List")

    it "fails to validate an unexpected url" $ do
      let go =
            validateSnsMessage
              $ SNSPayload
                { snsMessage = "Some message"
                , snsMessageId = "corrupt"
                , snsTimestamp = "2022-05-18T14:52:26.952Z"
                , snsTopicArn = "arn:aws:sns:us-west-2:123456789012:MyTopic"
                , snsType = "Notification"
                , snsSignatureVersion = "1"
                , snsSignature =
                    "Dg24trcOUiLjclt5JwyJS0JEOnEEbi6P30XS6KBxMCwzZ08a04UwjaFTW9Ae8xurhBS5YESz1fY28vTwvEmxh/20WmB3bWIDOMp9v5RI8XSZOvpMm+hdQJ43VqGhEDyAvRU6iCDLihDlZNc/sBCwl9X0H4kh/8vIElRif9gFBbYI94ZHGgqEV+Zc3gVKo9Udrl/MxNvMVadsO/+/oPVUeWibQr3xfGK95oc/ocuNAgi0MOxZmLVnibHu36KOTSvy2qSLonnRRFcbaauYZJ4js7oTq+1ujXNO72oPLaeG3pVJ2grqMc5z8tKQxFnSTE3es7wQarU/CLrbO8j0isbnWw=="
                , snsSigningCertURL = "http://attacker.com/evil.pem"
                , snsTypePayload =
                    Notification
                      $ SNSNotification
                        { snsSubject =
                            Just
                              "SynthesisTaskNotification { TaskId: 680a1f1b-f3ae-4474-aa8f-3b6dfe52e656, Status: COMPLETED }"
                        }
                }
      go `shouldReturn` Left (BadUri "http://attacker.com/evil.pem")

    it "successfully validates an SNS subscription" $ do
      -- pendingWith "need valid subscription payload"
      let
        message =
          "You have chosen to subscribe to the topic arn:aws:sns:us-west-2:123456789012:MyTopic.\nTo confirm the subscription, visit the SubscribeURL included in this message."
        subscription =
          SNSSubscription
            { snsToken = "2336412f37..."
            , snsSubscribeURL =
                "https://sns.us-west-2.amazonaws.com/?Action=ConfirmSubscription&TopicArn=arn:aws:sns:us-west-2:123456789012:MyTopic&Token=2336412f37..."
            }
      x <-
        validateSnsMessage
          $ SNSPayload
            { snsMessage = message
            , snsMessageId = "165545c9-2a5c-472c-8df2-7ff2be2b3b1b"
            , snsTimestamp = "2012-04-26T20:45:04.751Z"
            , snsTopicArn = "arn:aws:sns:us-west-2:123456789012:MyTopic"
            , snsType = "SubscriptionConfirmation"
            , snsSignatureVersion = "1"
            , snsSignature =
                "Jec/VlsopbiA2fCckj/IwTPjDbSuFkl2hNKL898sQuZcMeKeOLthYs7YlF+xLi+Ip6rG/X08GZKtCqpoiSgKW8D9PI6eHVM2JQa76sFJO5ZdPylrDH+URwBf28gT+1l/VYk4p3VK8RZo+3Wkn87HXwxTq1YoN390o5ncT34zaBDtLx2cUA8+JOnYjItmYjVXDhrEBF6xad/vIY8V2o5xyQOfEWLm71/Tcs3radzNoSj2xlLQyJKPOzV661fG6Xz1vVKfDVC03+Q4Pn67SmU1wWRRT1nDwPPzQlcDAiAGRjB1U/C5iHfLQFF3dKo4azylkrM2ReTCMm9KMyIWqjq5eg=="
            , snsSigningCertURL = cert
            , snsTypePayload = SubscriptionConfirmation subscription
            }
      x `shouldBe` Right (SNSSubscribe subscription)

    it "successfully validates an SNS unsubscribe" $ do
      -- pendingWith "need valid subscription payload"
      let
        message =
          "You have chosen to subscribe to the topic arn:aws:sns:us-west-2:123456789012:MyTopic.\nTo confirm the subscription, visit the SubscribeURL included in this message."
        subscription =
          SNSSubscription
            { snsToken = "2336412f37..."
            , snsSubscribeURL =
                "https://sns.us-west-2.amazonaws.com/?Action=ConfirmSubscription&TopicArn=arn:aws:sns:us-west-2:123456789012:MyTopic&Token=2336412f37..."
            }
      x <-
        validateSnsMessage
          $ SNSPayload
            { snsMessage = message
            , snsMessageId = "165545c9-2a5c-472c-8df2-7ff2be2b3b1b"
            , snsTimestamp = "2012-04-26T20:45:04.751Z"
            , snsTopicArn = "arn:aws:sns:us-west-2:123456789012:MyTopic"
            , snsType = "UnsubscribeConfirmation"
            , snsSignatureVersion = "1"
            , snsSignature =
                "fKtmZTE6xvGhbcCTchFPLmuhdoXI7hxWrE9qe1RjeLDecMaZGmqsn4rOrFDsteqot4ItLuJqvV7RtImGXrMa/JNnZdP71lG6FdrKTiGqZNrnxZZYbIuZMAsSQM4E8VaRwbxLXuPQY9IYFP4y9GfsdpDYx0tpbXOxGz/JFVQjTFpHY55BmV6Ec73g0X/eLSEdKfHtWg/gVf6W27ewa40jXvaa78VmcVXbPXIKwzGgSSSe9t6xxVe0kLjKXaDyJTl3rbZJZJgBLInbychWNq1vGHGZQhtCyxjKRfKIWNWDbHdM/fUBGUhuv089CblWpq8g/21HiJ9n+S3VSn0hCXB5hg=="
            , snsSigningCertURL = cert
            , snsTypePayload = UnsubscribeConfirmation subscription
            }
      x `shouldBe` Right (SNSUnsubscribe subscription)

cert :: Text
cert = "http://localhost:3000"