Automate user-level custom permissions for Amazon QuickSight
TL;DR: Use a layered approach. Set conservative account- or role-level defaults, apply profiles at user creation when possible, react to group changes with an EventBridge→Lambda pipeline, and run a paginated batch job to remediate existing users. Together these patterns shrink the transient provisioning window where privilege creep and accidental access to AI-driven features happen.
Just-In-Time (JIT) federation and SSO can create a brief provisioning window after a user signs in where they exist in Amazon QuickSight but haven’t yet been assigned to groups. That transient state is where over-privilege often appears. Amazon’s guidance describes four practical automation patterns that map to different moments in a user lifecycle and to operational scale.
The four automation patterns, when to use each
-
Scenario 1: Apply at registration (pre-provisioning)
When your provisioning flow controls user creation (JIT hooks, SCIM, or scripted invites), call RegisterUser and attach a profile using –custom-permissions-name so the user lands in QuickSight with the intended restrictions. Example (simplified):
RegisterUser –aws-account-id 123456789012 –custom-permissions-name “Restricted-Author-Profile”
RegisterUser requires additional args (namespace, identity-type, username/email). Implement this where you create the user to avoid an interim over-privilege gap.
-
Scenario 2: Account- or role-level defaults (start here)
Set a conservative baseline using UpdateAccountCustomPermission and UpdateRoleCustomPermission. These account- and role-level defaults act as the fallback when no user-level profile exists. Permission resolution follows: account → role → user (user-level overrides role, and role-level overrides account-level).
Practical advice: “Start with Scenario 2 to establish your baseline today.” (AWS blog post)
-
Scenario 3: Event-driven, near real-time assignment
For federated environments or when groups determine access, deploy a CloudTrail → EventBridge → Lambda pipeline. This detects group membership changes and applies or removes a user-level custom permission profile immediately.
How the event-driven flow works
- CloudTrail typically logs group membership and user events (for example: CreateGroupMembership/DeleteGroupMembership from QuickSight and AddMemberToGroup/RemoveMemberFromGroup from IAM Identity Center). Verify the exact events in your account because APIs and event names can vary by integration.
- EventBridge filters CloudTrail events (by eventSource and eventName) and forwards matching events to a Lambda function.
- Lambda resolves the QuickSight user and the group-to-profile mapping, then calls UpdateUserCustomPermission to apply a profile or DeleteUserCustomPermission to remove it.
Important operational notes:
- EventBridge rules and CloudTrail events are region-scoped by default. Deploy the CloudFormation stack in the same AWS Region as your QuickSight subscription, or design cross-region aggregation if you operate multi-region QuickSight instances.
- There is no API that attaches a QuickSight custom permission profile directly to a Group. You must update the user record itself when membership changes.
Example deployment hints from the guidance:
- Name your Lambda something like Auto-Assign-QS-Permissions. Use the latest Lambda-supported Python runtime you’ve validated (for example, Python 3.11) and increase the timeout (30 seconds recommended).
- Give the Lambda a role such as Quick-Auto-Permissions-Role with a policy like Quick-Lambda-Policy that includes QuickSight Update/Delete user‑permission calls, DescribeUser, and CloudWatch Logs permissions.
- Set Lambda environment variables for PERMISSION_PROFILE, TARGET_GROUP_NAME, and NAMESPACE so the function can be parameterized per deployment.
-
Scenario 4: Retroactive batch updates
To fix an existing population, run a pagination-aware Python script that lists group members and applies UpdateUserCustomPermission for each. Use ListGroupMemberships with MaxResults and NextToken to iterate pages; MaxResults is commonly used up to 100 per page.
Example configuration values shown in the guidance include:
- AWS_ACCOUNT_ID = ‘279938032093’
- TARGET_GROUP_NAME = ‘BlogTestGroup’
- PERMISSION_PROFILE_NAME = ‘TestBlog’
- NAMESPACE = ‘default’
For scripts that iterate many users, implement pacing and backoff to avoid throttling. The guidance states: “The default delay of 0.1 seconds between API calls (~10 requests/second) is suitable for most deployments.” Treat that as a starting point, not a limit. Verify API quotas for your account and implement exponential backoff with jitter.
Operational runbook: checklist to deploy
- CloudFormation template: https://aws-blogs-artifacts-public.s3.us-east-1.amazonaws.com/artifacts/ML-21102/AutomateUser-LevelCustomPermissionsforAmazonQuick.yaml (suggested stack name: quickcustompermissions). Verify template contents and region before deployment.
- Lambda function: name Auto-Assign-QS-Permissions; runtime: latest validated Python runtime (e.g., Python 3.11); timeout: 30s; increase memory if you expect heavy API calls.
- IAM: create role Quick-Auto-Permissions-Role and attach Quick-Lambda-Policy granting quicksight:UpdateUserCustomPermission, quicksight:DeleteUserCustomPermission, quicksight:DescribeUser, quicksight:ListGroupMemberships (or equivalent), and CloudWatch Logs. Scope ARNs to your account/namespace when possible.
- EventBridge rules: filter for CloudTrail API calls where eventSource is quicksight.amazonaws.com and eventName is CreateGroupMembership/DeleteGroupMembership, or eventSource sso-directory.amazonaws.com with AddMemberToGroup/RemoveMemberFromGroup.
- Lambda environment variables: PERMISSION_PROFILE (profile name to apply), TARGET_GROUP_NAME (group this rule targets), NAMESPACE (QuickSight namespace).
- Batch remediation script: implement MaxResults/NextToken iteration for ListGroupMemberships; include configurable delay and exponential backoff; log failures to a durable store for follow-up.
- Monitoring: emit metrics for successful and failed UpdateUserCustomPermission calls; alert on sustained throttling or high error rates. Consider CloudWatch dashboards and SNS alerts for ops handoff.
Edge cases, conflicts, and recommended logic
QuickSight supports one custom permission profile per user. If a user belongs to multiple groups that map to different profiles, your pipeline must resolve that conflict. The AWS guidance suggests priority schemes but doesn’t prescribe one. Pick a deterministic policy and log decisions for auditability.
Concrete conflict-resolution approach (pseudocode):
- Define a group priority list (highest to lowest).
- When a user’s group set changes, compute the highest-priority group in that set.
- Apply the permission profile associated with that highest-priority group. If none match, fall back to role/account default.
Example decision flow (one-line pseudocode):
- If user.groups ∩ priorityList[0] ≠ Ø then apply profile(priorityList[0]) else test next priority; if none, apply account/role default.
Backoff and throttling strategy (pseudocode):
- attempt = 0
- while attempt < max_retries:
- call API
- if success: break
- else sleep(random_jitter * (base_delay * 2**attempt))
- attempt += 1
Log every decision with the user identifier, source event, groups evaluated, chosen profile, and API result to aid audits and troubleshooting.
Phased starter timeline
- Immediate (days): Set conservative account and role defaults with UpdateAccountCustomPermission and UpdateRoleCustomPermission to enforce least privilege from day one.
- Near-term (weeks): Deploy the CloudTrail → EventBridge → Lambda pipeline in a non-production region using the CloudFormation template. Test group events, conflict-resolution logic, and backoff behavior.
- Remediation (as needed): Run the pagination-aware batch script to apply profiles to existing users; tune pacing and monitor for throttles and errors.
“When new users are provisioned through Just-In-Time federation, CloudTrail captures a CreateUser event (when Quick users are invited by admins, this produces a BatchCreateUser event).” (AWS blog post)
Key takeaways, short questions and honest answers
-
Can I set a custom permission when a QuickSight user is created?
Yes. Use RegisterUser with –custom-permissions-name to attach a profile at creation time; include required parameters such as namespace and identity-type in your provisioning call.
-
How do I establish a safe baseline for everyone now?
Use UpdateAccountCustomPermission and UpdateRoleCustomPermission to set account- and role-level default profiles; these act as fallbacks while you build user-level automation.
-
How do I apply or remove profiles automatically when group membership changes?
Capture group add/remove events via CloudTrail, filter them in EventBridge, and trigger a Lambda that calls UpdateUserCustomPermission or DeleteUserCustomPermission for the impacted user.
-
What about large groups or retroactive fixes?
Run a pagination-aware Python script that uses ListGroupMemberships with MaxResults and NextToken and applies UpdateUserCustomPermission per member; implement exponential backoff with jitter rather than relying solely on a fixed delay.
-
Can a user have multiple QuickSight permission profiles?
No. QuickSight supports one custom permission profile per user, so implement deterministic conflict-resolution when a user belongs to groups that map to different profiles.
This is a layered security pattern: establish a conservative baseline with account/role defaults, add event-driven user overrides to close JIT/SSO gaps, and run paginated remediation for existing users. If you’d like, I can generate a concise CloudFormation/IAM checklist tailored to your AWS account and region to drop straight into your deployment playbook.