Last active
March 13, 2024 12:38
-
-
Save evgalak/d0d1adf099e2d7bff741c16a89bf30ba to your computer and use it in GitHub Desktop.
PHP code snippet to generate signed URL of the AWS QuickSight embed dashboard
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// In addition to explanations from: | |
// https://stackoverflow.com/questions/53773313/how-to-get-generate-aws-quicksight-secure-dashboard-url/54052069#54052069 | |
use Aws\Sts\StsClient; | |
use Aws\Credentials\Credentials; | |
use Aws\QuickSight\QuickSightClient; | |
use Aws\CognitoIdentity\CognitoIdentityClient; | |
use Aws\QuickSight\Exception\QuickSightException; | |
class StatisticsController | |
{ | |
/* | |
* Generate signed URL of the AWS QuickSight embed dashboard | |
* | |
* @param $qsDashboardId | |
* @return $qsDashboardUrl | |
* @throws Throwable | |
*/ | |
function getQsDashboardUrl($qsDashboardId) | |
{ | |
// $user = Auth::user(); | |
// Authorised user | |
$user = (object) ['username'=>'***', 'email=>'***'] | |
// Step 0: Get idToken from request headers | |
// $authorizationHeader = request()->header('Authorization'); | |
// $idToken = trim(str_replace('Bearer', '', $authorizationHeader)); | |
// Here we should have a valid ID tocken (from the cognito user pool, or other provider) | |
$idToken='******************************************************'; | |
// Step 1: Get identity based on idToken | |
$cognitoIdentityClient = new CognitoIdentityClient([ | |
'version' => 'latest', | |
'region' => 'eu-central-1', | |
'IdentityPoolId' => config('aws-cognito-auth.identity_pool_id') // IDENTITY pool id: 'eu-central-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' | |
]); | |
$identity = $cognitoIdentityClient->getId([ | |
'IdentityPoolId'=> config('aws-cognito-auth.identity_pool_id') , | |
'Logins' => [ | |
config('aws-cognito-auth.user_pool_url') => $idToken, | |
// USER pool url/id 'cognito-idp.eu-central-1.amazonaws.com/eu-central-1_XXXXXXXX' => $idToken | |
// Or other providers like Fb, Google, AD, etc. | |
] | |
]); | |
// Step 2A.1: Get identity credentials | |
$openIdToken = $cognitoIdentityClient->GetOpenIdToken([ | |
'IdentityId'=> $identity['IdentityId'], | |
'Logins' => [ | |
config('aws-cognito-auth.user_pool_url') => $idToken, | |
] | |
]); | |
// Step 2A.2: Instantiate StsClient | |
$stsClient = new StsClient([ | |
'region' => 'eu-central-1', | |
'version' => 'latest', | |
'credentials' => false, | |
]); | |
// Step 2A.3: Request temporary credentials of role what should have policy with | |
// quicksight:RegisterUser, quicksight:GetDashboardEmbedUrl actions allowed | |
$role = $stsClient->assumeRoleWithWebIdentity([ | |
'RoleArn' => config('aws-quicksight.embed_dashboard_role_arn'), | |
'RoleSessionName' => $user->username, | |
'WebIdentityToken' => $openIdToken['Token'], | |
]); | |
// Step 2A.4: Prepare credentials object | |
$credentialsObject = new Credentials( | |
$role['Credentials']['AccessKeyId'], | |
$role['Credentials']['SecretAccessKey'], | |
$role['Credentials']['SessionToken'], | |
(int) $role['Credentials']['Expiration']->format('U') | |
); | |
// Alternative scenario. If Quicksight is on a same AWS acc, | |
// then you can request credentials directly, it will auto assume default identity pool role for authorised users | |
// | |
/* | |
// Step 2B : Get identity credentials | |
$credentials = $cognitoIdentityClient->getCredentialsForIdentity([ | |
'IdentityId'=> $identity['IdentityId'], | |
'Logins' => [ | |
config('aws-cognito-auth.user_pool_url') => $idToken, | |
] | |
]); | |
// Step 2B.1: Prepare credentials object | |
$credentialsObject = new Credentials( | |
$credentials['Credentials']['AccessKeyId'], | |
$credentials['Credentials']['SecretKey'], | |
$credentials['Credentials']['SessionToken'], | |
(int) $credentials['Credentials']['Expiration']->format('U') | |
); | |
*/ | |
// Step 3: Instantiate QS client in us-east-1(QS users repository is there even if your datasets are somewhere else) | |
$qsClient = new QuickSightClient([ | |
'region' => 'us-east-1', | |
'version' => 'latest', | |
'credentials' => $credentialsObject | |
]); | |
// Step 3: Load/Register QS user client | |
$qsRegisterUserParams = [ | |
'AwsAccountId' => config('aws-quicksight.account_id'), | |
'Email' => $user->email, | |
'IdentityType' => 'IAM', //| QUICKSIGHT, | |
'Namespace' => 'default', | |
'UserRole' => 'READER', //ADMIN | AUTHOR | READER | RESTRICTED_AUTHOR | RESTRICTED_READER, | |
'IamArn' => config('aws-quicksight.embed_dashboard_role_arn'), | |
'SessionName' => $user->username, | |
]; | |
$qsUser = null; | |
// Step 3.1: Try to Load QS user info | |
try{ | |
$qsUser = $qsClient->describeUser([ | |
'AwsAccountId' => config('aws-quicksight.account_id'), | |
'Namespace' => 'default', | |
'UserName'=> config('aws-quicksight.embed_dashboard_role_name').'/'.$user->username, | |
]); | |
} | |
catch (QuickSightException $e){ | |
//If a user is just not found procced to registration, in all other cases - throw an exception | |
throw_if($e->getAwsErrorCode() !== 'ResourceNotFoundException', $e); | |
} | |
// Step 3.1: If user not found - try to register | |
if(!$qsUser){ | |
$qsUser = $qsClient->registerUser($qsRegisterUserParams); | |
} | |
// Step 4.1: Re-Instantiate QS client to region with datasources | |
$qsClient = new QuickSightClient([ | |
'region' => config('aws-quicksight.datasets_region'), | |
'version' => config('aws-quicksight.version'), | |
'credentials' => $credentialsObject | |
]); | |
// Step 4.2: Get dashboard URL | |
$result = $qsClient->getDashboardEmbedUrl([ | |
'AwsAccountId' => config('aws-quicksight.account_id'), | |
'DashboardId' => $qsDashboardId, | |
'IdentityType' => 'IAM', | |
'ResetDisabled' => false, | |
'SessionLifetimeInMinutes' => config('aws-quicksight.session_duration'), | |
'UndoRedoDisabled' => false, | |
'IamArn' => $qsUser['User']['Arn'] | |
]); | |
return $result['EmbedUrl']; | |
} | |
} | |
?> |
Great that you have found it! So, does it works now?
Yes, using method 2A works. Thank you again for documenting this and making it public!
Thanks for sharing the php.
I am working on embedding the Quicksight dashboard on Wordpress site.
I have done the following steps:
- policy:Quicksightembed: registeruser, stsassume, getembeddedurl
- Role: quicksightRole <>>attached the above policy(quicksightembed)
- Cognito userpool and identity pool created (this is currently being used on the wordpress site)
- built the graph and publish dashboard to all
- uploaded your php to the wordpress (parameters changed).
It is not working the webpage is blank. Could you please provide step guide to implement this on wordpress on linux?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thank you for getting back to me! I originally started with 2B because my AWS and Quicksight were on the same account, but I started from square one with the code again using 2A method. However, I kept getting this error using 2A's method:
It turns out that I missed the subtle change in the credential Object between 2B and 2A. The secret key in 2B is
SecretKey
but in 2A it'sSecretAccessKey
. Copy-pasta... you got me again!