IAM
Protocol: Query (XML) — POST http://localhost:4566/ with Action= parameter
Supported Actions
Users
| Action | Description |
|---|---|
| CreateUser | Creates an IAM user in the local account. |
| GetUser | Returns a stored IAM user. |
| DeleteUser | Deletes an IAM user from the local IAM store. |
| ListUsers | Lists IAM users in the local account. |
| UpdateUser | Updates mutable IAM user fields. |
| TagUser | Adds tags to an IAM user. |
| UntagUser | Removes tags from an IAM user. |
| ListUserTags | Lists tags stored for an IAM user. |
Groups
| Action | Description |
|---|---|
| CreateGroup | Creates an IAM group. |
| GetGroup | Returns an IAM group and its users. |
| DeleteGroup | Deletes an IAM group from the local IAM store. |
| ListGroups | Lists IAM groups in the local account. |
| AddUserToGroup | Adds a user to an IAM group. |
| RemoveUserFromGroup | Removes a user from an IAM group. |
| ListGroupsForUser | Lists groups that contain a user. |
Roles
| Action | Description |
|---|---|
| CreateRole | Creates an IAM role with an assume-role policy. |
| GetRole | Returns a stored IAM role. |
| DeleteRole | Deletes an IAM role from the local IAM store. |
| ListRoles | Lists IAM roles in the local account. |
| UpdateRole | Updates mutable IAM role fields. |
| CreateServiceLinkedRole | Creates a role under /aws-service-role/ for a service principal. |
| DeleteServiceLinkedRole | Deletes a service-linked role and returns a deletion task id. |
| GetServiceLinkedRoleDeletionStatus | Returns the status of a service-linked role deletion. |
| UpdateAssumeRolePolicy | Replaces a role's assume-role policy document. |
| TagRole | Adds tags to an IAM role. |
| UntagRole | Removes tags from an IAM role. |
| ListRoleTags | Lists tags stored for an IAM role. |
Policies
| Action | Description |
|---|---|
| CreatePolicy | Creates a customer-managed IAM policy. |
| GetPolicy | Returns metadata for a managed IAM policy. |
| DeletePolicy | Deletes a managed IAM policy. |
| ListPolicies | Lists managed IAM policies, including seeded AWS managed policies. |
| ListEntitiesForPolicy | Lists roles, users, and groups with a direct managed-policy attachment. |
| CreatePolicyVersion | Creates a new version of a managed policy. |
| GetPolicyVersion | Returns a managed policy version document. |
| DeletePolicyVersion | Deletes a non-default managed policy version. |
| ListPolicyVersions | Lists versions for a managed policy. |
| SetDefaultPolicyVersion | Sets the default version for a managed policy. |
| TagPolicy | Adds tags to a managed policy. |
| UntagPolicy | Removes tags from a managed policy. |
| ListPolicyTags | Lists tags stored for a managed policy. |
ListEntitiesForPolicy currently returns direct permissions-policy attachments. EntityFilter,
PathPrefix, PolicyUsageFilter, and pagination are not yet applied; responses return
IsTruncated=false.
Permission Boundaries
| Action | Description |
|---|---|
| PutUserPermissionsBoundary | Sets a managed policy as a user's permissions boundary. |
| DeleteUserPermissionsBoundary | Removes a user's permissions boundary. |
| PutRolePermissionsBoundary | Sets a managed policy as a role's permissions boundary. |
| DeleteRolePermissionsBoundary | Removes a role's permissions boundary. |
Policy Attachments
| Action | Description |
|---|---|
| AttachUserPolicy | Attaches a managed policy to a user. |
| DetachUserPolicy | Detaches a managed policy from a user. |
| ListAttachedUserPolicies | Lists managed policies attached to a user. |
| AttachGroupPolicy | Attaches a managed policy to a group. |
| DetachGroupPolicy | Detaches a managed policy from a group. |
| ListAttachedGroupPolicies | Lists managed policies attached to a group. |
| AttachRolePolicy | Attaches a managed policy to a role. |
| DetachRolePolicy | Detaches a managed policy from a role. |
| ListAttachedRolePolicies | Lists managed policies attached to a role. |
Inline Policies
| Action | Description |
|---|---|
| PutUserPolicy | Stores or replaces an inline policy on a user. |
| GetUserPolicy | Returns an inline policy stored on a user. |
| DeleteUserPolicy | Deletes an inline policy from a user. |
| ListUserPolicies | Lists inline policy names stored on a user. |
| PutGroupPolicy | Stores or replaces an inline policy on a group. |
| GetGroupPolicy | Returns an inline policy stored on a group. |
| DeleteGroupPolicy | Deletes an inline policy from a group. |
| ListGroupPolicies | Lists inline policy names stored on a group. |
| PutRolePolicy | Stores or replaces an inline policy on a role. |
| GetRolePolicy | Returns an inline policy stored on a role. |
| DeleteRolePolicy | Deletes an inline policy from a role. |
| ListRolePolicies | Lists inline policy names stored on a role. |
Instance Profiles
| Action | Description |
|---|---|
| CreateInstanceProfile | Creates an IAM instance profile. |
| GetInstanceProfile | Returns an instance profile and its roles. |
| DeleteInstanceProfile | Deletes an instance profile from the local IAM store. |
| ListInstanceProfiles | Lists IAM instance profiles. |
| AddRoleToInstanceProfile | Adds a role to an instance profile. |
| RemoveRoleFromInstanceProfile | Removes a role from an instance profile. |
| ListInstanceProfilesForRole | Lists instance profiles associated with a role. |
Access Keys
| Action | Description |
|---|---|
| CreateAccessKey | Creates access-key credentials for a user. |
| GetAccessKeyLastUsed | Returns the stored last-used metadata for an access key. |
| ListAccessKeys | Lists access keys for a user. |
| UpdateAccessKey | Updates an access key's status. |
| DeleteAccessKey | Deletes an access key from a user. |
Account Aliases
| Action | Description |
|---|---|
| ListAccountAliases | Lists the alias set for the account, or an empty list when none is set. |
| CreateAccountAlias | Sets the account alias. An account can hold only one. |
| DeleteAccountAlias | Removes the account alias. |
An account holds one alias, and AWS enforces that by replacement rather than rejection:
CreateAccountAlias with a new value silently swaps the current one. EntityAlreadyExists means
the requested name is taken — on AWS that includes names held by other accounts, since aliases are
globally unique, but the store here is per-account so only "you already hold this one" arises.
DeleteAccountAlias must name the current alias; a mismatch returns NoSuchEntity. Both verbs
apply the same pattern constraint, so a malformed value returns ValidationError on either.
Aliases are 3–63 characters of lowercase letters, digits and hyphens, may not start or end with a
hyphen, and may not contain two hyphens in a row — AWS's documented
^[a-z0-9]([a-z0-9]|-(?!-)){1,61}[a-z0-9]$. The ValidationError message is reproduced from AWS
verbatim and does not itself mention the consecutive-hyphen rule.
Set FLOCI_SERVICES_IAM_ACCOUNT_ALIAS to seed an alias at startup, for callers that expect to
read one without creating it first. It seeds the default account only, so a caller signing
with a credential that resolves to a different account still reads an empty list. Seeding is
skipped when an alias is already stored, so under storage.mode: persistent a changed value has
no effect on later starts — the skip is logged at debug with both values. /_floci/state/reset
clears the alias without re-seeding it, as it does the optional deployer principal; the seed
returns on restart.
OIDC Identity Providers
| Action | Description |
|---|---|
| CreateOpenIDConnectProvider | Creates an OIDC identity provider from an https URL. |
| GetOpenIDConnectProvider | Returns a provider's URL, client IDs, thumbprints and tags. |
| ListOpenIDConnectProviders | Lists the ARNs of stored OIDC providers. |
| DeleteOpenIDConnectProvider | Deletes an OIDC identity provider. |
| AddClientIDToOpenIDConnectProvider | Adds a client ID (audience) to a provider. |
| RemoveClientIDFromOpenIDConnectProvider | Removes a client ID from a provider. |
| UpdateOpenIDConnectProviderThumbprint | Replaces a provider's thumbprint list. |
| TagOpenIDConnectProvider | Adds tags to a provider. |
| UntagOpenIDConnectProvider | Removes tags from a provider. |
| ListOpenIDConnectProviderTags | Lists tags stored for a provider. |
A provider is identified by its URL, so the ARN is derived from it rather than from a generated
id: https://oidc.eks.eu-central-1.amazonaws.com/id/EXAMPLE becomes
arn:aws:iam::<account>:oidc-provider/oidc.eks.eu-central-1.amazonaws.com/id/EXAMPLE. Creating
the same URL twice returns EntityAlreadyExists. As on AWS, GetOpenIDConnectProvider reports
the URL without its scheme.
The URL must begin with https:// and is at most 255 characters. It is not normalized, matching
AWS: a trailing slash or a difference in case produces a separate provider rather than a
duplicate.
A provider holds at most 100 client IDs (LimitExceeded beyond that) and 5 thumbprints
(InvalidInput beyond that). Adding a client ID that is already present, and removing one that
was never added, both succeed and change nothing, as they do on AWS.
Thumbprints are stored and echoed back but never validated against the remote endpoint, since nothing here performs the TLS handshake they describe.
Login Profiles
| Action | Description |
|---|---|
| CreateLoginProfile | Creates a password login profile for a user. |
| DeleteLoginProfile | Deletes a user's login profile. |
| UpdateLoginProfile | Updates a user's login profile password settings. |
Policy Simulation
| Action | Description |
|---|---|
| SimulatePrincipalPolicy | Evaluates requested actions and resources against the resolved principal's policies. |
Account
| Action | Description |
|---|---|
| GetAccountSummary | Returns entity counts (users, groups, roles, customer-managed policies, instance profiles) and IAM quota values. Resources Floci does not track (MFA devices, SAML/OIDC providers, server certificates) are reported as zero rather than omitted. |
AWS Managed Policies
Floci seeds a catalog of commonly-used AWS managed policies at startup. These are attachable immediately without any setup:
General access
AdministratorAccess · PowerUserAccess · ReadOnlyAccess · IAMFullAccess · AmazonS3FullAccess · AmazonS3ReadOnlyAccess · AmazonDynamoDBFullAccess · AmazonEC2FullAccess · AmazonSQSFullAccess · AmazonSNSFullAccess · AmazonVPCFullAccess · CloudWatchFullAccess · AWSLambdaFullAccess
Lambda execution roles (arn:aws:iam::aws:policy/service-role/...)
AWSLambdaBasicExecutionRole · AWSLambdaBasicDurableExecutionRolePolicy · AWSLambdaDynamoDBExecutionRole · AWSLambdaKinesisExecutionRole · AWSLambdaMSKExecutionRole · AWSLambdaSQSQueueExecutionRole · AWSLambdaVPCAccessExecutionRole
ECS / EKS execution roles
AmazonECSTaskExecutionRolePolicy · AmazonEKSFargatePodExecutionRolePolicy
EKS cluster & node groups
AmazonEKSClusterPolicy · AmazonEKSServicePolicy · AmazonEKSVPCResourceController · AmazonEKSWorkerNodePolicy · AmazonEKS_CNI_Policy
Other execution roles
AmazonS3ObjectLambdaExecutionRolePolicy · CloudWatchLambdaInsightsExecutionRolePolicy · CloudWatchLambdaApplicationSignalsExecutionRolePolicy · AWSConfigRulesExecutionRole · AWSMSKReplicatorExecutionRole · AWS-SSM-DiagnosisAutomation-ExecutionRolePolicy · AWS-SSM-RemediationAutomation-ExecutionRolePolicy · AmazonSageMakerGeospatialExecutionRole · AmazonSageMakerCanvasEMRServerlessExecutionRolePolicy · SageMakerStudioBedrockFunctionExecutionRolePolicy · SageMakerStudioDomainExecutionRolePolicy · SageMakerStudioQueryExecutionRolePolicy · AmazonDataZoneDomainExecutionRolePolicy · AmazonBedrockAgentCoreMemoryBedrockModelInferenceExecutionRolePolicy · AWSPartnerCentralSellingResourceSnapshotJobExecutionRolePolicy
All seeded policies use a permissive wildcard document since Floci does not enforce IAM policy evaluation by default.
Optional Local Deployer Principal
Floci can seed a local IAM user for development workflows that expect a concrete caller identity before provisioning starts. This is disabled by default.
Enable it with:
When enabled, Floci creates the floci-deployer user if it does not already exist, attaches arn:aws:iam::aws:policy/AdministratorAccess, and creates static floci / floci access-key credentials if that access key does not already exist. Existing users and access keys are preserved.
Requests signed with the seeded access key return the deployer user ARN from sts:GetCallerIdentity.
IAM Enforcement Mode
By default Floci accepts any credentials without enforcing IAM policies — all requests are allowed through regardless of what policies are attached to the calling identity. This preserves backward compatibility and keeps the default setup frictionless.
Setting enforcement-enabled: true activates the policy evaluator as a JAX-RS request filter. Every inbound request is then evaluated against the identity-based policies of the calling IAM user or assumed role before it reaches the service handler.
Enable enforcement
Environment variable:
Docker Compose:
Evaluation rules
Policy evaluation follows the standard AWS precedence:
- An explicit Deny in any identity, session, or boundary policy → request is denied (HTTP 403
AccessDeniedException) - An explicit Allow in an identity policy creates the base grant
- If a session policy is present, it must also explicitly allow the request
- If a permission boundary is present, it must also explicitly allow the request
- No matching effective allow → implicit deny (HTTP 403)
Bypass rules
These identities always bypass enforcement (backward-compatible defaults):
| Identity | Behaviour |
|---|---|
Access key test (the default dev credential) |
Always allowed — no policy lookup |
| Unknown access key (not in IAM store) | Always allowed — backward-compatible with pre-existing keys |
No Authorization header |
Allowed — unauthenticated path (e.g. health checks) |
| Unresolvable IAM action for the request | Allowed — unknown mappings are permissive |
Supported policy features
- Identity-based policies: inline user/group/role policies and managed attached policies.
- Session policies: inline policies passed during
sts:AssumeRole. - Permission boundaries: managed policies used to cap maximum permissions.
- Action/Resource patterns: literal matches, wildcards (
*,?), andNotAction/NotResourceblocks. - Conditions: support for
Conditionblocks with multiple operators. - Effects:
AllowandDeny.
Supported Condition Operators:
StringEquals,StringNotEquals,StringEqualsIgnoreCase,StringNotEqualsIgnoreCaseStringLike,StringNotLikeArnEquals,ArnLike,ArnNotEquals,ArnNotLikeNumericEquals,NumericNotEquals,NumericLessThan,NumericGreaterThan(and Equals variants)DateEquals,DateNotEquals,DateLessThan,DateGreaterThan(and Equals variants)Bool,IpAddress,NotIpAddress,Null- Supports
...IfExistsvariants for all operators.
Not yet supported: NotPrincipal, resource-based policies (S3 bucket policy, Lambda resource policy).
Assumed roles
When a caller uses sts:AssumeRole the returned session credentials are registered internally. Subsequent requests signed with those session credentials are evaluated against:
1. The role's attached and inline policies.
2. The session policy (if provided during AssumeRole), acting as an intersection filter.
Example — minimal enforcement setup
export AWS_ENDPOINT_URL=http://localhost:4566
# Create a user and get credentials
aws iam create-user --user-name alice
KEY=$(aws iam create-access-key --user-name alice --query 'AccessKey.[AccessKeyId,SecretAccessKey]' --output text)
AKID=$(echo $KEY | awk '{print $1}')
SECRET=$(echo $KEY | awk '{print $2}')
# Create and attach a policy that allows S3 list
POLICY_ARN=$(aws iam create-policy \
--policy-name allow-s3-list \
--policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":"s3:ListAllMyBuckets","Resource":"*"}]}' \
--query 'Policy.Arn' --output text)
aws iam attach-user-policy --user-name alice --policy-arn $POLICY_ARN
# alice can now list buckets
AWS_ACCESS_KEY_ID=$AKID AWS_SECRET_ACCESS_KEY=$SECRET \
aws s3 ls
Service-linked roles
CreateServiceLinkedRole puts a role under /aws-service-role/<principal>/ and marks it as
service-linked. As on AWS, a role carrying that mark is protected: AttachRolePolicy,
DetachRolePolicy, PutRolePolicy, DeleteRolePolicy, PutRolePermissionsBoundary,
DeleteRolePermissionsBoundary, UpdateRole, UpdateAssumeRolePolicy, AddRoleToInstanceProfile,
RemoveRoleFromInstanceProfile and DeleteRole all answer UnmodifiableEntity and name the
linked service to go through instead. TagRole and UntagRole are allowed, as on AWS. Within the
IAM API DeleteServiceLinkedRole is the only way to remove such a role — the emulator's own
/_floci/state/reset still clears it along with everything else.
Three deviations to be aware of:
- The role name is derived locally and will not match AWS for most services. AWS lets each
linked service choose the name, and it is not computable from the service principal —
lex.amazonaws.comyieldsAWSServiceRoleForLexBotsthere, where Floci derivesAWSServiceRoleForLex. Read the name back from the create response rather than hardcoding it, and do not rely on a name observed locally matching the one AWS mints. - Deletion is synchronous.
DeleteServiceLinkedRolecompletes before it returns, so the task id it hands back is already finished andGetServiceLinkedRoleDeletionStatusalways reportsSUCCEEDED. TheIN_PROGRESS,NOT_STARTEDandFAILEDstates never occur, and no failureReasonis ever returned — a poll loop works, but its failure branch is never taken. CreateRoleaccepts the/aws-service-role/path, which AWS reserves. AWS rejects that prefix onCreateRole; Floci allows it and treats the result as an ordinary role, since the service-linked mark comes from the action that minted the role rather than from its path. Such a role stays fully modifiable, andDeleteServiceLinkedRoleanswersNoSuchEntityfor it.
Configuration
| Variable | Default | Description |
|---|---|---|
FLOCI_SERVICES_IAM_ENABLED |
true |
Enable or disable the service |
FLOCI_SERVICES_IAM_ENFORCEMENT_ENABLED |
false |
Enforce IAM policies on all inbound requests |
FLOCI_SERVICES_IAM_SEED_DEPLOYER_PRINCIPAL |
false |
Seed the optional floci-deployer user and floci / floci access key |
FLOCI_SERVICES_IAM_ACCOUNT_ALIAS |
(unset) | Seed an account alias at startup; unset means the account has no alias |
Examples
export AWS_ENDPOINT_URL=http://localhost:4566
# Create a role
aws iam create-role \
--role-name lambda-execution-role \
--assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"Service": "lambda.amazonaws.com"},
"Action": "sts:AssumeRole"
}]
}' \
--endpoint-url $AWS_ENDPOINT_URL
# Attach a managed policy
aws iam attach-role-policy \
--role-name lambda-execution-role \
--policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole \
--endpoint-url $AWS_ENDPOINT_URL
# Create a user
aws iam create-user --user-name alice --endpoint-url $AWS_ENDPOINT_URL
# Create an access key
aws iam create-access-key --user-name alice --endpoint-url $AWS_ENDPOINT_URL
# List roles
aws iam list-roles --endpoint-url $AWS_ENDPOINT_URL