Error while embedding Amazon QuickSight dashboards with Django

2.7k Views Asked by At

I am trying to embed QuickSight dashboards into my django application. I followed all of the steps regarding embedding detailed in the following documentation: https://docs.aws.amazon.com/en_us/quicksight/latest/user/embedded-dashboards-setup.html

Using the AWS CLI, I am able to assume an IAM role I created, register a user into my QS account, and get the dashboard embed url, and view the dashboard in a web browser.

However, when trying to mimic the same behavior inside the application using the Python SDK, it yields the following: "We can't display this page (Not authorized)."

We have whitelisted our domain within Quicksight, and tested it on 2 different servers. The user who is logged into the django app and is trying to view the dashboard already is in the QS account with the necessary permissions to view the dashboard. But still getting "We can't display this page (Not authorized)."

Use of the Python SDK is below:

def viewDashboard(request):

import boto3
sts = boto3.client('sts')

assumed_role_object = sts.assume_role(
    RoleArn="arn:aws:iam::********4324:role/QuickSightEmbed",
    RoleSessionName=email
)

# From the response that contains the assumed role, get the temporary
# credentials that can be used to make subsequent API calls
credentials = assumed_role_object['Credentials']

# Use the temporary credentials that AssumeRole returns to make a
# connection to Amazon S3
s3_resource = boto3.resource(
    's3',
    aws_access_key_id=credentials['AccessKeyId'],
    aws_secret_access_key=credentials['SecretAccessKey'],
    aws_session_token=credentials['SessionToken'],
)

client = boto3.client('quicksight', region_name='us-east-1')

response = client.register_user(
    IdentityType='IAM',
    Email=email,
    UserRole='READER',
    IamArn='arn:aws:iam::********4324:role/QuickSightEmbed',
    SessionName=email,
    AwsAccountId='********4324',
    Namespace='default',
)

client = boto3.client('quicksight', region_name='us-west-2')
url = client.get_dashboard_embed_url(
    AwsAccountId="********4324",
    DashboardId="4ea*****-8f**-46**-98**-389e43f*****",
    IdentityType="IAM",
)

This url is then passed to the HTML as the url to embed.

3

There are 3 best solutions below

1
Adi Joshi On

Once the user has been registered you need to share that dashboard with the user.

0
user2503882 On

You are registering a user in another region:

client = boto3.client('quicksight', region_name='us-east-1')

0
Tomas On

I had the same problem. I get the url, but could not embed the dashboard. Make sure that the url you get is well formatted. Then, I advise you, from views, generate a getDashboardUrl () function, to then be invoked from your method that receives the request, and you pass it as context to the template. In the template, use the html iframe tag. Do not recommend use boto3 function. Since it has cookie handling problems.

Try the following:

In views:

def getDashboardURL():
    sts = boto3.client('sts', region_name=region, 
    aws_access_key_id = aws_access_key_id, 
    aws_secret_access_key = aws_secret_access_key)
    assumedRole = sts.assume_role(
               RoleArn = roleArn,
               RoleSessionName=sessionName,
               )
    assumedRoleSession = boto3.Session(
        aws_access_key_id = assumedRole['Credentials']['AccessKeyId'],
        aws_secret_access_key = assumedRole['Credentials']['SecretAccessKey'],
        aws_session_token = assumedRole['Credentials']['SessionToken'],
    )

    quickSight = assumedRoleSession.client(
            'quicksight', region_name=region)

    response = quickSight.get_dashboard_embed_url(
        AwsAccountId = accountId,
        DashboardId = dashboardId,
        IdentityType = 'QUICKSIGHT',
        SessionLifetimeInMinutes = 600,
        UndoRedoDisabled = True,
        ResetDisabled = True,
        UserArn = 'here your user quicksight ARN'
    )
    return response['EmbedUrl']

def dashboard(request):
    url = getDashboardURL()
    context = {
        'dash_url': url
     }
    return render(request, 'dashboard.html', context)

In template dashaboard:

<div>
    <iframe src="{{ dash_url }}" title="Dashboard" class="container> </iframe>
</div>