# AWS - Step Functions Enum

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

## Step Functions

AWS Step Functions è un servizio di workflow che ti consente di coordinare e orchestrare più servizi AWS in workflow serverless. Utilizzando AWS Step Functions, puoi progettare e eseguire workflow che collegano vari servizi AWS come AWS Lambda, Amazon S3, Amazon DynamoDB e molti altri, in una sequenza di passaggi. Questo servizio di orchestrazione fornisce un'interfaccia visiva per i workflow e offre capacità di **macchina a stati**, consentendoti di definire ogni passaggio del workflow in modo dichiarativo utilizzando il **Amazon States Language** (ASL) basato su JSON.

## Concetti chiave

### Workflow Standard vs. Express

AWS Step Functions offre due tipi di **workflow a macchina a stati**: Standard ed Express.

- **Workflow Standard**: Questo tipo di workflow predefinito è progettato per processi a lungo termine, durevoli e auditabili. Supporta l'**esecuzione esattamente una volta**, garantendo che i compiti vengano eseguiti solo una volta a meno che non siano specificati i tentativi. È ideale per workflow che necessitano di una cronologia di esecuzione dettagliata e può durare fino a un anno.
- **Workflow Express**: Questo tipo è ideale per compiti ad alto volume e breve durata, con una durata massima di cinque minuti. Supportano l'**esecuzione almeno una volta**, adatta per compiti idempotenti come l'elaborazione dei dati. Questi workflow sono ottimizzati per costi e prestazioni, addebitando in base alle esecuzioni, alla durata e all'uso della memoria.

### Stati

Gli stati sono le unità essenziali delle macchine a stati. Definiscono i singoli passaggi all'interno di un workflow, potendo eseguire una varietà di funzioni a seconda del tipo:

- **Task:** Esegue un lavoro, spesso utilizzando un servizio AWS come Lambda.
- **Choice:** Prende decisioni basate sull'input.
- **Fail/Succeed:** Termina l'esecuzione con un fallimento o un successo.
- **Pass:** Passa l'input all'output o inietta dati.
- **Wait:** Ritarda l'esecuzione per un tempo stabilito.
- **Parallel:** Inizia rami paralleli.
- **Map:** Itera dinamicamente i passaggi su elementi.

### Task

Uno stato **Task** rappresenta una singola unità di lavoro eseguita da una macchina a stati. I task possono invocare varie risorse, comprese attività, funzioni Lambda, servizi AWS o API di terze parti.

- **Attività**: Lavoratori personalizzati che gestisci, adatti per processi a lungo termine.
- Risorsa: **`arn:aws:states:region:account:activity:name`**.
- **Funzioni Lambda**: Esegue funzioni AWS Lambda.
- Risorsa: **`arn:aws:lambda:region:account:function:function-name`**.
- **Servizi AWS**: Si integra direttamente con altri servizi AWS, come DynamoDB o S3.
- Risorsa: **`arn:partition:states:region:account:servicename:APIname`**.
- **HTTP Task**: Chiama API di terze parti.
- Campo risorsa: **`arn:aws:states:::http:invoke`**. Quindi, dovresti fornire i dettagli di configurazione dell'endpoint API, come l'URL dell'API, il metodo e i dettagli di autenticazione.

Il seguente esempio mostra una definizione di stato Task che invoca una funzione Lambda chiamata HelloWorld:
```json
"HelloWorld": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"Parameters": {
"Payload.$": "$",
"FunctionName": "arn:aws:lambda:<region>:<account-id>:function:HelloWorld"
},
"End": true
}
```
### Choice

Uno stato di **Choice** aggiunge logica condizionale a un flusso di lavoro, abilitando decisioni basate sui dati di input. Valuta le condizioni specificate e transita allo stato corrispondente in base ai risultati.

- **Comparison**: Ogni regola di scelta include un operatore di confronto (ad es., **`NumericEquals`**, **`StringEquals`**) che confronta una variabile di input con un valore specificato o un'altra variabile.
- **Next Field**: Gli stati di scelta non supportano il campo **`End`**, invece, definiscono lo stato **`Next`** a cui transitare se il confronto è vero.

Esempio di stato **Choice**:
```json
{
"Variable": "$.timeStamp",
"TimestampEquals": "2000-01-01T00:00:00Z",
"Next": "TimeState"
}
```
### Fail/Succeed

Uno stato **`Fail`** ferma l'esecuzione di una macchina a stati e la segna come un fallimento. Viene utilizzato per specificare un nome di errore e una causa, fornendo dettagli sul fallimento. Questo stato è terminale, il che significa che termina il flusso di esecuzione.

Uno stato **`Succeed`** ferma l'esecuzione con successo. Viene tipicamente utilizzato per terminare il flusso di lavoro quando completa con successo. Questo stato non richiede un campo **`Next`**.

{{#tabs }}
{{#tab name="Fail example" }}
```json
"FailState": {
"Type": "Fail",
"Error": "ErrorName",
"Cause": "Error details"
}
```
{{#endtab }}

{{#tab name="Esempio di successo" }}
```json
"SuccessState": {
"Type": "Succeed"
}
```
{{#endtab }}
{{#endtabs }}

### Pass

Uno stato **Pass** passa il suo input al suo output senza eseguire alcun lavoro o trasformando l'input dello stato JSON utilizzando filtri, e poi passando i dati trasformati al prossimo stato. È utile per testare e costruire macchine a stati, permettendo di iniettare dati statici o trasformarli.
```json
"PassState": {
"Type": "Pass",
"Result": {"key": "value"},
"ResultPath": "$.newField",
"Next": "NextState"
}
```
### Aspetta

Uno stato di **Aspetta** ritarda l'esecuzione della macchina a stati per una durata specificata. Ci sono tre metodi principali per configurare il tempo di attesa:

- **X Secondi**: Un numero fisso di secondi da attendere.

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

- **Timestamp Assoluto**: Un orario esatto fino al quale attendere.

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

- **Attesa Dinamica**: Basata su input utilizzando **`SecondsPath`** o **`TimestampPath`**.

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

### Parallelo

Uno stato di **Parallelo** consente di eseguire più rami di attività contemporaneamente all'interno del tuo flusso di lavoro. Ogni ramo viene eseguito in modo indipendente e elabora la propria sequenza di stati. L'esecuzione attende fino al completamento di tutti i rami prima di procedere allo stato successivo. I suoi campi chiave sono:

- **Rami**: Un array che definisce i percorsi di esecuzione paralleli. Ogni ramo è una macchina a stati separata.
- **ResultPath**: Definisce dove (nell'input) posizionare l'output combinato dei rami.
- **Retry e Catch**: Configurazioni di gestione degli errori per lo stato parallelo.
```json
"ParallelState": {
"Type": "Parallel",
"Branches": [
{
"StartAt": "Task1",
"States": { ... }
},
{
"StartAt": "Task2",
"States": { ... }
}
],
"Next": "NextState"
}
```
### Mappa

Uno stato **Map** consente l'esecuzione di un insieme di passaggi per ogni elemento in un dataset. Viene utilizzato per l'elaborazione parallela dei dati. A seconda di come si desidera elaborare gli elementi del dataset, Step Functions fornisce le seguenti modalità:

- **Modalità Inline**: Esegue un sottoinsieme di stati per ogni elemento dell'array JSON. Adatto per compiti su piccola scala con meno di 40 iterazioni parallele, eseguendo ciascuna di esse nel contesto del flusso di lavoro che contiene lo stato **`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"
}
```

- **Modalità Distribuita**: Progettata per l'elaborazione parallela su larga scala con alta concorrenza. Supporta l'elaborazione di grandi dataset, come quelli memorizzati in Amazon S3, consentendo un'alta concorrenza fino a 10.000 esecuzioni di flussi di lavoro secondari paralleli, eseguendo questi secondari come un'esecuzione secondaria separata.

```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"
}
}
}
```

### Versioni e alias

Step Functions consente anche di gestire le distribuzioni dei flussi di lavoro attraverso **versioni** e **alias** delle macchine a stati. Una versione rappresenta uno snapshot di una macchina a stati che può essere eseguito. Gli alias fungono da puntatori a un massimo di due versioni di una macchina a stati.

- **Versioni**: Questi snapshot immutabili di una macchina a stati vengono creati dalla revisione più recente di quella macchina a stati. Ogni versione è identificata da un ARN unico che combina l'ARN della macchina a stati con il numero di versione, separati da due punti (**`arn:aws:states:region:account-id:stateMachine:StateMachineName:version-number`**). Le versioni non possono essere modificate, ma è possibile aggiornare la macchina a stati e pubblicare una nuova versione, o utilizzare la versione desiderata della macchina a stati.
- **Alias**: Questi puntatori possono fare riferimento a un massimo di due versioni della stessa macchina a stati. Possono essere creati più alias per una singola macchina a stati, ciascuno identificato da un ARN unico costruito combinando l'ARN della macchina a stati con il nome dell'alias, separati da due punti (**`arn:aws:states:region:account-id:stateMachine:StateMachineName:aliasName`**). Gli alias consentono il routing del traffico tra una delle due versioni di una macchina a stati. In alternativa, un alias può puntare a una singola versione specifica della macchina a stati, ma non ad altri alias. Possono essere aggiornati per reindirizzare a una versione diversa della macchina a stati secondo necessità, facilitando distribuzioni controllate e gestione dei flussi di lavoro.

Per ulteriori informazioni dettagliate su **ASL**, controlla: [**Amazon States Language**](https://states-language.net/spec.html).

## Ruoli IAM per macchine a stati

AWS Step Functions utilizza i ruoli di AWS Identity and Access Management (IAM) per controllare l'accesso alle risorse e alle azioni all'interno delle macchine a stati. Ecco gli aspetti chiave relativi alla sicurezza e ai ruoli IAM in AWS Step Functions:

- **Ruolo di Esecuzione**: Ogni macchina a stati in AWS Step Functions è associata a un ruolo di esecuzione IAM. Questo ruolo definisce quali azioni la macchina a stati può eseguire per tuo conto. Quando una macchina a stati transita tra stati che interagiscono con i servizi AWS (come l'invocazione di funzioni Lambda, l'accesso a DynamoDB, ecc.), assume questo ruolo di esecuzione per svolgere quelle azioni.
- **Permessi**: Il ruolo di esecuzione IAM deve essere configurato con permessi che consentano le azioni necessarie su altri servizi AWS. Ad esempio, se la tua macchina a stati deve invocare funzioni AWS Lambda, il ruolo IAM deve avere permessi **`lambda:InvokeFunction`**. Allo stesso modo, se deve scrivere su DynamoDB, devono essere concessi i permessi appropriati (**`dynamodb:PutItem`**, **`dynamodb:UpdateItem`**, ecc.).

## Enumerazione

La policy ReadOnlyAccess è sufficiente per tutte le seguenti azioni di enumerazione.
```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

Nella pagina seguente, puoi controllare come **abusare dei permessi di Step Functions per escalare i privilegi**:

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

## Post Exploitation

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

## Persistence

{{#ref}}
../aws-persistence/aws-step-functions-persistence/README.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}}
