To adhere to the Principle of Least Privilege, we will create IAM Groups for workshop operators, then design and create specialized IAM Policies and Roles for each Lambda and Step Functions service within the system.
Before creating the service roles for the system, create IAM groups to manage AWS Console access by role. This avoids attaching permissions policies directly to each user.
Policies such as AdministratorAccess and PowerUserAccess are suitable only for controlled workshop/lab environments. For production, replace them with custom policies scoped to the exact resources and actions required.
Go to IAM -> User groups -> Create group.
Create the administrator group:
DocuFlow-AdminsAdministratorAccess
Create the developer group:
DocuFlow-DevelopersPowerUserAccess
Create the read-only group:
DocuFlow-ReadOnlyReadOnlyAccess

Create a sample admin user:
docuflow-tra.DocuFlow-Admins.

Create sample workshop users:
docuflow-tinh, docuflow-tai, and docuflow-duong.docuflow-loc.

In Set permissions, choose Add user to group. Add developer users to DocuFlow-Developers; if you created a view-only user, add that user to DocuFlow-ReadOnly.

After creation, return to IAM -> User groups to confirm that the groups have the expected users and policies.
docuflow-dev-security-upload-url-role (Lambda to generate upload URL)Purpose: Allows API Gateway to invoke Lambda to generate a Presigned URL so the Frontend can upload files to the S3 Raw bucket and record initial information into the database.
Go to the IAM service ➔ Policies ➔ Choose Create policy (Select the JSON tab).
Paste the following JSON Policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowPutObjectToRawBucket",
"Effect": "Allow",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::docuflow-dev-raw-*"
},
{
"Sid": "AllowWriteToDynamoDB",
"Effect": "Allow",
"Action": [
"dynamodb:PutItem",
"dynamodb:UpdateItem"
],
"Resource": "arn:aws:dynamodb:*:*:table/docuflow-dev-documents-table"
}
]
}

Click Next. Set Policy Name: docuflow-dev-ingestion-s3-raw-access-policy.
Enter Description: Allows Lambda function to generate S3 presigned URLs for raw document upload and initialize metadata in DynamoDB table.

Click Create policy.
Go to Roles ➔ Choose Create role (Select Trusted Entity Type: AWS service ➔ Service or use case: Lambda).

Click Next.
Attach Policy: Check docuflow-dev-ingestion-s3-raw-access-policy and the default system policy AWSLambdaBasicExecutionRole (for logging).

Click Next. Set Role Name: docuflow-dev-security-upload-url-role.

Click Create role.

docuflow-dev-security-job-starter-role (Lambda to read SQS and trigger Workflow)Purpose: Allows Lambda to receive messages from the SQS queue to get the file ID, then trigger the automated processing workflow in Step Functions.
Go to the IAM service ➔ Policies ➔ Choose Create policy (Select the JSON tab).
Paste the following JSON Policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowStartStepFunctions",
"Effect": "Allow",
"Action": "states:StartExecution",
"Resource": "arn:aws:states:*:*:stateMachine:docuflow-dev-*"
},
{
"Sid": "AllowManageSQSMessages",
"Effect": "Allow",
"Action": [
"sqs:ReceiveMessage",
"sqs:DeleteMessage",
"sqs:GetQueueAttributes"
],
"Resource": "arn:aws:sqs:*:*:docuflow-dev-*"
}
]
}

Click Next. Set Policy Name: docuflow-dev-workflow-trigger-policy.
Enter Description: Grants permissions to process messages from SQS queue and trigger Step Functions workflow executions.

Click Create policy.

Go to Roles ➔ Choose Create role (Select Trusted Entity Type: AWS service ➔ Service or use case: Lambda).

Click Next.
Attach Policy: Check docuflow-dev-workflow-trigger-policy and AWSLambdaBasicExecutionRole.

Click Next. Set Role Name: docuflow-dev-security-job-starter-role.

Click Create role.

docuflow-dev-workflow-stepfunctions-role (Dedicated permissions for Step Functions Orchestrator)Purpose: Grants Step Functions permissions to sequentially invoke processing Lambda functions and log execution progress.
Go to the IAM service ➔ Policies ➔ Choose Create policy (Select the JSON tab).
Paste the following JSON Policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowStepFunctionToCallLambda",
"Effect": "Allow",
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:*:*:function:docuflow-dev-*"
},
{
"Sid": "AllowStepFunctionsLogging",
"Effect": "Allow",
"Action": [
"logs:CreateLogDelivery",
"logs:PutLogEvents",
"logs:GetLogDelivery",
"logs:UpdateLogDelivery",
"logs:DeleteLogDelivery",
"logs:ListLogDeliveries"
],
"Resource": "*"
}
]
}

Click Next. Set Policy Name: docuflow-dev-workflow-orchestration-policy.
Enter Description: Allows Step Functions to orchestrate workflow by invoking core processing Lambdas and logging deliveries.

Click Create policy.

Go to Roles ➔ Choose Create role (Select Trusted Entity Type: Custom trust policy).
Paste the following Trust Policy defining the Step Functions service:
{
"Version": "2012-10-17",
"Statement": [{ "Effect": "Allow", "Principal": { "Service": "states.amazonaws.com" }, "Action": "sts:AssumeRole" }]
}

Click Next. Attach Policy: Check docuflow-dev-workflow-orchestration-policy.

Click Next. Set Role Name: docuflow-dev-workflow-stepfunctions-role.
Enter Description: Service role for Step Functions state machine to orchestrate the AI document pipeline.

Click Create role.

docuflow-dev-ai-textract-lambda-role (Lambda permissions for Amazon Textract text extraction)Purpose: Allows Lambda to retrieve files from the S3 Raw bucket, perform extraction using Textract, and save the raw results to the S3 Processed Bucket.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowReadRawBucket",
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::docuflow-dev-raw-*"
},
{
"Sid": "AllowWriteProcessedBucket",
"Effect": "Allow",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::docuflow-dev-processed-*"
},
{
"Sid": "AllowCallTextractAI",
"Effect": "Allow",
"Action": "textract:AnalyzeExpense",
"Resource": "*"
}
]
}

docuflow-dev-ai-textract-invoke-policy.Allows Lambda to retrieve raw documents from S3, invoke Amazon Textract AnalyzeExpense API, and save results.



docuflow-dev-ai-textract-invoke-policy along with AWSLambdaBasicExecutionRole, AmazonS3ExpressFullAccess, AmazonTextractFullAccess.

docuflow-dev-ai-textract-lambda-role.Execution role for extraction lambda to read raw invoices, run Textract OCR, and write thô data.

docuflow-dev-security-ai-proxy-role (Lambda permissions to call External AI outside AWS)Purpose: The ultimate security checkpoint. Only this AI Proxy function is allowed to read the Token (API Key) stored in Secrets Manager to connect to external AI models.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowAIProxyToGetSecret",
"Effect": "Allow",
"Action": "secretsmanager:GetSecretValue",
"Resource": "arn:aws:secretsmanager:ap-southeast-1:*:secret:docuflow-dev-external-ai-api-key-*"
},
{
"Sid": "AllowAIProxyToUseKMS",
"Effect": "Allow",
"Action": [
"kms:Decrypt",
"kms:DescribeKey"
],
"Resource": "arn:aws:kms:*:*:alias/docuflow-dev-main-key"
}
]
}

docuflow-dev-ai-secret-read-policy.Strictly restricts access to External AI API credentials stored within AWS Secrets Manager.



docuflow-dev-ai-secret-read-policy and AWSLambdaBasicExecutionRole.

docuflow-dev-security-ai-proxy-role.


docuflow-dev-data-lambda-role (Lambda CRUD permissions for UI Display Data)Purpose: Allows API Lambda functions to perform CRUD operations on DynamoDB and load files from S3 buckets to display on the Frontend.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowReadWriteDynamoDBOnly",
"Effect": "Allow",
"Action": [
"dynamodb:GetItem",
"dynamodb:Query",
"dynamodb:UpdateItem",
"dynamodb:Scan",
"dynamodb:DeleteItem"
],
"Resource": [
"arn:aws:dynamodb:*:*:table/docuflow-dev-documents-table",
"arn:aws:dynamodb:*:*:table/docuflow-dev-documents-table/index/*"
]
},
{
"Sid": "AllowReadS3ProcessedBucket",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:DeleteObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::docuflow-dev-processed-*/*",
"arn:aws:s3:::docuflow-dev-raw-*/*",
"arn:aws:s3:::docuflow-dev-processed-*",
"arn:aws:s3:::docuflow-dev-raw-*"
]
}
]
}
3. Click Next. Set Policy Name: docuflow-dev-data-dynamodb-access-policy.
4. Enter Description: Allows standard query, scanning, and metadata update operations against the core DynamoDB documents table.
5. Click Create policy.
6. Go to Roles ➔ Choose Create role (Trusted Entity Type: AWS service ➔ Service: Lambda).
7. Click Next.
8. Attach Policy: Check docuflow-dev-data-dynamodb-access-policy and AWSLambdaBasicExecutionRole.
9. Click Next. Set Role Name: docuflow-dev-data-lambda-role.Execution role for metadata/data lambda to fetch and modify documents inside DynamoDB.


docuflow-dev-notification-lambda-role (Lambda permissions to send Alert notifications)Purpose: Pushes system error notifications or abnormal invoice alerts to an SNS Topic to trigger the automated email flow for the team.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowPublishToSNSTopic",
"Effect": "Allow",
"Action": "sns:Publish",
"Resource": "arn:aws:sns:*:*:docuflow-dev-notification-system-alerts-topic"
}
]
}

docuflow-dev-notification-sns-publish-policy.Enables system alerting components to publish failure logs and anomaly alerts to the target SNS Topic.



docuflow-dev-notification-sns-publish-policy and AWSLambdaBasicExecutionRole.

docuflow-dev-notification-lambda-role.Execution role for notification component to broadcast system alert messages via SNS.


docuflow-dev-workflow-validate-lambda-role (Lambda permissions for input data validation)Purpose: Responsible for validating file formats and sizes from the S3 Raw bucket, and recording the initial PROCESSING state in DynamoDB.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowReadS3RawMetadata",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:GetObjectAttributes"
],
"Resource": "arn:aws:s3:::docuflow-dev-raw-*"
},
{
"Sid": "AllowUpdateStatusToDynamoDB",
"Effect": "Allow",
"Action": [
"dynamodb:UpdateItem",
"dynamodb:GetItem"
],
"Resource": "arn:aws:dynamodb:*:*:table/docuflow-dev-documents-table"
}
]
}

docuflow-dev-ingestion-validation-policy.Allows Validate Lambda to check file metadata in S3 Raw and update initial processing state in DynamoDB.



docuflow-dev-ingestion-validation-policy and AWSLambdaBasicExecutionRole.

docuflow-dev-workflow-validate-lambda-role.Execution role for validation lambda to inspect uploaded documents and update state.


docuflow-dev-ai-confidence-status-lambda-role (Lambda permissions for Status Logic & Confidence Evaluation)Purpose: After the AI Proxy returns the results, the Confidence + Status Lambda evaluates the score, categorizes the status as EXTRACTED or REVIEW_REQUIRED, saves the final result (result.json) to the S3 Processed Bucket, and updates the DynamoDB table.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowWriteToProcessedBucket",
"Effect": "Allow",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::docuflow-dev-processed-*"
},
{
"Sid": "AllowWriteFinalStatusToDynamoDB",
"Effect": "Allow",
"Action": [
"dynamodb:UpdateItem",
"dynamodb:PutItem"
],
"Resource": "arn:aws:dynamodb:*:*:table/docuflow-dev-documents-table"
}
]
}

docuflow-dev-ai-confidence-status-policy.Allows Lambda to calculate confidence scores, save final result JSON to S3 Processed, and update metadata in DynamoDB.



docuflow-dev-ai-confidence-status-policy and AWSLambdaBasicExecutionRole.

docuflow-dev-ai-confidence-status-lambda-role.Execution role for confidence and status lambda to evaluate AI result and update final state.

