Amazon QuickSight custom permissions are a nightmare to manage manually once you hit a few dozen users. If you are still clicking checkboxes in the console to stop analysts from exporting raw data or

Taylor27 Intermediate 1h ago 434 views 2 likes 3 min read

Which automation pattern actually fits your setup?

I've looked at four ways to handle this. Most people default to the console, but that doesn't scale.

1. The "At Creation" approach (RegisterUser)
If you use a custom onboarding portal or a script to spin up users, don't wait for a second API call to set permissions. You can pass the permission profile directly during the RegisterUser call. This is the cleanest method for SaaS setups where you need to tie feature access (like GenBI or paginated reports) to a specific pricing tier immediately.

2. The "Blanket" approach (Account/Role Defaults)
If everyone in a specific role (e.g., all Readers) should have the same restrictions, stop managing them individually. Use UpdateAccountCustomPermission or UpdateRoleCustomPermission. This enforces a baseline for every existing and future user in that role. It's the lowest effort, but it lacks granularity.

3. The "Event-Driven" approach (EventBridge + Lambda)
This is for when you have complex logic—like "If user is in Group A, give them Profile X; if in Group B, give them Profile Y." Since QuickSight doesn't natively map groups to custom permission profiles, you have to bridge the gap. I've seen this implemented by triggering a Lambda via EventBridge whenever a user is added to a group (including IAM Identity Center groups), which then calls the permission API.

4. The "Cleanup" approach (Python Batch)
If you've already provisioned 500 users and realized they all have the wrong permissions, you need a retroactive script. You can't do this via the UI without losing your mind. A Python script using Boto3 to iterate through ListUsers and apply UpdateUserCustomPermission is the only sane way to fix a legacy mess.

Implementing the RegisterUser trigger

For those controlling the provisioning flow, avoid the "create then update" two-step process. It doubles your API calls and creates a window where the user has default (potentially too broad) permissions.

If you are using the AWS CLI, the command looks like this:

aws quicksight register-user \
--aws-account-id 123456789012 \
--namespace DEFAULT \
--principal "[email protected]" \
--role ARN:aws:quicksight:us-east-1:123456789012:role/Author \
--custom-permissions-name "Restricted-Author-Profile"

In this case, Restricted-Author-Profile must already exist in your account. If you try to pass a name that hasn't been defined in the custom permissions settings, the API will throw a ResourceNotFoundException.

Dealing with retroactive bulk updates

If you're in the "cleanup" phase, you'll likely run into rate limiting if you have thousands of users. Boto3 is the standard here, but you need to handle the pagination of the user list correctly.

Here is the logic I use for batch updating permissions for users in a specific group:

import boto3

client = boto3.client('quicksight')
ACCOUNT_ID = '123456789012'
GROUP_NAME = 'Financial-Analysts'
PERMISSION_PROFILE = 'No-Export-Profile'

# Get all users in the specific group
paginator = client.get_paginator('list_group_memberships')
for page in paginator.paginate(AwsAccountId=ACCOUNT_ID, GroupName=GROUP_NAME):
    for member in page['GroupMemberships']:
        user_arn = member['UserArn']
        
        # Apply the custom permission profile to the user
        client.update_user_custom_permission(
            AwsAccountId=ACCOUNT_ID,
            UserArn=user_arn,
            CustomPermissionName=PERMISSION_PROFILE
        )

One thing to watch out for: update_user_custom_permission is an asynchronous-style update in terms of how it reflects in the UI. Don't panic if the console doesn't update instantly; the API call is what matters.

When NOT to use custom permissions

Don't confuse these with Row-Level Security (RLS). Custom permissions control features (can they export? can they share?), not data (can they see the West Coast region?). If you are trying to restrict data access, you need a separate namespace mapping or RLS file. Using custom permissions to try and solve data privacy is a common mistake that leads to over-complicated architecture.

Prompt
A more systematic set of tool reviews lives in these AI tool field notes, with plenty of directly applicable cases.

All Replies (4)

S
SoloSmith Expert 1h ago

Finally! I spent hours fighting the UI before switching to the API. Does this work with the Terraform provider or just raw Python?

0 Reply
D
DevWolf Advanced 1h ago

Pure relief seeing someone else struggle with the UI. I'm using the Terraform provider, but I keep hitting a weird 403 error...

0 Reply
N
NeonPanda Intermediate 1h ago

I want to try this tonight. My current script misses the namespace updates—is that a limitation of the SDK?

0 Reply
A
AveryPilot Novice 1h ago

I'm so relieved. I wasted a whole month on manual updates before realizing the API existed. Does this play nice with Okta?

0 Reply

Write a Reply

Markdown supported