Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/content/docs/aws/configuration/config/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ Also see [OpenSearch configuration variables](#opensearch) which are used to man
| `KINESIS_SHARD_LIMIT` | `100` (default), `Infinity` (to disable) | Integer value , causing the Kinesis API to start throwing exceptions to mimic the default shard limit. |
| `KINESIS_ON_DEMAND_STREAM_COUNT_LIMIT` | `10` (default), `Infinity` (to disable) | Integer value , causing the Kinesis API to start throwing exceptions to mimic the default on demand stream count limit. |
| `KINESIS_LATENCY` | `500` (default), `0` (to disable)| Integer value of milliseconds, causing the Kinesis API to delay returning a response in order to mimic latency from a live AWS call. |
| `KINESIS_MOCK_PROVIDER_ENGINE` | `node` (default) \| `scala` \| `rust` | String value of `node` (default), `scala`, or `rust` that determines the underlying build of Kinesis Mock. See [Performance Tuning](/aws/services/kinesis#performance-tuning) for guidance on choosing an engine. |
| `KINESIS_MOCK_PROVIDER_ENGINE` | `node` (default) \| `scala` | String value of `node` (default) or `scala` that determines the underlying build of Kinesis Mock. |
| `KINESIS_MOCK_MAXIMUM_HEAP_SIZE` | `512m` (default) | JVM memory format string that sets the maximum memory size for the Kinesis Mock Scala server, corresponds to the JVM `-Xmx` flag. |
| `KINESIS_MOCK_INITIAL_HEAP_SIZE` | `256m` (default) | JVM memory format string that sets the initial memory size for the Kinesis Mock Scala server, corresponds to the JVM `-Xms` flag. |

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ It only includes operations performed with a principal, not as root, so test set
| **Permission Boundaries** | |
| | - Roles |
| | - Users |
| **Service Control Policies (SCPs)** | |
| | - Enforced across the organization hierarchy (root, OU, account) |
| | - Enforced for cross-account access |
| | - Evaluated by the IAM Policy Simulator |

## Supported Policy Features

Expand Down
41 changes: 8 additions & 33 deletions src/content/docs/aws/services/kinesis.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -170,44 +170,21 @@ You can fetch the CloudWatch logs for your Lambda function reading records from

### Performance Tuning

By default, Kinesis Mock runs on the Node.js engine (`KINESIS_MOCK_PROVIDER_ENGINE=node`).
For high-volume workloads, large payloads, or long-running setups, you can switch to a different engine using the `KINESIS_MOCK_PROVIDER_ENGINE` flag.
For high-volume workloads or large payloads, we recommend switching to the Scala engine via the `KINESIS_MOCK_PROVIDER_ENGINE=scala` flag, delivering up to 10x better performance compared to the default Node.js engine.

#### Scala engine

The Scala engine (`KINESIS_MOCK_PROVIDER_ENGINE=scala`) delivers up to 10x better performance compared to the default Node.js engine.
The following parameters can be tuned for the Scala engine:
Additionally, the following parameters can be tuned:

- Increase `KINESIS_MOCK_MAXIMUM_HEAP_SIZE` beyond the default `512m` to reduce JVM memory pressure.
- Increase `KINESIS_MOCK_INITIAL_HEAP_SIZE` beyond the default `256m` to pre-allocate more JVM heap memory.
- Reduce `KINESIS_LATENCY` artificial response delays from the default `500` milliseconds (or disable entirely with `0`).

Refer to our [Kinesis configuration documentation](https://docs.localstack.cloud/references/configuration/#kinesis) for more details on these parameters.

:::note
`KINESIS_MOCK_MAXIMUM_HEAP_SIZE` and `KINESIS_MOCK_INITIAL_HEAP_SIZE` are only applicable when using the Scala engine.
Future versions of LocalStack will likely default to using the `scala` engine over the less-performant `node` version currently in use.
:::

#### Rust engine

The Rust engine (`KINESIS_MOCK_PROVIDER_ENGINE=rust`), introduced in LocalStack 2026.07, is a LocalStack-native rebuild of Kinesis Mock and is the recommended choice for any demanding or long-lived workload.
It provides:

- **Native multi-account and multi-region support** from a single binary, regardless of how many accounts you use — this removes the per-account instance overhead described under [Limitations](#limitations).
- **Faithful enforcement of all AWS API limits**, including per-shard rate ingress/egress limits.
- **An improved persistence model** that replaces the legacy unbounded in-memory queue, allowing the mock to run under sustained load for long periods without the risk of running out of memory.

:::caution
This is the first release of the Rust engine and it should be considered experimental for anyone opting in.

Persistence is **not compatible** between the Rust engine and the Node.js or Scala engines, in either direction.
Any existing Kinesis persistence (including Cloud Pods and state created with the `node` or `scala` engines) will not carry over when you switch to `rust` — and vice versa.
Switching engines effectively starts from a fresh state.
:::

#### All engines

Regardless of the selected engine, you can reduce `KINESIS_LATENCY` artificial response delays from the default `500` milliseconds (or disable them entirely with `0`).

Refer to our [Kinesis configuration documentation](https://docs.localstack.cloud/aws/configuration/config/configuration/#kinesis) for more details on these parameters.

## Resource Browser

The LocalStack Web Application provides a Resource Browser for managing Kinesis Streams & Kafka Clusters.
Expand All @@ -232,10 +209,8 @@ The following code snippets and sample applications provide practical examples o

## Limitations

When using the default Node.js or the Scala engine, each AWS account launches a separate instance of Kinesis Mock in multi-account setups, which is very resource intensive when a large number of AWS accounts are used.
[This Kinesis Mock issue](https://github.com/etspaceman/kinesis-mock/issues/377) is being used to keep track of this feature for the upstream engines.

The [Rust engine](#performance-tuning) (`KINESIS_MOCK_PROVIDER_ENGINE=rust`) is not affected by this limitation, as it natively supports any number of accounts and regions from a single binary.
In multi-account setups, each AWS account launches a separate instance of Kinesis Mock, which is very resource intensive when a large number of AWS accounts are used.
[This Kinesis Mock issue](https://github.com/etspaceman/kinesis-mock/issues/377) is being used to keep track of this feature.

## API Coverage

Expand Down
107 changes: 107 additions & 0 deletions src/content/docs/aws/services/organizations.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,113 @@ To get started, start your LocalStack instance using your preferred method:
awslocal organizations delete-organization
```

## Service Control Policy enforcement

[Service Control Policies (SCPs)](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps.html) set the maximum permissions for accounts in your organization.
When IAM enforcement is enabled, LocalStack checks SCPs together with other applicable policies.
A request goes through only if both the principal's policies, resource's policies and the SCPs covering its account allow the action on the resource.

To turn on SCP enforcement, start LocalStack with [`ENFORCE_IAM=1`](/aws/developer-tools/security-testing/iam-policy-enforcement) and enable the `SERVICE_CONTROL_POLICY` policy type on your organization root (see the [getting started](#getting-started) steps above).

LocalStack evaluates SCPs at each level of the organization hierarchy: root, organizational unit, and account.
An action must be allowed by an SCP at every level between the root and the account.
If any level lacks an `Allow`, the result is an implicit deny, and an explicit `Deny` overrides any `Allow`.

:::note
The organization's management (master) account is exempt from SCPs.
Principals in the management account are never restricted by SCPs, even with an explicit `Deny` SCP attached.
:::

### Cross-account access

LocalStack enforces SCPs for [cross-account access](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic-cross-account.html), where a principal in one account uses a resource owned by another account.

For a cross-account request, LocalStack checks the SCPs of the source account (the account making the request).
A deny in those SCPs blocks the request even when the target resource's policy grants access.

Consider a member account that lists the objects of an S3 bucket in another account of the same organization, with a bucket policy that grants the member account access:

```bash
# Run as the member (source) account
awslocal s3api list-objects-v2 --bucket cross-account-bucket
```

The default `FullAWSAccess` SCP lets the request succeed on the bucket policy.
Attach an SCP that denies `s3:ListBucket` to the member account, and the request fails:

```bash title="Output"
An error occurred (AccessDenied) when calling the ListObjectsV2 operation: User: arn:aws:iam::111111111111:user/test is not authorized to perform: s3:ListBucket on resource: "arn:aws:s3:::cross-account-bucket" with an explicit deny in a service control policy
```

An SCP that allows only unrelated actions (for example, an `ec2:*`-only SCP) produces an implicit deny, since no SCP allows `s3:ListBucket`:

```bash title="Output"
An error occurred (AccessDenied) when calling the ListObjectsV2 operation: User: arn:aws:iam::111111111111:user/test is not authorized to perform: s3:ListBucket on resource: "arn:aws:s3:::cross-account-bucket" because no service control policy allows the s3:ListBucket action
```

The management account stays exempt from SCPs for cross-account requests too.

### Testing SCPs with the IAM Policy Simulator

You can use the [IAM Policy Simulator](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_testing-policies.html) to check whether a principal's request would be allowed or denied without running it against your resources.
LocalStack evaluates SCPs during policy simulation, so you can validate SCP behavior with [`SimulatePrincipalPolicy`](https://docs.aws.amazon.com/IAM/latest/APIReference/API_SimulatePrincipalPolicy.html) before making live requests.

```bash
awslocal iam simulate-principal-policy \
--policy-source-arn arn:aws:iam::111111111111:user/test \
--action-names s3:ListBucket \
--resource-arns arn:aws:s3:::cross-account-bucket
```

When SCPs affect the decision, LocalStack populates the `OrganizationsDecisionDetail` field of the [`EvaluationResult`](https://docs.aws.amazon.com/IAM/latest/APIReference/API_EvaluationResult.html), so you can see whether an SCP allowed the action.

:::note
LocalStack's Policy Simulator and its IAM enforcement engine share the same underlying evaluation logic.
As a result, the simulator reflects the real AWS IAM behavior rather than the behavior of the AWS Policy Simulator, which differs in a few ways:

- AWS ignores SCPs that contain conditions during simulation. LocalStack evaluates SCPs with conditions.
- AWS applies SCPs to the organization's management account during simulation. LocalStack does not apply SCPs to the management account, matching the real behavior of AWS Organizations.
- AWS reports an explicit `Deny` from an SCP as an implicit deny. LocalStack reports it as an explicit deny, which is the expected outcome.
:::

## Service Control Policy validation

When you create or update a Service Control Policy (SCP) with `CreatePolicy` or `UpdatePolicy`, LocalStack validates the policy document against the syntax rules that SCPs must follow.
A policy that violates any of these rules is rejected with a `MalformedPolicyDocumentException` or a `ConstraintViolationException`, matching the behavior you would see on AWS.

The following constraints are enforced for SCPs:

- **No `Principal` or `NotPrincipal` elements**: unlike identity-based or resource-based IAM policies, SCPs cannot specify a `Principal` or `NotPrincipal` key inside a `Statement`. A policy that includes either key is rejected with a `MalformedPolicyDocumentException`.
- **Maximum policy size of 10,240 characters**: a policy document larger than 10,240 characters is rejected with a `ConstraintViolationException` (reason `POLICY_CONTENT_LIMIT_EXCEEDED`). This matches the limit enforced by AWS in practice.
- **A single policy object**: the document must be a single JSON object. Passing a JSON array of policy objects is rejected.
- **A single `Statement` key**: the document may contain only one `Statement` key. Duplicate `Statement` keys (or any other duplicate keys) cause the policy to be rejected as malformed.
- **Resources must be present**: each statement must contain a `Resource` element. Specific resource ARNs (not just the `*` wildcard) are accepted.

:::note
The AWS documentation states that the [maximum SCP size is 5,120 characters](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_reference_limits.html) and that SCPs [only support the `*` wildcard for resources](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps_syntax.html#scp-syntax-resource).
LocalStack instead mirrors the behavior observed against real AWS: the enforced size limit is 10,240 characters, and specific resource ARNs are accepted.
:::

For example, the following policy is rejected because it includes a `Principal` element, which is not permitted in an SCP:

```bash
awslocal organizations create-policy \
--name "InvalidSCP" \
--description "SCP with a Principal element" \
--type SERVICE_CONTROL_POLICY \
--content '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": "*"
}
]
}'
```

## API Coverage

<FeatureCoverage service="organizations" client:load />
Loading