# AWS - Step Functions Enum

{{#include ../../../banners/hacktricks-training.md}}

## Step Functions

AWS Step Functions est un service de flux de travail qui vous permet de coordonner et d'orchestrer plusieurs services AWS en flux de travail sans serveur. En utilisant AWS Step Functions, vous pouvez concevoir et exécuter des flux de travail qui connectent divers services AWS tels qu'AWS Lambda, Amazon S3, Amazon DynamoDB, et bien d'autres, dans une séquence d'étapes. Ce service d'orchestration fournit une interface de flux de travail visuelle et offre des capacités de **machine d'état**, vous permettant de définir chaque étape du flux de travail de manière déclarative en utilisant le **Amazon States Language** (ASL) basé sur JSON.

## Concepts clés

### Flux de travail Standard vs. Express

AWS Step Functions propose deux types de **flux de travail de machine d'état** : Standard et Express.

- **Flux de travail Standard** : Ce type de flux de travail par défaut est conçu pour des processus durables, audités et de longue durée. Il prend en charge l'**exécution exactement une fois**, garantissant que les tâches s'exécutent une seule fois, sauf si des réessais sont spécifiés. Il est idéal pour les flux de travail nécessitant un historique d'exécution détaillé et peut fonctionner jusqu'à un an.
- **Flux de travail Express** : Ce type est idéal pour des tâches de volume élevé et de courte durée, s'exécutant jusqu'à cinq minutes. Ils prennent en charge l'**exécution au moins une fois**, adaptés aux tâches idempotentes comme le traitement de données. Ces flux de travail sont optimisés pour le coût et la performance, facturant en fonction des exécutions, de la durée et de l'utilisation de la mémoire.

### États

Les états sont les unités essentielles des machines d'état. Ils définissent les étapes individuelles au sein d'un flux de travail, pouvant effectuer une variété de fonctions selon leur type :

- **Task :** Exécute un travail, souvent en utilisant un service AWS comme Lambda.
- **Choice :** Prend des décisions basées sur l'entrée.
- **Fail/Succeed :** Termine l'exécution avec un échec ou un succès.
- **Pass :** Transmet l'entrée à la sortie ou injecte des données.
- **Wait :** Retarde l'exécution pendant un temps défini.
- **Parallel :** Initie des branches parallèles.
- **Map :** Itère dynamiquement les étapes sur des éléments.

### Task

Un état **Task** représente une unité de travail unique exécutée par une machine d'état. Les tâches peuvent invoquer diverses ressources, y compris des activités, des fonctions Lambda, des services AWS ou des API tierces.

- **Activities** : Travailleurs personnalisés que vous gérez, adaptés aux processus de longue durée.
- Ressource : **`arn:aws:states:region:account:activity:name`**.
- **Lambda Functions** : Exécute des fonctions AWS Lambda.
- Ressource : **`arn:aws:lambda:region:account:function:function-name`**.
- **AWS Services** : S'intègre directement avec d'autres services AWS, comme DynamoDB ou S3.
- Ressource : **`arn:partition:states:region:account:servicename:APIname`**.
- **HTTP Task** : Appelle des API tierces.
- Champ de ressource : **`arn:aws:states:::http:invoke`**. Ensuite, vous devez fournir les détails de configuration de l'endpoint API, tels que l'URL de l'API, la méthode et les détails d'authentification.

L'exemple suivant montre une définition d'état Task qui invoque une fonction Lambda appelée HelloWorld :
```json
"HelloWorld": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"Parameters": {
"Payload.$": "$",
"FunctionName": "arn:aws:lambda:<region>:<account-id>:function:HelloWorld"
},
"End": true
}
```
### Choix

Un état de **Choix** ajoute une logique conditionnelle à un flux de travail, permettant des décisions basées sur des données d'entrée. Il évalue les conditions spécifiées et transitionne vers l'état correspondant en fonction des résultats.

- **Comparaison** : Chaque règle de choix inclut un opérateur de comparaison (par exemple, **`NumericEquals`**, **`StringEquals`**) qui compare une variable d'entrée à une valeur spécifiée ou à une autre variable.
- **Champ Suivant** : Les états de choix ne prennent pas en charge le champ **`End`**, au lieu de cela, ils définissent l'état **`Next`** vers lequel transiter si la comparaison est vraie.

Exemple d'état de **Choix** :
```json
{
"Variable": "$.timeStamp",
"TimestampEquals": "2000-01-01T00:00:00Z",
"Next": "TimeState"
}
```
### Échec/Réussite

Un état **`Fail`** arrête l'exécution d'une machine d'état et la marque comme un échec. Il est utilisé pour spécifier un nom d'erreur et une cause, fournissant des détails sur l'échec. Cet état est terminal, ce qui signifie qu'il met fin au flux d'exécution.

Un état **`Succeed`** arrête l'exécution avec succès. Il est généralement utilisé pour terminer le flux de travail lorsqu'il se termine avec succès. Cet état ne nécessite pas de champ **`Next`**.

{{#tabs }}
{{#tab name="Exemple d'échec" }}
```json
"FailState": {
"Type": "Fail",
"Error": "ErrorName",
"Cause": "Error details"
}
```
{{#endtab }}

{{#tab name="Exemple de réussite" }}
```json
"SuccessState": {
"Type": "Succeed"
}
```
{{#endtab }}
{{#endtabs }}

### Pass

Un état **Pass** transmet son entrée à sa sortie soit sans effectuer de travail, soit en transformant l'entrée d'état JSON à l'aide de filtres, puis en passant les données transformées à l'état suivant. Il est utile pour tester et construire des machines d'état, vous permettant d'injecter des données statiques ou de les transformer.
```json
"PassState": {
"Type": "Pass",
"Result": {"key": "value"},
"ResultPath": "$.newField",
"Next": "NextState"
}
```
### Attendre

Un état **Wait** retarde l'exécution de la machine d'état pendant une durée spécifiée. Il existe trois méthodes principales pour configurer le temps d'attente :

- **X Secondes** : Un nombre fixe de secondes à attendre.

```json
"WaitState": {
"Type": "Wait",
"Seconds": 10,
"Next": "NextState"
}
```

- **Horodatage Absolu** : Un moment exact jusqu'auquel attendre.

```json
"WaitState": {
"Type": "Wait",
"Timestamp": "2024-03-14T01:59:00Z",
"Next": "NextState"
}
```

- **Attente Dynamique** : Basée sur l'entrée utilisant **`SecondsPath`** ou **`TimestampPath`**.

```json
jsonCopiar código
"WaitState": {
"Type": "Wait",
"TimestampPath": "$.expirydate",
"Next": "NextState"
}
```

### Parallèle

Un état **Parallel** vous permet d'exécuter plusieurs branches de tâches simultanément dans votre flux de travail. Chaque branche s'exécute indépendamment et traite sa propre séquence d'états. L'exécution attend que toutes les branches soient terminées avant de passer à l'état suivant. Ses champs clés sont :

- **Branches** : Un tableau définissant les chemins d'exécution parallèles. Chaque branche est une machine d'état distincte.
- **ResultPath** : Définit où (dans l'entrée) placer la sortie combinée des branches.
- **Retry et Catch** : Configurations de gestion des erreurs pour l'état parallèle.
```json
"ParallelState": {
"Type": "Parallel",
"Branches": [
{
"StartAt": "Task1",
"States": { ... }
},
{
"StartAt": "Task2",
"States": { ... }
}
],
"Next": "NextState"
}
```
### Map

Un **Map** état permet l'exécution d'un ensemble d'étapes pour chaque élément d'un ensemble de données. Il est utilisé pour le traitement parallèle des données. Selon la manière dont vous souhaitez traiter les éléments de l'ensemble de données, Step Functions propose les modes suivants :

- **Inline Mode** : Exécute un sous-ensemble d'états pour chaque élément du tableau JSON. Convient aux tâches à petite échelle avec moins de 40 itérations parallèles, exécutant chacune d'elles dans le contexte du flux de travail contenant l'état **`Map`**.

```json
"MapState": {
"Type": "Map",
"ItemsPath": "$.arrayItems",
"ItemProcessor": {
"ProcessorConfig": {
"Mode": "INLINE"
},
"StartAt": "AddState",
"States": {
"AddState": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"OutputPath": "$.Payload",
"Parameters": {
"FunctionName": "arn:aws:lambda:<region>:<account-id>:function:add-function"
},
"End": true
}
}
},
"End": true
"ResultPath": "$.detail.added",
"ItemsPath": "$.added"
}
```

- **Distributed Mode** : Conçu pour le traitement parallèle à grande échelle avec une haute concurrence. Prend en charge le traitement de grands ensembles de données, tels que ceux stockés dans Amazon S3, permettant une haute concurrence allant jusqu'à 10 000 exécutions de flux de travail enfants parallèles, exécutant ces enfants comme une exécution enfant séparée.

```json
"DistributedMapState": {
"Type": "Map",
"ItemReader": {
"Resource": "arn:aws:states:::s3:getObject",
"Parameters": {
"Bucket": "my-bucket",
"Key": "data.csv"
}
},
"ItemProcessor": {
"ProcessorConfig": {
"Mode": "DISTRIBUTED",
"ExecutionType": "EXPRESS"
},
"StartAt": "ProcessItem",
"States": {
"ProcessItem": {
"Type": "Task",
"Resource": "arn:aws:lambda:region:account-id:function:my-function",
"End": true
}
}
},
"End": true
"ResultWriter": {
"Resource": "arn:aws:states:::s3:putObject",
"Parameters": {
"Bucket": "myOutputBucket",
"Prefix": "csvProcessJobs"
}
}
}
```

### Versions et alias

Step Functions vous permet également de gérer les déploiements de flux de travail via des **versions** et des **alias** de machines d'état. Une version représente un instantané d'une machine d'état qui peut être exécuté. Les alias servent de pointeurs vers jusqu'à deux versions d'une machine d'état.

- **Versions** : Ces instantanés immuables d'une machine d'état sont créés à partir de la révision la plus récente de cette machine d'état. Chaque version est identifiée par un ARN unique qui combine l'ARN de la machine d'état avec le numéro de version, séparés par un deux-points (**`arn:aws:states:region:account-id:stateMachine:StateMachineName:version-number`**). Les versions ne peuvent pas être modifiées, mais vous pouvez mettre à jour la machine d'état et publier une nouvelle version, ou utiliser la version de machine d'état souhaitée.
- **Alias** : Ces pointeurs peuvent référencer jusqu'à deux versions de la même machine d'état. Plusieurs alias peuvent être créés pour une seule machine d'état, chacun identifié par un ARN unique construit en combinant l'ARN de la machine d'état avec le nom de l'alias, séparés par un deux-points (**`arn:aws:states:region:account-id:stateMachine:StateMachineName:aliasName`**). Les alias permettent de diriger le trafic entre l'une des deux versions d'une machine d'état. Alternativement, un alias peut pointer vers une version spécifique de la machine d'état, mais pas vers d'autres alias. Ils peuvent être mis à jour pour rediriger vers une version différente de la machine d'état si nécessaire, facilitant les déploiements contrôlés et la gestion des flux de travail.

Pour des informations plus détaillées sur **ASL**, consultez : [**Amazon States Language**](https://states-language.net/spec.html).

## Rôles IAM pour les machines d'état

AWS Step Functions utilise les rôles AWS Identity and Access Management (IAM) pour contrôler l'accès aux ressources et aux actions au sein des machines d'état. Voici les principaux aspects liés à la sécurité et aux rôles IAM dans AWS Step Functions :

- **Rôle d'exécution** : Chaque machine d'état dans AWS Step Functions est associée à un rôle d'exécution IAM. Ce rôle définit quelles actions la machine d'état peut effectuer en votre nom. Lorsqu'une machine d'état passe d'états qui interagissent avec des services AWS (comme invoquer des fonctions Lambda, accéder à DynamoDB, etc.), elle assume ce rôle d'exécution pour réaliser ces actions.
- **Permissions** : Le rôle d'exécution IAM doit être configuré avec des permissions qui permettent les actions nécessaires sur d'autres services AWS. Par exemple, si votre machine d'état doit invoquer des fonctions AWS Lambda, le rôle IAM doit avoir des permissions **`lambda:InvokeFunction`**. De même, si elle doit écrire dans DynamoDB, des permissions appropriées (**`dynamodb:PutItem`**, **`dynamodb:UpdateItem`**, etc.) doivent être accordées.

## Énumération

La politique ReadOnlyAccess est suffisante pour toutes les actions d'énumération suivantes.
```bash
# State machines #

## List state machines
aws stepfunctions list-state-machines
## Retrieve informatio about the specified state machine
aws stepfunctions describe-state-machine --state-machine-arn <value>

## List versions for the specified state machine
aws stepfunctions list-state-machine-versions --state-machine-arn <value>
## List aliases for the specified state machine
aws stepfunctions list-state-machine-aliases --state-machine-arn <value>
## Retrieve information about the specified state machine alias
aws stepfunctions describe-state-machine-alias --state-machine-alias-arn <value>

## List executions of a state machine
aws stepfunctions list-executions --state-machine-arn <value> [--status-filter <RUNNING | SUCCEEDED | FAILED | TIMED_OUT | ABORTED | PENDING_REDRIVE>] [--redrive-filter <REDRIVEN | NOT_REDRIVEN>]
## Retrieve information and relevant metadata about a state machine execution (output included)
aws stepfunctions describe-execution --execution-arn <value>
## Retrieve information about the state machine associated to the specified execution
aws stepfunctions describe-state-machine-for-execution --execution-arn <value>
## Retrieve the history of the specified execution as a list of events
aws stepfunctions get-execution-history --execution-arn <value> [--reverse-order | --no-reverse-order] [--include-execution-data | --no-include-execution-data]

## List tags for the specified step Functions resource
aws stepfunctions list-tags-for-resource --resource-arn <value>

## Validate the definition of a state machine without creating the resource
aws stepfunctions validate-state-machine-definition --definition <value> [--type <STANDARD | EXPRESS>]

# Activities #

## List existing activities
aws stepfunctions list-activities
## Retrieve information about the specified activity
aws stepfunctions describe-activity --activity-arn <value>

# Map Runs #

## List map runs of an execution
aws stepfunctions list-map-runs --execution-arn <value>
## Provide information about the configuration, progress and results of a Map Run
aws stepfunctions describe-map-run --map-run-arn <value>
## Lists executions of a Map Run
aws stepfunctions list-executions --map-run-arn <value> [--status-filter <RUNNING | SUCCEEDED | FAILED | TIMED_OUT | ABORTED | PENDING_REDRIVE>] [--redrive-filter <REDRIVEN | NOT_REDRIVEN>]
```
## Privesc

Dans la page suivante, vous pouvez vérifier comment **abuser des permissions des Step Functions pour escalader les privilèges** :

{{#ref}}
../aws-privilege-escalation/aws-stepfunctions-privesc.md
{{#endref}}

## Post Exploitation

{{#ref}}
../aws-post-exploitation/aws-stepfunctions-post-exploitation.md
{{#endref}}

## Persistence

{{#ref}}
../aws-persistence/aws-step-functions-persistence.md
{{#endref}}

## References

- [https://docs.aws.amazon.com/service-authorization/latest/reference/list_awsstepfunctions.html](https://docs.aws.amazon.com/service-authorization/latest/reference/list_awsstepfunctions.html)
- [https://docs.aws.amazon.com/step-functions/latest/dg/welcome.html](https://docs.aws.amazon.com/step-functions/latest/dg/welcome.html)
- [https://states-language.net/spec.html](https://states-language.net/spec.html)

{{#include ../../../banners/hacktricks-training.md}}
