Skip to main content
Glama
localstack
by localstack

localstack-iam-policy-analyzer

Configure IAM enforcement modes and analyze logs to automatically generate missing IAM policies for LocalStack development environments.

Instructions

Configures LocalStack's IAM enforcement and analyzes logs to automatically generate missing IAM policies.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
actionYesThe action to perform: 'set-mode' to configure enforcement, 'analyze-policies' to generate a policy from logs, or 'get-status' to check the current mode.
modeNoThe enforcement mode to set. This is required only when the action is 'set-mode'.

Implementation Reference

  • Tool metadata that registers the tool with name 'localstack-iam-policy-analyzer', description, and annotations.
    export const metadata: ToolMetadata = { name: "localstack-iam-policy-analyzer", description: "Configures LocalStack's IAM enforcement and analyzes logs to automatically generate missing IAM policies.", annotations: { title: "LocalStack IAM Policy Analyzer", readOnlyHint: false, destructiveHint: false, idempotentHint: false, }, };
  • Zod schema defining input parameters: action (enum) and optional mode (enum).
    export const schema = { action: z .enum(["set-mode", "analyze-policies", "get-status"]) .describe( "The action to perform: 'set-mode' to configure enforcement, 'analyze-policies' to generate a policy from logs, or 'get-status' to check the current mode." ), mode: z .enum(["ENFORCED", "SOFT_MODE", "DISABLED"]) .optional() .describe("The enforcement mode to set. This is required only when the action is 'set-mode'."), };
  • Primary handler function that performs preflights, then switches on 'action' to call get-status, set-mode, or analyze-policies sub-handlers.
    export default async function localstackIamPolicyAnalyzer({ action, mode, }: InferSchema<typeof schema>) { const preflightError = await runPreflights([ requireLocalStackCli(), requireProFeature(ProFeature.IAM_ENFORCEMENT), ]); if (preflightError) return preflightError; switch (action) { case "get-status": return await handleGetStatus(); case "set-mode": if (!mode) { return ResponseBuilder.error( "Missing Required Parameter", `The 'mode' parameter is required when using 'set-mode' action. Valid modes: - **ENFORCED**: Strict IAM enforcement (blocks unauthorized actions) - **SOFT_MODE**: Log IAM violations without blocking - **DISABLED**: Turn off IAM enforcement completely` ); } return await handleSetMode(mode); case "analyze-policies": return await handleAnalyzePolicies(); default: return ResponseBuilder.error( "Unknown action", `Unknown action: ${action}. Supported actions: get-status, set-mode, analyze-policies` ); } }
  • Helper function for 'analyze-policies' action: retrieves logs, filters IAM denials, enriches with resource data, deduplicates permissions, generates IAM policy, and formats the report.
    async function handleAnalyzePolicies() { try { const logRetriever = new LocalStackLogRetriever(); const logResult = await logRetriever.retrieveLogs(5000); if (!logResult.success) { return ResponseBuilder.markdown(`❌ **Failed to Retrieve Logs** ${logResult.errorMessage} Please ensure LocalStack is running and generating logs.`); } const iamDenials = logResult.logs.filter((log) => log.isIamDenial === true); if (iamDenials.length === 0) { return ResponseBuilder.markdown(`✅ **Analysis Complete - No IAM Denials Found** No IAM permission errors were found in the recent logs. **This means either:** - Your application has all necessary permissions - IAM enforcement is not active (check with \`get-status\`) - No recent activity has triggered permission checks - IAM denials occurred outside the analyzed log window **Next steps:** - If you expected to see denials, ensure IAM enforcement is in \`ENFORCED\` or \`SOFT_MODE\` - Try running your application again to generate fresh logs - Increase the log analysis window if needed`); } const enrichedDenials = await enrichWithResourceData(iamDenials, logResult.logs); const uniquePermissions = deduplicatePermissions(enrichedDenials); const iamPolicy = generateIamPolicy(uniquePermissions); return formatPolicyReport(enrichedDenials, uniquePermissions, iamPolicy); } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); return ResponseBuilder.markdown(`❌ **Policy Analysis Failed** Error: ${errorMessage} Please ensure LocalStack is running and check the logs for more details.`); } }
  • Generates the IAM policy document (JSON) from a map of unique permissions, grouping actions by resource.
    export function generateIamPolicy(permissions: Map<string, UniquePermission>) { const resourcesToActionMap = new Map<string, Set<string>>(); for (const permission of permissions.values()) { const resource = permission.resource || "*"; if (!resourcesToActionMap.has(resource)) { resourcesToActionMap.set(resource, new Set()); } resourcesToActionMap.get(resource)!.add(permission.action); } const statements = Array.from(resourcesToActionMap.entries()).map(([resource, actions], i) => ({ Sid: `GeneratedStatement${i + 1}`, Effect: "Allow", Action: Array.from(actions).sort(), Resource: resource, })); return { Version: "2012-10-17", Statement: statements, }; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/localstack/localstack-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server