{
  "Comment": "Step Function to apply IOC blocks",
  "StartAt": "NotifyAcknowledgement",
  "States": {
    "NotifyAcknowledgement": {
      "Type": "Task",
      "Resource": "arn:aws:states:::sns:publish",
      "Parameters": {
        "TopicArn": "${sns_gsirt_notification_topic_arn}",
        "Subject.$": "States.Format('IOC update has been acknowledged {}', $$.State.EnteredTime)",
        "Message.$": "States.Format('Execution Id: {}, started at {}', $$.Execution.Id, $$.State.EnteredTime)"
      },
      "Catch": [
        {
          "ErrorEquals": [
            "States.ALL"
          ],
          "Next": "InvokeSanitizeLambda"
        }
      ],
      "Next": "InvokeSanitizeLambda"
    },
    "InvokeSanitizeLambda": {
      "Type": "Task",
      "Resource": "arn:aws:states:::lambda:invoke",
      "Parameters": {
        "Payload.$": "$",
        "FunctionName": "${ioc_sanitize_arn}"
      },
      "Retry": [
        {
          "ErrorEquals": ["Lambda.AWSLambdaException"],
          "IntervalSeconds": 30,
          "MaxAttempts": 2,
          "BackoffRate": 2.0
        }
      ],
      "Catch": [
        {
          "ErrorEquals": ["States.ALL"],
          "ResultPath": "$.error",
          "Next": "NotifyFail"
        }
      ],
      "Next": "InvokeFargateRedeployLambda"
    },
    "InvokeFargateRedeployLambda": {
      "Type": "Task",
      "Resource": "arn:aws:states:::lambda:invoke",
      "Parameters": {
        "Payload.$": "$",
        "FunctionName": "${ioc_fargate_redeploy_arn}"
      },
      "Retry": [
        {
          "ErrorEquals": ["Lambda.AWSLambdaException"],
          "IntervalSeconds": 30,
          "MaxAttempts": 2,
          "BackoffRate": 2.0
        }
      ],
      "Catch": [
        {
          "ErrorEquals": ["States.ALL"],
          "ResultPath": "$.error",
          "Next": "NotifyFail"
        }
      ],
      "Next": "IpBlocksOrDomainBlocks"
    },
    "IpBlocksOrDomainBlocks": {
      "Type": "Choice",
      "Default": "FormatChoiceError",
      "Choices": [
        {
          "Variable": "$$.Execution.Input.detail.object.key",
          "IsPresent": false,
          "Next": "FormatChoiceError"
        },
        {
          "Variable": "$$.Execution.Input.detail.object.key",
          "StringEquals": "pde/ioc-block-ips.txt",
          "Next": "PrepareWafList"
        },
        {
          "Variable": "$$.Execution.Input.detail.object.key",
          "StringEquals": "pde/ioc-block-domain.txt",
          "Next": "InvokeUpdateDNSFirewallLambda"
        }
      ]
    },
    "FormatChoiceError": {
      "Type": "Pass",
      "Result": "Unknown source block list file.",
      "ResultPath": "$.error",
      "Next": "NotifyFail"
    },
    "InvokeUpdateDNSFirewallLambda": {
      "Type": "Task",
      "Resource": "arn:aws:states:::lambda:invoke",
      "Parameters": {
        "Payload.$": "$",
        "FunctionName": "${ioc_update_dns_firewall_arn}"
      },
      "Retry": [
        {
          "ErrorEquals": ["Lambda.AWSLambdaException"],
          "IntervalSeconds": 30,
          "MaxAttempts": 2,
          "BackoffRate": 2.0
        }
      ],
      "Catch": [
        {
          "ErrorEquals": ["States.ALL"],
          "ResultPath": "$.error",
          "Next": "NotifyFail"
        }
      ],
      "Next": "NotifySuccess"
    },
    "PrepareWafList": {
      "Type": "Pass",
      "Result": ${update_waf_ipset_input},
      "ResultPath": "$.ip_sets",
      "Next": "IterateUpdateWafIPSetsLambda"
    },
    "IterateUpdateWafIPSetsLambda": {
      "Type": "Map",
      "InputPath": "$.ip_sets",
      "ItemsPath": "$",
      "ResultSelector": {
        "Failures.$": "$[?(@.result == 'FAILED')]",
        "Successes.$": "$[?(@.result == 'SUCCESS')]"
      },
      "ResultPath": "$.processed_ip_sets",
      "OutputPath": "$.processed_ip_sets",
      "ItemProcessor": {
        "ProcessorConfig": {
          "Mode": "INLINE"
        },
        "StartAt": "InvokeUpdateWafIPSetsLambda",
        "States": {
          "InvokeUpdateWafIPSetsLambda": {
            "Type": "Task",
            "Resource": "arn:aws:states:::lambda:invoke",
            "OutputPath": "$.Payload",
            "Parameters": {
              "Payload.$": "$",
              "FunctionName": "${ioc_update_waf_ipsets_arn}"
            },
            "Retry": [
              {
                "ErrorEquals": ["Lambda.AWSLambdaException"],
                "IntervalSeconds": 30,
                "MaxAttempts": 2,
                "BackoffRate": 2.0
              }
            ],
            "Catch": [
              {
                "ErrorEquals": [
                  "States.ALL"
                ],
                "ResultPath": "$.error",
                "Next": "MarkAsFailed"
              }
            ],
            "End": true
          },
          "MarkAsFailed": {
            "Type": "Pass",
            "Result": "FAILED",
            "ResultPath": "$.result",
            "End": true
          }
        }
      },
      "Next": "TestIpsetFailures"
    },
    "TestIpsetFailures": {
      "Type": "Choice",
      "Default": "NotifySuccess",
      "Choices": [
        {
          "Variable": "$.Failures[0]",
          "IsPresent": true,
          "Next": "FormatMapError"
        }
      ]
    },
    "FormatMapError": {
      "Type": "Pass",
      "ResultPath": "$.error",
      "OutputPath": "$.Failures[0]",
      "Next": "NotifyFail"
    },
    "NotifySuccess": {
      "Type": "Parallel",
      "Branches": [
        {
          "StartAt": "NotifySuccessDevOps",
          "States": {
            "NotifySuccessDevOps": {
              "Type": "Task",
              "Resource": "arn:aws:states:::sns:publish",
              "Parameters": {
                "TopicArn": "${sns_notification_topic_arn}",
                "Subject.$": "States.Format('⛲ 🥳 IOC update has been completed for {}', $$.Execution.Input.detail.object.key)",
                "Message.$": "States.Format('Execution Id: {}, incoming block list file: s3://{}/{}', $$.Execution.Id, $$.Execution.Input.detail.bucket.name, $$.Execution.Input.detail.object.key )"
              },
              "End": true
            }
          }
        },
        {
          "StartAt": "NotifySuccessGSIRT",
          "States": {
            "NotifySuccessGSIRT": {
              "Type": "Task",
              "Resource": "arn:aws:states:::sns:publish",
              "Parameters": {
                "TopicArn": "${sns_gsirt_notification_topic_arn}",
                "Subject.$": "States.Format('IOC update has been completed {}', $$.State.EnteredTime)",
                "Message.$": "States.Format('Execution Id: {}, incoming block list file: s3://{}/{}, completed at {}', $$.Execution.Id, $$.Execution.Input.detail.bucket.name, $$.Execution.Input.detail.object.key, $$.State.EnteredTime)"
              },
              "End": true
            }
          }
        }
      ],
      "Catch": [{
            "ErrorEquals": ["States.ALL"],
            "Next": "SuccessState"
      }],
      "Next": "SuccessState"
    },
    "NotifyFail": {
        "Type": "Task",
        "Resource": "arn:aws:states:::sns:publish",
        "Parameters": {
            "TopicArn": "${sns_notification_topic_arn}",
            "Subject": "⛲ 😵 ❌ 😵 IOC update has FAILED",
            "Message.$": "States.Format('Execution Id: {}, \n\nError:{}', $$.Execution.Id, States.JsonToString($.error) )"
        },
        "Catch": [{
            "ErrorEquals": ["States.ALL"],
            "Next": "FailState"
        }],
        "Next": "FailState"
    },
    "FailState": {
      "Type": "Fail"
    },
    "SuccessState": {
      "Type": "Succeed"
    }
  }
}
