references/fis-actions-reference.md
# AWS FIS Actions, Action Selection & Scenario Library
Use this to **suggest** the right fault for a scenario and to build the `actions` block of a
template. Action IDs and parameters change over time — **verify with `aws fis list-actions` and
`aws fis get-action --id <action-id>`** (or the [FIS Actions reference](https://docs.aws.amazon.com/fis/latest/userguide/fis-actions-reference.html))
before committing to a command. The tables below are illustrative, not a frozen source of truth.
## Contents
- Action structure
- Action selection map — match failure scenario → action
- Action catalog by namespace (illustrative)
- Targets — how to scope the blast radius
- Scenario library (console-only, AWS-owned)
- Prerequisites & gotchas by action
## Action structure
Each action in `actions` has:
| Field | Meaning |
|---|---|
| `actionId` | The pre-defined FIS action to run (e.g. `aws:ec2:stop-instances`). **Required.** |
| `parameters` | Key-value pairs for the action (durations use ISO 8601, e.g. `PT10M`). Required/optional per action. |
| `targets` | Maps the action's target role name → a target defined in the template's `targets` block. |
| `startAfter` | Names of actions that must finish before this one starts. Omit → runs in parallel. |
```json
"actions": {
"StopInstances": {
"actionId": "aws:ec2:stop-instances",
"description": "Stop EC2 instances then restart after 10 minutes",
"parameters": { "startInstancesAfterDuration": "PT10M" },
"targets": { "Instances": "myInstanceTarget" },
"startAfter": []
}
}
```
### Action ID naming convention
`aws:<service-name>:<action-type>` — e.g. `aws:rds:failover-db-cluster`. Service-level fault
namespaces (`aws:ec2:*`, `aws:rds:*`, …) act on infrastructure; the `aws:fis:*` namespace injects
**API-level** faults and provides control actions (`wait`).
## Action selection map — match failure scenario → action
Models often pick a real but *wrong* action. Use this map, then verify the ID.
| If the scenario is… | Illustrative action ID (verify with `list-actions`) |
|---|---|
| Full AZ power interruption / "AZ goes dark" | Use the **AZ Availability: Power Interruption** scenario (multi-fault); it combines instance/subnet/EBS/RDS/ElastiCache faults |
| Single-AZ instance loss | `aws:ec2:stop-instances` or `aws:ec2:terminate-instances` (scope target to the AZ via filter) |
| Spot capacity reclaim | `aws:ec2:send-spot-instance-interruptions` |
| ECS task loss / capacity drain | `aws:ecs:stop-task`, `aws:ecs:drain-container-instances` |
| EKS pod failure | `aws:eks:pod-delete` |
| EKS node loss | `aws:eks:terminate-nodegroup-instances` |
| EKS pod latency / packet loss | `aws:eks:pod-network-latency`, `aws:eks:pod-network-packet-loss` |
| DB / Aurora / RDS failover | `aws:rds:failover-db-cluster` (cluster) or `aws:rds:reboot-db-instances` (instance) |
| ElastiCache node/AZ disruption | `aws:elasticache:replicationgroup-interrupt-az-power` |
| Region-level API unavailability | `aws:fis:inject-api-unavailable-error` |
| Service returns 5xx but is reachable | `aws:fis:inject-api-internal-error` |
| Throttling / 429 responses | `aws:fis:inject-api-throttle-error` |
| Lambda slow responses (latency) | `aws:lambda:invocation-add-delay` |
| Lambda forced errors | `aws:lambda:invocation-error` |
| Lambda altered HTTP integration response | `aws:lambda:invocation-http-integration-response` |
| Network partition / subnet isolation | `aws:network:disrupt-connectivity` |
| Route-table-level connectivity loss | `aws:network:route-table-disrupt-connectivity` |
| Cross-Region (transit gateway) isolation | `aws:network:transit-gateway-disrupt-cross-region-connectivity` |
| EBS volume I/O latency | `aws:ebs:pause-volume-io` (Nitro only) — or the EBS latency scenarios |
| Run a custom fault on a host | `aws:ssm:send-command`, `aws:ssm:start-automation-execution` |
| Assert a CloudWatch alarm's state mid-experiment | `aws:cloudwatch:assert-alarm-state` |
| Trigger ARC zonal autoshift | `aws:arc:start-zonal-autoshift` |
| Insert a pause between actions | `aws:fis:wait` |
**Rule of thumb:** a **service/API symptom** (unavailable, 5xx, throttle) → `aws:fis:inject-api-*`
(all three end in `-error`). An **infrastructure symptom** (instance, task, pod, DB, cache,
volume, network) → the resource-specific namespace.
## Action catalog by namespace (illustrative)
- **EC2** — `aws:ec2:stop-instances`, `aws:ec2:reboot-instances`, `aws:ec2:terminate-instances`,
`aws:ec2:send-spot-instance-interruptions`, `aws:ec2:api-insufficient-instance-capacity-error`.
- **ECS** — `aws:ecs:stop-task`, `aws:ecs:drain-container-instances`, plus SSM-agent-based CPU/
memory/IO/network stress task actions.
- **EKS** — `aws:eks:pod-delete`, `aws:eks:terminate-nodegroup-instances`,
`aws:eks:pod-cpu-stress`, `aws:eks:pod-memory-stress`, `aws:eks:pod-io-stress`,
`aws:eks:pod-network-latency`, `aws:eks:pod-network-packet-loss`,
`aws:eks:pod-network-blackhole-port`.
- **RDS** — `aws:rds:reboot-db-instances`, `aws:rds:failover-db-cluster`.
- **ElastiCache** — `aws:elasticache:replicationgroup-interrupt-az-power`.
- **EBS** — `aws:ebs:pause-volume-io` (Nitro-based instances only).
- **Lambda** — `aws:lambda:invocation-add-delay`, `aws:lambda:invocation-error`,
`aws:lambda:invocation-http-integration-response` (require the FIS Lambda extension layer).
- **Network** — `aws:network:disrupt-connectivity`,
`aws:network:route-table-disrupt-connectivity`,
`aws:network:transit-gateway-disrupt-cross-region-connectivity`.
- **FIS API faults / control** — `aws:fis:inject-api-internal-error`,
`aws:fis:inject-api-throttle-error`, `aws:fis:inject-api-unavailable-error`, `aws:fis:wait`.
- **SSM (custom faults on hosts)** — `aws:ssm:send-command` (runs an SSM document, e.g. FIS
public stress documents like `AWSFIS-Run-CPU-Stress`), `aws:ssm:start-automation-execution`.
Requires the SSM Agent installed/running on targets.
- **CloudWatch** — `aws:cloudwatch:assert-alarm-state`.
- **ARC** — `aws:arc:start-zonal-autoshift`.
## Targets — how to scope the blast radius
A target defines `resourceType` (exactly one) plus one selector:
- `resourceArns` — specific resource ARNs (cannot combine with tags or filters).
- `resourceTags` — map of tag key→value; **all** listed tags must match (AND).
- `filters` — `path` (PascalCase, from the resource's Describe API output) + `values` (OR within
a filter; AND across filters). Cannot combine with `resourceArns`.
- `parameters` — attribute-based selectors for certain resource types (see below).
- `selectionMode` — `ALL`, `COUNT(n)`, or `PERCENT(n)`; picks from the identified set at random.
`COUNT(n)` selects exactly `n` resources — no rounding. `PERCENT(n)` resolves the percentage to a
count and **rounds down**; if it resolves to fewer than 1 resource, nothing is selected and the
experiment fails.
FIS resolves **all** targets at experiment start. If a target resolves to zero resources, the
experiment fails (unless `emptyTargetResolutionMode` is `skip`).
### Resource parameters (attribute selectors) — examples
- `aws:ec2:ebs-volume` → `availabilityZoneIdentifier`.
- `aws:ec2:subnet` → `availabilityZoneIdentifier`, `vpc` (one VPC per account).
- `aws:ecs:task` → `cluster`, `service`.
- `aws:eks:pod` → `clusterIdentifier` (req), `namespace` (req), `selectorType`
(`labelSelector`|`deploymentName`|`podName`, req), `selectorValue` (req),
`availabilityZoneIdentifier` (opt), `targetContainerName` (opt).
- `aws:lambda:function` → `functionQualifier`.
- `aws:rds:cluster` → `writerAvailabilityZoneIdentifiers`; `aws:rds:db` → `availabilityZoneIdentifiers`.
- `aws:elasticache:replicationgroup` → `availabilityZoneIdentifier` (req).
**Multi-account / cross-AZ tip:** when targeting by AZ, use the **AZ ID** (e.g. `use1-az1`), not
the AZ name (`us-east-1a`) — AZ IDs are consistent across accounts.
### Example target
```json
"targets": {
"randomInstance": {
"resourceType": "aws:ec2:instance",
"resourceTags": { "env": "prod" },
"filters": [
{ "path": "Placement.AvailabilityZone", "values": ["us-east-1a"] },
{ "path": "State.Name", "values": ["running"] }
],
"selectionMode": "COUNT(1)"
}
}
```
## Scenario library (console-only, AWS-owned)
Scenarios are pre-built target+action patterns for common impairments. They are a **console-only**
experience: select one in the FIS console → **Create template with scenario** → fill in
parameters, role, stop conditions, logging → save as an experiment template. To automate, either
export the created template, or copy the scenario's **Content** tab and complete missing
parameters manually. Prefer a scenario over a hand-built template when one fits — less
undifferentiated heavy lifting and AWS-maintained.
Common scenarios (verify current library in the console):
**EC2 (target by tag):**
- **EC2 stress: instance failure** — stop instances, restart after the action duration (default 5 min).
- **EC2 stress: CPU / Memory / Disk / Network Latency** — inject increasing resource pressure.
**EKS (target pods by Kubernetes app label):**
- **EKS stress: Pod Delete** — delete matched pods (recovery per k8s config).
- **EKS stress: CPU / Memory / Disk / Network latency**.
**Single-AZ / multi-AZ / multi-Region (multiple resource types):**
- **AZ Availability: Power Interruption** — simulate a complete power interruption in one AZ.
- **AZ: Application Slowdown** — add latency between resources within one AZ.
- **Cross-AZ: Traffic Slowdown** — inject packet loss between AZs.
- **Cross-Region: Connectivity** — block traffic from the experiment Region to a destination
Region and pause cross-Region data replication.
**EBS (target volumes by tag; volumes must be in the same AZ):**
- **EBS: Sustained / Increasing / Intermittent / Decreasing Latency** — I/O latency patterns.
## Prerequisites & gotchas by action
- **SSM-based actions** (host stress, custom faults): SSM Agent must be installed and running on
targets; the experiment role needs SSM permissions.
- **Lambda actions**: require the FIS Lambda extension layer configured on the function.
- **EBS `pause-volume-io`**: target volumes must be attached to Nitro-based instances.
- **EKS pod actions**: require the target EKS cluster to be prepared for FIS (see EKS Pod actions docs).
- **Network faults**: verify VPC/subnet/route-table prerequisites; connectivity disruption acts
at the network layer, not the API layer.
references/fis-api-reference.md
# AWS FIS API Quick Reference
**Read this BEFORE producing any `aws fis` command.** This is the canonical, deterministic source
of truth for FIS operation names and template parameters. Without explicit guidance, models
substitute plausible-sounding API names that don't exist. Action IDs and resource types still
evolve — verify those with `aws fis list-actions` / `aws fis get-action`.
---
## Contents
- ⚠️ TOP HALLUCINATIONS — DO NOT WRITE THESE
- Canonical `aws fis` operations
- Template top-level fields (create/update)
- Experiment & action states
- Tooling prerequisite — the client must support FIS
- Related service namespaces (do NOT confuse with `aws fis`)
## ⚠️ TOP HALLUCINATIONS — DO NOT WRITE THESE
| ❌ NEVER WRITE | ✅ ALWAYS WRITE |
|---|---|
| `aws fis create-experiment` | `aws fis create-experiment-template` (you create a *template*, then start an experiment from it) |
| `aws fis run-experiment` | `aws fis start-experiment --experiment-template-id EXTxxxx` |
| `aws fis start-experiment --template-id` | `aws fis start-experiment --experiment-template-id` (full flag) |
| `aws fis describe-experiment` | `aws fis get-experiment --id EXPxxxx` |
| `aws fis describe-experiment-template` | `aws fis get-experiment-template --id EXTxxxx` |
| `aws fis list-experiment-templates --template-id` | `aws fis list-experiment-templates` (no id) / `get-experiment-template --id` for one |
| `aws fis cancel-experiment` | `aws fis stop-experiment --id EXPxxxx` |
| `aws fis get-action --action-id` | `aws fis get-action --id <action-id>` |
| `aws fis list-experiment-targets` | `aws fis list-experiment-resolved-targets --id EXPxxxx` |
| `aws:fis:inject-api-unavailable` (no suffix) | `aws:fis:inject-api-unavailable-error` (real action ends in `-error`) |
| `aws:ec2:stop-instance` (singular) | `aws:ec2:stop-instances` (plural) |
| `aws:rds:failover-cluster` | `aws:rds:failover-db-cluster` |
| `aws:eks:delete-pod` | `aws:eks:pod-delete` |
| `--stop-conditions` omitted on create | `stopConditions` is **required**. Always prefer a real `aws:cloudwatch:alarm` stop condition; use `[{"source":"none"}]` **ONLY in a disposable sandbox — never in production** |
| `roleArn` optional | `roleArn` is **required** — FIS assumes it to run actions |
**Memory aids:**
- Templates use **get/create/update/delete-experiment-template**; runs use
**start/stop/get-experiment** + **list-experiment-resolved-targets**. There is no
"create-experiment" or "run-experiment".
- All three FIS API-fault actions end in **`-error`**:
`inject-api-internal-error`, `inject-api-throttle-error`, `inject-api-unavailable-error`.
---
## Canonical `aws fis` operations
### Experiment templates
- `create-experiment-template --cli-input-json file://template.json`
(or explicit `--description --role-arn --actions --targets --stop-conditions [--log-configuration]
[--experiment-options] [--experiment-report-configuration] [--tags]`)
- `get-experiment-template --id EXTxxxx`
- `list-experiment-templates`
- `update-experiment-template --id EXTxxxx --cli-input-json file://template-v2.json`
- `delete-experiment-template --id EXTxxxx`
### Experiments (runs)
- `start-experiment --experiment-template-id EXTxxxx [--tags K=V] [--experiment-options ...]`
- `get-experiment --id EXPxxxx`
- `list-experiments`
- `stop-experiment --id EXPxxxx`
- `list-experiment-resolved-targets --id EXPxxxx [--target-name NAME]`
### Actions (discovery — use to VERIFY action IDs)
- `list-actions` — enumerate all available action IDs.
- `get-action --id <action-id>` — parameters, targets, and description for one action.
### Multi-account target account configurations
- `create-target-account-configuration --experiment-template-id EXTxxxx --account-id 222233334444 --role-arn ARN [--description "..."]`
- `get-target-account-configuration --experiment-template-id EXTxxxx --account-id 222233334444`
- `list-target-account-configurations --experiment-template-id EXTxxxx`
- `update-target-account-configuration --experiment-template-id EXTxxxx --account-id 222233334444 ...`
- `delete-target-account-configuration --experiment-template-id EXTxxxx --account-id 222233334444`
### Tagging
Tagging operations take a **resource ARN** (`--resource-arn`), not the `--id` used by the
template/experiment operations. FIS resource ARN formats:
- Experiment template: `arn:aws:fis:<region>:<account-id>:experiment-template/<EXTxxxx>`
- Experiment (run): `arn:aws:fis:<region>:<account-id>:experiment/<EXPxxxx>`
- `list-tags-for-resource --resource-arn ARN`
- `tag-resource --resource-arn ARN --tags K=V`
- `untag-resource --resource-arn ARN --tag-keys K`
---
## Template top-level fields (create/update)
| Field | Required | Notes |
|---|---|---|
| `description` | yes | Free text — no PII/secrets (surfaces in CloudTrail/console). |
| `roleArn` | yes | Role FIS assumes; trust `fis.amazonaws.com` + confused-deputy conditions. |
| `actions` | yes | Map of action name → `{actionId, parameters, targets, startAfter, description}`. |
| `targets` | yes (may be `{}`) | Map of target name → `{resourceType, resourceArns \| resourceTags \| filters \| parameters, selectionMode}`. Field is **required even when no action needs a target** — pass `{}` for target-less actions (e.g. `aws:fis:wait`); omitting it fails create with `targets is required`. |
| `stopConditions` | yes | List of `{source, value}`; `source` = `aws:cloudwatch:alarm` (with alarm ARN in `value`) or `none`. |
| `logConfiguration` | no | `{logSchemaVersion, cloudWatchLogsConfiguration and/or s3Configuration}` — **both destinations may be set together**, unlike the mutually exclusive selectors in `targets` above. `logSchemaVersion` must be `2`. |
| `experimentReportConfiguration` | no | `{outputs.s3Configuration, dataSources.cloudWatchDashboards, preExperimentDuration, postExperimentDuration}`. |
| `experimentOptions` | no | `{accountTargeting: single-account \| multi-account, emptyTargetResolutionMode: fail \| skip, actionsMode: run-all \| skip-all}`. |
| `tags` | no | Map. |
### Selection modes
Random pick from the identified set:
- `ALL` — every identified resource.
- `COUNT(n)` — exactly `n` resources. No rounding.
- `PERCENT(n)` — resolves the percentage to a count and **rounds down**; if it resolves to fewer
than 1 resource, nothing is selected and the experiment fails.
### `experimentOptions` semantics
- `accountTargeting`: `multi-account` requires ≥1 target account configuration.
- `emptyTargetResolutionMode`: `fail` (default) fails the experiment if any target resolves to
zero; `skip` continues.
- `actionsMode`: `skip-all` = **target preview** (resolves targets, runs no actions, no report/
charge for actions).
---
## Experiment & action states
- Experiment: `pending` → `initiating` → `running` → `completed` | `stopping` → `stopped` | `failed`.
- Action: adds `cancelled`.
- `stopped` ≈ stop condition fired or manual stop; `failed` ≈ target resolution or action error.
- Cannot resume `stopped`/`failed` or rerun `completed` — start a new experiment.
---
## Tooling prerequisite — the client must support FIS
The `fis` subcommand requires **AWS CLI v2**. If `aws fis ...` fails with `Invalid choice: fis`,
the client predates FIS support: upgrade to AWS CLI v2, use the **AWS MCP server**, or call FIS
via an SDK that includes the FIS client (e.g. `boto3`) — the operation and parameter names above
are identical across all of them.
---
## Related service namespaces (do NOT confuse with `aws fis`)
- CloudWatch alarms (stop conditions): `aws cloudwatch put-metric-alarm` / `describe-alarms`.
- ARC zonal shift (FIS can *trigger* autoshift via the `aws:arc:start-zonal-autoshift` action;
ARC *setup* is `aws arc-zonal-shift ...` — see the `recovery-controller-setup` skill).
- Resilience Hub v2 (Define phase): `aws resiliencehubv2 ...` — see `aws-resilience-lifecycle`.
Verify the authoritative FIS command surface with `aws fis help` and each subcommand's `help`
rather than treating this list as permanently fixed.
references/fis-concepts.md
# AWS FIS Concepts & Terminology
Authoritative source: <https://docs.aws.amazon.com/fis/> — verify specifics there, as FIS adds
actions, resource types, and scenarios over time.
## Contents
- What AWS FIS is
- Core concepts (official terminology)
- Lifecycle: template → experiment → analysis
- Experiment states
- Supported resource types
- Ways to work with FIS
- Pricing (high level)
- When to recommend FIS (and when not)
- How FIS fits the resilience lifecycle
- Security — see fis-security.md
## What AWS FIS is
AWS Fault Injection Service (AWS FIS) is a managed service for running **fault injection
experiments** on AWS workloads, based on the principles of **chaos engineering**. Experiments
stress an application with disruptive events so you can observe how it responds and then improve
its performance and resilience. FIS provides pre-built fault actions plus the controls and
guardrails (stop conditions, roll-back on threshold breach) needed to run experiments safely —
including in production.
**Important:** FIS carries out real actions on real AWS resources. Always plan first, run in
pre-production before production, and bound the blast radius with a stop condition.
## Core concepts (official terminology — use these exact terms)
| Term | Definition |
|---|---|
| **Experiment** | A single run that tests your theory of how the system behaves under fault. Started from an experiment template. Finishes when all actions complete, a stop condition triggers, an action errors, or you stop it manually. |
| **Experiment template** | The blueprint of an experiment. Contains **actions**, **targets**, **stop conditions**, an IAM **role**, and optional **logging**, **report configuration**, and **experiment options**. |
| **Action** | An activity FIS performs on a resource during an experiment (e.g., stop instances, inject latency). Runs for a set duration or until the experiment stops. Actions run sequentially (via `startAfter`) or in parallel. |
| **Target** | One or more AWS resources an action runs on. Selected by resource ARNs, tags, filters, or parameters, then narrowed by a **selection mode** (`ALL`, `COUNT(n)`, `PERCENT(n)`). |
| **Stop condition** | A guardrail that stops the experiment if a CloudWatch alarm enters ALARM state. Defines the safe boundary (blast radius) of the experiment. |
| **Scenario** | An AWS-owned, pre-built pattern (console-only "scenario library") of targets + actions for a common impairment. Used to create an experiment template. |
| **Experiment report** | An optional PDF summarizing an experiment's actions and (optionally) a CloudWatch dashboard snapshot; delivered to S3. |
| **Orchestrator / target account** | In multi-account experiments, the orchestrator account owns the template/experiment; target accounts hold the affected resources. |
## Lifecycle: template → experiment → analysis
1. **Create an experiment template** (`create-experiment-template`) — define actions, targets,
stop conditions, role, and optional logging/report/options.
2. **(Recommended) Preview targets** — verify which resources will be affected before running.
3. **Start an experiment** (`start-experiment`) from the template.
4. **Monitor** (`get-experiment`) — track state and resolved targets; view logs.
5. **Experiment finishes** when: all actions complete, a stop condition triggers, an action
errors, or you `stop-experiment` manually.
6. **Analyze** — review metrics/dashboards, logs, and (if enabled) the experiment report.
You **cannot resume** a stopped or failed experiment, and you cannot rerun a completed one — start
a new experiment from the (optionally updated) template.
## Experiment states
`pending` → `initiating` → `running` → `completed` | `stopping` → `stopped` | `failed`.
(Action states add `cancelled`.) A `failed` experiment usually means target resolution failed or
an action could not run; `stopped` usually means a stop condition fired or a manual stop.
## Supported resource types (target `resourceType`)
FIS adds support for new services over time, so **do not treat any list as exhaustive** — a stale
list will cause you to tell a user a resource type is unsupported when it is. Discover the current
set instead:
```bash
# every action, with the resource type each one targets
aws fis list-actions
aws fis get-action --id <action-id> # inspect its targets
```
Illustrative examples of the shape these take: `aws:ec2:instance`, `aws:ecs:task`,
`aws:eks:pod`, `aws:rds:cluster`, `aws:lambda:function`, `aws:s3:bucket`. The authoritative list is
in the [FIS documentation](https://docs.aws.amazon.com/fis/latest/userguide/targets.html).
Each action supports exactly one resource type; a target must match the action's resource type.
## Ways to work with FIS
- **Console** — <https://console.aws.amazon.com/fis/> (only place with the scenario library).
- **AWS CLI** — `aws fis ...` ([CLI reference](https://docs.aws.amazon.com/cli/latest/reference/fis/)).
- **AWS CloudFormation** — `AWS::FIS::ExperimentTemplate` (and `AWS::FIS::TargetAccountConfiguration`).
- **AWS SDKs** — language-specific FIS clients.
- **HTTPS API** — [FIS API Reference](https://docs.aws.amazon.com/fis/latest/APIReference/).
## Pricing (high level)
FIS charges are based on action runtime and the number of target accounts; experiment logging
(vended logs to CloudWatch Logs / S3) and experiment reports (S3 storage plus the CloudWatch
`GetMetricWidgetImage`/`GetDashboard` calls) incur additional charges from those services.
Pricing details change — check <https://aws.amazon.com/fis/pricing/> for the current model rather
than quoting rates from here.
## When to recommend FIS (and when not)
**Recommend FIS when the user wants to:**
- Validate that an application actually survives a failure mode (AZ loss, Region isolation, DB
failover, dependency latency/errors, resource exhaustion) — not just assume it does.
- Prove a Resilience Hub finding's remediation with a reproduced failure before marking it
resolved (see `aws-resilience-lifecycle`).
- Run game days / continuous resilience testing with bounded, observable, auto-stopping faults.
**Redirect when:**
- They want to **set up** ARC routing controls or zonal shift → `recovery-controller-setup`
(FIS can *trigger* zonal autoshift via `aws:arc:start-zonal-autoshift`, but does not configure ARC).
- They want the **end-to-end resilience program** (Define → Test → Operate) → `aws-resilience-lifecycle`.
- They want CloudWatch **alarm/dashboard setup** itself → the AWS Observability skill.
## How FIS fits the resilience lifecycle
Define (Resilience Hub) → **Test (FIS)** → Operate (ARC). FIS is the "Test" phase: it reproduces
the failure modes surfaced during Define and validates the operational controls built for
Operate. Stop conditions reuse the same CloudWatch alarms that define steady state.
## Security
FIS performs real, potentially destructive actions on real resources, so treat every experiment as
a privileged operation. Full guidance is in [fis-security.md](fis-security.md):
- The experiment IAM role — trust policy with **confused-deputy** conditions
(`aws:SourceAccount` + `aws:SourceArn`), and least-privilege permissions scoped by ARN/tag.
- Restricting who may call `fis:StartExperiment`, including the caller's `iam:PassRole` condition.
- Bounding the blast radius — a mandatory CloudWatch-alarm stop condition, narrow targeting
(`COUNT(1)` / low `PERCENT`), target preview, and pre-production before production.
- Data handling — no PII or secrets in template/experiment string fields, and encryption for
experiment logs and reports.
references/fis-security.md
# Security Considerations — aws-fault-injection-service
FIS runs **real, potentially destructive actions on real resources**. Secure both *who can run
experiments* and *what an experiment is allowed to touch*, and always bound the blast radius.
## Contents
- The experiment IAM role (`roleArn`)
- Restrict who can start experiments
- Bounded blast radius (safety, not just IAM)
- Data handling
- Auditing
- Further reading
## The experiment IAM role (`roleArn`)
FIS assumes the experiment role to perform actions on your behalf. It is a **service role** with:
1. A **trust policy** allowing `fis.amazonaws.com` to assume it, with confused-deputy conditions.
2. **Identity-based permissions** for exactly the target-service APIs the experiment's actions
invoke (and SSM / logs / report S3+CloudWatch if those features are used).
### Trust policy with confused-deputy protection (required)
Condition on `aws:SourceAccount` and `aws:SourceArn` so only your account's FIS experiments can
assume the role — never leave the trust policy unconditioned.
```json
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": { "Service": "fis.amazonaws.com" },
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": { "aws:SourceAccount": "123456789012" },
"ArnLike": {
"aws:SourceArn": "arn:aws:fis:us-east-1:123456789012:experiment/*"
}
}
}]
}
```
### Least-privilege permissions (scope to actions AND target ARNs)
Grant only what the chosen actions need, scoped to the specific target resources — never `"*"`
across a service. Example for an EC2 reboot experiment on tagged prod instances:
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["ec2:RebootInstances"],
"Resource": "arn:aws:ec2:us-east-1:123456789012:instance/*",
"Condition": { "StringEquals": { "aws:ResourceTag/env": "prod" } }
},
{
"Effect": "Allow",
"Action": ["ec2:DescribeInstances"],
"Resource": "*"
}
]
}
```
`Describe*` calls FIS uses for target resolution/filtering generally require `Resource: "*"`
(they don't support resource-level scoping), but the **fault** actions should be scoped by ARN
and/or `aws:ResourceTag`. Match permissions to the action's underlying API.
### Action → underlying-permission mapping (illustrative — verify with `get-action`)
The exact IAM actions each FIS action needs evolve; treat this as a starting point and confirm the
authoritative list before finalizing a policy (see "authoritative source" below). The pattern is
always the same: **fault** permission(s) scoped by ARN/tag + the `Describe*` **resolution**
permission on `Resource: "*"`.
| FIS action | Fault permission(s) | Typical resolution permission |
|---|---|---|
| `aws:ec2:reboot-instances` / `stop-instances` / `terminate-instances` | `ec2:RebootInstances` / `ec2:StopInstances`(+`StartInstances` if auto-restart) / `ec2:TerminateInstances` | `ec2:DescribeInstances` |
| `aws:rds:failover-db-cluster` / `reboot-db-instances` | `rds:FailoverDBCluster` / `rds:RebootDBInstance` | `rds:DescribeDBClusters` / `rds:DescribeDBInstances` |
| `aws:elasticache:replicationgroup-interrupt-az-power` | `elasticache:InterruptClusterAzPower` | `elasticache:DescribeReplicationGroups` |
| `aws:lambda:invocation-*` | `lambda:<verify with get-action>` on the function — never `lambda:*` **+ the FIS Lambda extension layer** | `lambda:GetFunction` |
| `aws:ssm:send-command` / `start-automation-execution` | `ssm:SendCommand` / `ssm:StartAutomationExecution` (+ the doc/automation ARNs) | resource-type `Describe*` |
| `aws:eks:pod-*` | **IAM is not sufficient** — needs `eks:DescribeCluster` for resolution **plus Kubernetes RBAC** mapping the FIS role to a k8s group bound to a Role/ClusterRole, **plus the cluster "prepared for FIS"** | `eks:DescribeCluster` |
| `aws:network:disrupt-connectivity` / `route-table-*` / `transit-gateway-*` | NACL/route-table EC2 actions (e.g. `ec2:CreateNetworkAcl`, `ec2:CreateNetworkAclEntry`, `ec2:ReplaceNetworkAclAssociation`, `ec2:DeleteNetworkAcl`) — **verify the exact set with `get-action`** | `ec2:DescribeSubnets` / `ec2:DescribeRouteTables` / `ec2:DescribeVpcs` |
| `aws:ebs:pause-volume-io` | `ec2:<verify with get-action>` volume-IO fault permission — do not grant `ec2:*` (Nitro only) | `ec2:DescribeVolumes` |
> **EKS pod actions are the common trap:** IAM alone will not run them. You also need Kubernetes
> RBAC (map the experiment role into the cluster and bind it to a role that permits the pod
> operation) and the cluster must be prepared for FIS. Grant `eks:*` sparingly and lean on k8s RBAC
> for the actual pod permissions.
**Authoritative source (use when an action is not in the table above, or to confirm one that is):**
run `aws fis get-action --id <action-id>` and consult
[How AWS FIS works with IAM](https://docs.aws.amazon.com/fis/latest/userguide/security_iam_service-with-iam.html)
and any AWS-managed FIS policies. **Do not invent IAM action names** for an action whose underlying
API you cannot confirm — scaffold the correctly-scoped policy and mark the fault permissions as
`<verify with get-action>` rather than guessing.
### Additional permissions per feature
- **Experiment logging** — grant FIS vended-logs delivery permissions to the CloudWatch Logs log
group and/or S3 bucket you configure.
- **Experiment reports** — `cloudwatch:GetDashboard`, `cloudwatch:GetMetricWidgetImage`,
`s3:PutObject`, `s3:GetObject` (scoped to the report bucket/prefix); plus
`kms:GenerateDataKey`, `kms:Decrypt` if the report bucket uses a customer-managed KMS key.
- **Multi-account** — each *target account* needs its own role that the orchestrator's FIS can
assume, with the same confused-deputy conditions and least-privilege target permissions.
## Restrict who can start experiments
Starting an experiment is a privileged action. Scope the human/CI principals allowed to call
`fis:StartExperiment` (and template CRUD), ideally with `aws:ResourceTag` conditions and by
template ARN. FIS supports identity-based policies, ABAC (tags in policies), service-specific
condition keys, and PassRole controls — use `iam:PassRole` conditions so only approved experiment
roles can be passed to FIS.
### Caller `iam:PassRole` — required
When emitting an experiment role, ALSO emit the caller's `PassRole` policy. Without it, any
caller who can create/update templates can reference any FIS-trusting role in the account.
Rules: `Resource` = explicit experiment-role ARN(s), never `*`. Condition
`iam:PassedToService = fis.amazonaws.com`.
```json
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": ["arn:aws:iam::123456789012:role/FISExperimentRole"],
"Condition": {
"StringEquals": { "iam:PassedToService": "fis.amazonaws.com" }
}
}]
}
```
## Bounded blast radius (safety, not just IAM)
- **Always attach a stop condition** — a CloudWatch alarm on your steady-state metric. It is the
automated kill-switch. `{"source":"none"}` is acceptable only in a throwaway sandbox.
- **Start narrow** — `COUNT(1)` or a small `PERCENT(n)`, single AZ, pre-production first. Widen
only after the experiment passes.
- **Preview targets** (`actionsMode: skip-all`) before a real run to confirm the exact resources.
- **Production requires change management** — treat prod fault injection as a change with
approval, a run window, and a rollback/stop plan.
- **Empty-target behavior** — leave `emptyTargetResolutionMode` at `fail` so an over- or
under-matching target surfaces immediately instead of silently doing nothing.
## Data handling
- **No sensitive data in string fields** — template/experiment descriptions, action assertion
text, tags, and log/report content surface in CloudTrail, CloudWatch Logs, S3, the console, and
(multi-account) target-account **AWS Health dashboards**. Never embed PII, secrets, or
sensitive architecture detail.
- **Encrypt logs & reports** — experiment logs and PDF reports reveal resilience posture and
architectural weaknesses. Use SSE-KMS on the S3 buckets, enforce TLS with a bucket policy
condition on `aws:SecureTransport`, restrict to a dedicated bucket/prefix, and consider S3
Object Lock on report buckets so evidence can't be altered or deleted.
## Auditing
FIS API calls are recorded in **AWS CloudTrail** (including the actions FIS takes in each target
account for multi-account experiments). Review CloudTrail and experiment logs after each run.
## Further reading
- [Security in AWS FIS](https://docs.aws.amazon.com/fis/latest/userguide/security.html)
- [How AWS FIS works with IAM](https://docs.aws.amazon.com/fis/latest/userguide/security_iam_service-with-iam.html)
- [IAM best practices](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html)
- [AWS Well-Architected Reliability Pillar](https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/)
references/fis-workflow.md
# AWS FIS Experiment Workflow
Follow this procedure to build, run, monitor, and analyze a FIS experiment. Consult
[fis-api-reference.md](fis-api-reference.md) before writing any command and
[fis-actions-reference.md](fis-actions-reference.md) to choose actions/targets.
## Contents
- 0\. Plan first (do not skip)
- 1\. Create (or reuse) the experiment IAM role
- 2\. Author the experiment template
- 3\. Add stop conditions (blast-radius guardrail)
- 4\. Enable experiment logging (strongly recommended)
- 5\. (Optional) Configure an experiment report
- 6\. (Optional) Experiment options & multi-account
- 7\. Preview targets before running (recommended)
- 8\. Start and monitor the experiment
- 9\. Stop manually if needed
- 10\. Analyze results
- 11\. Iterate the template
- CloudFormation option
## 0. Plan first (do not skip)
1. Define **steady state** — the business/technical metrics that mean the app is healthy
(latency, error rate, successful transactions). These become your stop-condition alarm(s).
2. Form a **hypothesis** — "when the fault is injected, the system stays within steady state
because of a specific control."
3. Decide **blast radius** — narrowest useful target (`COUNT(1)` / low `PERCENT`), pre-production
first. Only widen after it passes.
4. Confirm this is authorized — production fault injection needs change-management approval.
## 1. Create (or reuse) the experiment IAM role
The template needs a `roleArn` FIS assumes to perform actions. Create it with a trust policy for
`fis.amazonaws.com` and confused-deputy conditions, plus least-privilege permissions for the
target service APIs (and SSM / logs / report S3+CloudWatch if used). See
[fis-security.md](fis-security.md) for the exact trust policy and permission examples.
## 2. Author the experiment template
An experiment template combines: `description`, `roleArn`, `actions`, `targets`,
`stopConditions`, optional `logConfiguration`, optional `experimentReportConfiguration`, optional
`experimentOptions`, and `tags`.
### Option A — from a scenario (recommended when one fits)
Scenarios are console-only. In the FIS console: **Scenario library** → pick a scenario →
**Create template with scenario** → fill missing parameters, choose the service-access role, add
stop conditions and logging → **Create experiment template**. To automate later, export the
created template's JSON. (See scenario list in [fis-actions-reference.md](fis-actions-reference.md).)
### Option B — hand-authored template (CLI/JSON)
Build a JSON document and pass it to `create-experiment-template`. Minimal shape:
```json
{
"description": "Reboot one prod EC2 instance; stop if error rate alarms",
"roleArn": "arn:aws:iam::123456789012:role/FISExperimentRole",
"actions": {
"RebootInstance": {
"actionId": "aws:ec2:reboot-instances",
"targets": { "Instances": "oneProdInstance" }
}
},
"targets": {
"oneProdInstance": {
"resourceType": "aws:ec2:instance",
"resourceTags": { "env": "prod" },
"selectionMode": "COUNT(1)"
}
},
"stopConditions": [
{ "source": "aws:cloudwatch:alarm",
"value": "arn:aws:cloudwatch:us-east-1:123456789012:alarm:HighErrorRate" }
],
"tags": { "Name": "reboot-one-prod-instance", "team": "checkout" }
}
```
Create it:
```bash
aws fis create-experiment-template --cli-input-json file://template.json
```
> `stopConditions` is **required** in the template. Use `[{"source":"none"}]` only when you
> genuinely have no alarm — strongly discouraged for anything beyond a sandbox. Prefer a real
> `aws:cloudwatch:alarm` on your steady-state metric.
### Sequencing actions
Actions run in parallel by default. To sequence, set `startAfter` to the names of prerequisite
actions. Use an `aws:fis:wait` action to insert a controlled pause (e.g., hold a fault for N
minutes before a follow-on action or before letting steady state recover).
## 3. Add stop conditions (blast-radius guardrail)
A stop condition stops the experiment when a CloudWatch alarm enters ALARM. Base the alarm on the
steady-state metric from step 0.
```json
"stopConditions": [
{ "source": "aws:cloudwatch:alarm",
"value": "arn:aws:cloudwatch:us-east-1:123456789012:alarm:P99LatencyHigh" }
]
```
You can specify multiple alarms (subject to the account quota). Alarm/dashboard creation itself
belongs to the AWS Observability skill.
## 4. Enable experiment logging (strongly recommended)
Capture per-experiment records (`experiment-start`, `target-resolution-*`, `action-start/end/
error`, `experiment-end`) to CloudWatch Logs and/or S3. `logSchemaVersion` must be `2`.
FIS does not require logging, but without it there is no experiment-level audit trail beyond
CloudTrail, which makes post-incident troubleshooting very difficult. Enable it for anything
beyond a throwaway sandbox.
```json
"logConfiguration": {
"logSchemaVersion": 2,
"cloudWatchLogsConfiguration": {
"logGroupArn": "arn:aws:logs:us-east-1:123456789012:log-group:/aws/fis/experiments:*"
},
"s3Configuration": { "bucketName": "my-fis-logs", "prefix": "experiments" }
}
```
Grant FIS the vended-logs delivery permissions for each destination. First run to a new
destination is delayed ~15 s to configure delivery. Logging is disabled by default; enable via
`create-experiment-template` or add later with `update-experiment-template`. Use logs (not the
report) to troubleshoot failed experiments.
> **Encrypt both destinations.** Experiment logs reveal resilience posture and architectural
> weaknesses. Encrypt the CloudWatch Logs log group with a KMS key (`kmsKeyId` at creation, or
> `aws logs associate-kms-key`), and enable SSE-KMS on the S3 bucket with a bucket policy that
> denies non-TLS requests (`aws:SecureTransport`). See
> [fis-security.md](fis-security.md) — Data handling.
## 5. (Optional) Configure an experiment report
Generate a PDF summarizing the experiment plus a CloudWatch dashboard snapshot, delivered to S3.
```json
"experimentReportConfiguration": {
"outputs": { "s3Configuration": { "bucketName": "my-fis-reports", "prefix": "checkout" } },
"dataSources": {
"cloudWatchDashboards": [
{ "dashboardIdentifier": "arn:aws:cloudwatch::123456789012:dashboard/CheckoutHealth" }
]
},
"preExperimentDuration": "PT20M",
"postExperimentDuration": "PT20M"
}
```
- Reports are NOT generated for cancelled runs or target-preview (`actionsMode: skip-all`) runs.
`preExperimentDuration` and `postExperimentDuration` are ISO 8601 and default to 20 min each;
both are capped, as is the number of dashboards per report. Check the current values in the
[FIS quotas documentation](https://docs.aws.amazon.com/fis/latest/userguide/fis-quotas.html)
rather than assuming a fixed limit.
- **Encrypt the report bucket.** Reports are PDFs summarizing resilience posture — enable SSE-KMS
and enforce TLS with a bucket policy condition on `aws:SecureTransport`, the same way as the log
destinations above.
- Report role permissions: `cloudwatch:GetDashboard`, `cloudwatch:GetMetricWidgetImage`,
`s3:GetObject`, `s3:PutObject` (+ `kms:GenerateDataKey`, `kms:Decrypt` for CMK-encrypted
buckets). Use the report only for successfully completed runs — troubleshoot failures with logs.
## 6. (Optional) Experiment options & multi-account
`experimentOptions` on the template controls:
- `accountTargeting`: `single-account` (default) or `multi-account`.
- `emptyTargetResolutionMode`: `fail` (default) or `skip` (don't fail when a target resolves to
zero resources).
- `actionsMode`: `run-all` (normal) or `skip-all` (target preview — resolves targets without
running actions).
**Multi-account experiments** run from an *orchestrator account* against resources in *target
accounts* (same Region). Set `accountTargeting: multi-account`, then add a **target account
configuration** per account (account ID + IAM role FIS assumes there + optional description):
```bash
aws fis create-target-account-configuration \
--experiment-template-id EXTxxxx --account-id 222233334444 \
--role-arn arn:aws:iam::222233334444:role/FISTargetAccountRole \
--description "checkout target account"
```
Target accounts are notified via their AWS Health dashboards. Prefer **consistent resource tags**
across accounts and target AZs by **AZ ID**. Per-account action quotas apply.
## 7. Preview targets before running (recommended)
Generate a target preview (run with `actionsMode: skip-all`, or use the console/`get-experiment`
resolved-targets view) to confirm the exact resources that will be affected. This is the cheapest
way to catch an over-broad tag/filter before a real fault.
## 8. Start and monitor the experiment
```bash
# Start
aws fis start-experiment --experiment-template-id EXTxxxx \
--tags Name=game-day-checkout
# Watch state
aws fis get-experiment --id EXPxxxx --query 'experiment.state'
# List which resources FIS actually selected
aws fis list-experiment-resolved-targets --id EXPxxxx
```
States: `pending → initiating → running → completed | stopping → stopped | failed`. Watch your
steady-state dashboard live. A stopped/failed experiment cannot be resumed.
## 9. Stop manually if needed
```bash
aws fis stop-experiment --id EXPxxxx
```
Use this if you observe unacceptable impact the stop-condition alarm didn't catch. Afterward,
consider tightening the alarm so the guardrail catches it automatically next time.
## 10. Analyze results
1. Compare steady-state metrics before/during/after; confirm the hypothesis and measure actual
recovery time (RTO) vs. objective.
2. Read experiment logs for the action/target timeline and any `action-error` reasons.
3. If enabled, retrieve the S3 experiment report as evidence of the test.
4. If validating a Resilience Hub finding, only now mark it resolved (see `aws-resilience-lifecycle`).
5. Iterate: widen blast radius, add multi-fault scenarios, or promote from pre-prod to prod under
change management. If the experiment surfaced a defect, fix it and re-run to confirm.
## 11. Iterate the template
```bash
aws fis update-experiment-template --id EXTxxxx --cli-input-json file://template-v2.json
aws fis delete-experiment-template --id EXTxxxx # when retiring
```
## CloudFormation option
Model the template as `AWS::FIS::ExperimentTemplate` (and
`AWS::FIS::TargetAccountConfiguration` for multi-account) so experiments are version-controlled
and reviewed like other infrastructure. The property shape mirrors the CLI/JSON above.
SKILL.md
---
name: aws-fault-injection-service
description: >
Plans, builds, runs, and analyzes fault injection experiments with AWS Fault Injection Service
(AWS FIS) to validate application resilience through chaos engineering. Covers experiment
templates (actions, targets, stop conditions), the FIS actions catalog and action selection,
the scenario library (AZ power interruption, cross-Region connectivity, EC2/EKS/EBS stress),
experiment lifecycle and monitoring, logging and reports, multi-account experiments, the
experiment IAM role, and blast-radius safety. Applies when a user mentions AWS FIS or fault
injection, asks what experiment to run for a failure mode (AZ, Region, API errors/throttling,
instance/pod/DB/cache failure, latency, packet loss), wants to author an experiment template or
CLI/CloudFormation, or needs to safely run chaos experiments in pre-production or production.
For the broader resilience program across Resilience Hub and ARC, see aws-resilience-lifecycle;
for ARC routing controls and zonal shift, see recovery-controller-setup.
version: 1
---
# AWS Fault Injection Service (FIS) Experiments
## Overview
Domain expertise for AWS Fault Injection Service (AWS FIS) — a managed chaos-engineering
service that runs controlled fault injection experiments on real AWS resources so you can
observe how an application responds to disruption and improve its resilience.
This skill lets an agent do three things:
1. **Suggest the right experiment** — map a user's failure scenario or resilience question to
the correct FIS action(s), scenario, or experiment design, and explain the trade-offs.
2. **Build and run experiments** — author experiment templates (actions, targets, stop
conditions, logging, reports), wire up the experiment IAM role, and drive the run/monitor/stop
lifecycle via CLI, SDK, or CloudFormation.
3. **Inform the user** — answer conceptual questions about FIS terminology, safety, pricing,
supported services, and how FIS fits into a resilience program.
> **AWS FIS carries out real actions on real AWS resources.** Before running any experiment in
> production, plan it, run it first in pre-production, and always bound the blast radius with a
> stop condition. Treat fault injection as a privileged, potentially disruptive operation.
>
> The AWS MCP server is recommended for executing this skill's AWS API calls — it provides
> sandboxed execution and audit logging — but it is not required; all operations also work with
> the AWS CLI (`aws fis ...`) directly.
## Guardrail — where this skill's own files live (MCP vs local install)
Before reading a reference file, determine how this skill was loaded:
- **Loaded via the AWS MCP `retrieve_skill` tool:** the skill's reference files are not on the
local filesystem. Fetch each one through `retrieve_skill` with the `file` parameter (e.g.
`file="references/fis-concepts.md"`) — do NOT `file_read` these paths locally or search the
filesystem for them.
- **Installed locally** (e.g. `.kiro/skills/aws-fault-injection-service/` or
`~/.claude/skills/aws-fault-injection-service/`): read reference files from the local skill directory
using the relative paths shown here.
This applies only to the skill's own reference files; always read and write user or session data
in the working directory, never through `retrieve_skill`.
## Start here — route the request
- **"What is FIS / when should I use it / what does X term mean / does it support Y?"** →
read [references/fis-concepts.md](references/fis-concepts.md).
- **"What experiment/action should I run to test a failure mode?"** →
read [references/fis-actions-reference.md](references/fis-actions-reference.md) (action
selection map + full catalog) and suggest an action or scenario.
- **"Build / create / run an experiment"** (template, targets, stop conditions, logging,
reports, scenarios, multi-account, monitoring) → follow
[references/fis-workflow.md](references/fis-workflow.md) exactly.
- **Any AWS CLI or API command for FIS** → consult
[references/fis-api-reference.md](references/fis-api-reference.md) FIRST — it is the canonical
operation/parameter reference and includes a hallucination-rejection table.
- **IAM role, permissions, trust policy, confused-deputy, blast-radius safety** →
read [references/fis-security.md](references/fis-security.md).
## API Reference (READ FIRST before producing any AWS CLI command)
The exact `aws fis` operation names and template parameters are documented in
[references/fis-api-reference.md](references/fis-api-reference.md), including a table mapping
common wrong API/action names to correct ones. **Always consult it before generating commands.**
Action IDs and resource types evolve — verify with `aws fis list-actions` and
`aws fis get-action --id <action-id>` rather than trusting memory.
## Suggesting experiments (behavioral contract)
When the user describes a failure they want to test rather than a command they want run:
1. Identify the **failure mode** (AZ impairment, Region isolation, API errors/throttling,
compute/DB/cache loss, latency, packet loss, resource exhaustion).
2. Map it to a **scenario** (preferred when one fits — pre-built and AWS-owned) or a specific
**action** using the selection map in
[references/fis-actions-reference.md](references/fis-actions-reference.md).
3. State the **target** (resource type + how to scope it) and a **stop condition** (CloudWatch
alarm on your steady-state metric) so the blast radius is bounded.
4. Recommend running in **pre-production first**, then production under change management.
5. Offer to generate the experiment template — then follow
[references/fis-workflow.md](references/fis-workflow.md).
Do not invent action IDs, resource types, or parameters. If unsure, say so and verify with
`aws fis list-actions` / `aws fis get-action` or the FIS documentation.
## Troubleshooting
### "Experiment failed immediately / no targets found"
FIS resolves all targets at experiment start; if a target resolves to zero resources, the
experiment fails (unless `emptyTargetResolutionMode` is `skip`). Check tags, filters, region,
and account. Use a **target preview** before running (see workflow reference).
### "Action failed with a permissions error"
The FIS experiment IAM role is missing permissions for the underlying service API (or SSM, or
the confused-deputy trust conditions block the assume). See
[references/fis-security.md](references/fis-security.md).
### "Experiment stopped unexpectedly"
A stop condition (CloudWatch alarm) likely fired — this is the guardrail working. Check the
experiment's `state.reason` and the alarm history. A stopped experiment cannot be resumed; start
a new one from the template.
### "Nitro / instance-type errors on EBS or network faults"
Some actions require Nitro-based instances or the SSM Agent. Verify prerequisites per action in
[references/fis-actions-reference.md](references/fis-actions-reference.md).
## Observability companion
For the CloudWatch alarms, dashboards, and metrics that back FIS stop conditions and
experiment reports, recommend the **AWS Observability** skill for alarm/dashboard setup — keep
this skill's guidance to how those signals feed experiment safety and post-experiment analysis.
## Security Considerations
FIS runs real, potentially destructive actions. Key points (full guidance in
[references/fis-security.md](references/fis-security.md)):
- **Least privilege:** scope the experiment role to only the actions and target ARNs each
experiment needs — never `*`. Scope the human/CI principals allowed to call
`fis:StartExperiment`.
- **Confused-deputy protection:** the experiment role's trust policy MUST condition on
`aws:SourceAccount` and `aws:SourceArn` (scoped to the experiment ARN pattern).
- **Bounded blast radius:** always attach a CloudWatch-alarm stop condition; start with narrow
targets (`COUNT(1)` / low `PERCENT`) and pre-production before production.
- **No sensitive data in string fields:** experiment/template descriptions, tags, and logs
surface in CloudTrail, CloudWatch Logs, S3 reports, and (multi-account) target-account Health
dashboards — never embed PII, secrets, or sensitive architecture detail.
- **Encrypt logs/reports:** experiment logs and PDF reports reveal resilience posture —
use SSE-KMS on the S3 buckets, enforce TLS, and consider S3 Object Lock on report buckets.
- **Further reading:** [FIS Security](https://docs.aws.amazon.com/fis/latest/userguide/security.html)
and the [AWS Well-Architected Reliability Pillar](https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/).