How can I access an AWS DynamoDB as a guest user? - amazon-web-services

I am using aws-amplify and aws-sdk in Angular JS/Typescript.
I can successfully access my AWS DynamoDB as an authenticated user.
I am also trying to add guest user access for a certain table in Dynamo, but I am struggling to understand how I would get a reference to the DynamoDB without any credentials.
My code looks like this at the moment
getDocumentClient() {
return Auth.currentCredentials()
.then(credentials => new AWS.DynamoDB.DocumentClient({ credentials: credentials }))
.catch(err => logger.debug('error getting document client', err));
How would I do something similar to get access to the DynamoDB as an unauthenticated guest user?
Cheers
Lee

Try makeUnauthenticatedRequest.
Here's an example with S3 - I've shown this because I know you can make requests to S3 from the AWS SDK as an unauthenticated user. I'm assuming that this will also work for DynamoDB but have not tested it.
var s3 = new AWS.S3();
var params = {
Bucket: 'mybucket'
};
s3.makeUnauthenticatedRequest('listObjects', params, callback);
The more strategic approach would be Amazon Cognito Identity Pools which support unauthenticated/guest identities. Cognito vends an identity and AWS credentials, and you can configure an IAM role allowing DynamoDB read access for unauthenticated identity types.

I think you can refer to what is mentioned in the blog post below.
https://aws.amazon.com/blogs/compute/using-amazon-api-gateway-as-a-proxy-for-dynamodb/
The basic idea is to use API Gateway as a proxy for DynamoDB API. Permission to access DynamoDB is granted to API Gateway via execution role, and API Gateway is configured to open to public. In doing so, the flow will be as follows:
Web Browser <----- HTTPS -----> API Gateway <----- AWS Service Proxy integration -----> DynamoDB

Related

AWS STS Assume Role: Get session token

I am trying to get a session token for the given IAM in postman but not able to receive a token.
If I use boto3.client('sts'), I am able to get the token.
Use Case: I am trying to Invoke VPC Rest Endpoint from EC2 instance where ServiceNow mid-server instance is running. Since we have ServiceNow mid-server agent running on EC2 instance, I want to use IAM Role attached to EC2 to authenticate other VPC endpoints that are deployed in the same AWS account.
I have permission policy attached to IAM Role to allow Assume Role policy. If there any other approach, please suggest.
here HTML HTML response in postman. Postman redirecting to IAM Docs
client = boto3.client('sts')
response = client.assume_role(
RoleArn='arn:aws:iam::**************:role/ServiceNow-midserver-Role',
RoleSessionName='Session1',
DurationSeconds=3600
)
print(response)
anything wrong with postman request body or endpoint.
Authentication on postman is none.
To call AssumeRole from Postman (or curl etc.) as opposed to using a supported AWS SDK, you should follow the AssumeRole API documentation. You will also need to authenticate using AWS credentials.
Specifically, the request is an HTTP GET and parameters are passed as query strings, for example:
GET https://sts.amazonaws.com/
?Version=2011-06-15
&Action=AssumeRole
&RoleSessionName=stackoverflow-64706420
&RoleArn=arn:aws:iam::123456781234:role/myrole
&DurationSeconds=3600
Here's what this looks like in Postman:
And you will need to add AWS credentials so that your API request is signed correctly, for example:
Click 'Send' and the response will look something like this:
<AssumeRoleResponse xmlns="https://sts.amazonaws.com/doc/2011-06-15/">
<AssumeRoleResult>
<AssumedRoleUser>
<Arn>arn:aws:sts::123456781234:assumed-role/123456781234/stackoverflow-64706420</Arn>
<AssumedRoleId>ARO123EXAMPLE123:stackoverflow-64706420</AssumedRoleId>
</AssumedRoleUser>
<Credentials>
<AccessKeyId>ASIAIOSFODNN7EXAMPLE</AccessKeyId>
<SecretAccessKey>wJalrXUtnFEMI/K7MDENG/bPxRfiCYzEXAMPLEKEY</SecretAccessKey>
<SessionToken>
AQoDYXdzEPT//////////wEXAMPLEtc764bNrC9SAPBSM22wDOk4x4HIZ8j4FZTwdQW
LWsKWHGBuFqwAeMicRXmxfpSPfIeoIYRqTflfKD8YUuwthAx7mSEI/qkPpKPi/kMcGd
QrmGdeehM4IC1NtBmUpp2wUE8phUZampKsburEDy0KPkyQDYwT7WZ0wq5VSXDvp75YU
9HFvlRd8Tx6q6fE8YQcHNVXAkiY9q6d+xo0rKwT38xVqr7ZD0u0iPPkUL64lIZbqBAz
+scqKmlzm8FDrypNC9Yjc8fPOLn9FX9KSYvKTr4rvx3iSIlTJabIQwj2ICCR/oLxBA==
</SessionToken>
<Expiration>2020-12-09T13:34:41Z</Expiration>
</Credentials>
<PackedPolicySize>6</PackedPolicySize>
</AssumeRoleResult>
<ResponseMetadata>
<RequestId>c6104cbe-af31-11e0-8154-cbc7ccf896c7</RequestId>
</ResponseMetadata>
</AssumeRoleResponse>
You need to use credentials for an IAM user or an IAM role to call AssumeRole. boto3 must be getting credentials from the standard locations it look for (like ~/.aws/config) [ref:https://boto3.amazonaws.com/v1/documentation/api/latest/guide/configuration.html]. May be you could try providing the AWS creds in Authorization tab in Postman selecting type as AWS Signature and then call assumeRole.

Accessing AWS AppSync without using API Keys in React Native

In my React Native App I am using API Keys with AWS AppSync and I want to move to using Cognito or IAM but with no user sign in.
My React Native app that just uses AWS Appsync to read to and write from DyanmoDB.
I initially set up the app to use API keys as it was easier to understand and I'm now attempting to transition to using AWS Cognito or IAM.
To do this in my AWS Console I changed the "Appsync->MyAppAPI->Settings->Default authorisation mode"/"API-level" from "API key" to "AWS Identity and Access Management (IAM)".
I then created an Identity Pool and allowed "Enable access to unauthenticated identities".
My aws-exports file is
// WARNING: DO NOT EDIT. This file is automatically generated by AWS Amplify. It will be overwritten.
const awsmobile = {
"aws_appsync_graphqlEndpoint": "https://xxxxx.appsync-api.eu-west-x.amazonaws.com/graphql",
"aws_appsync_region": "eu-west-X",
"aws_appsync_authenticationType": "AWS_IAM",
"aws_appsync_apiKey": "xxx-xxxxxxxxxxxxxxxxxxxxxxxxxx",
};
export default awsmobile;
In my App.js file I have attempted to get the identityPoolId to be used and I have created this:
Amplify.configure({
url: config.aws_appsync_graphqlEndpoint,
region: config.aws_appsync_region,
auth: {
type: config.aws_appsync_authenticationType,
apiKey: config.aws_appsync_apiKey,
region: 'eu-west-x',
identityPoolId: 'eu-west-x:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
}
})
When I use the app to read from DynamoDB I get this error
[WARN] 04:51.835 API - ensure credentials error, No Cognito Federated Identity pool provided
I then went back to the Cognito Manage Identity Pool page and changed my identity pool to use Cognito as an authentication source and provided a User Pool ID and an App client id. But I still get the same error.
I am fundamentally missunderstanding something, could you offer any insight?

Amazon S3 - Access to Private Bucket

I have multiple images within a private S3 bucket and I would like an instance of Tableau to be able to access those images. Is there a URL or some way to access those images while still keeping the S3 bucket private?
Access Private Bucket through Tableau
You can setup a IAM user with access permission to S3 and allow Tableau access.
Check the article on Connect to your S3 data with the Amazon Athena connector in Tableau 10.3 for more details.
Note: You need to configure Amazon Athena for Querying the S3 content.
Custom Generated S3 Urls to Access Private Bucket
Yes. You can generate a Signed URL from your backend using AWS SDK. This can be done directly using S3 or through AWS CloudFront.
Using S3 Signed Urls. e.g, Signed Url for GET Object.
var params = {Bucket: 'bucket', Key: 'key'};
var url = s3.getSignedUrl('getObject', params);
console.log('The URL is', url);
Using CloudFront Signed Urls. e.g, Signed Url for GET in CloudFront.
var cfsign = require('aws-cloudfront-sign');
var signingParams = {
keypairId: process.env.PUBLIC_KEY,
privateKeyString: process.env.PRIVATE_KEY,
// Optional - this can be used as an alternative to privateKeyString
privateKeyPath: '/path/to/private/key',
expireTime: 1426625464599
}
// Generating a signed URL
var signedUrl = cfsign.getSignedUrl(
'http://example.cloudfront.net/path/to/s3/object',
signingParams
);
Note: Generating the Url needs to be done in your backend. You can setup a serverless solution for this by using AWS API Gateway and Lambda to provide an endpoint for authenticated users to access.
In addition you can also use AWS Cognito UserPools with Identity Pool to get direct access to S3 Private Content without the above steps. For this you need to use the Cognito UserPools or a federated identity as the identity provider which is connected with Cognito Identity Pools.

API gateway how to pass AWS IAM authorization from rest client

I am trying to test authenticated API gateway endpoint from rest client. How to I generate/set the "AWS_IAM" authorization headers when making the request ?
You can use Cognito with a "public" pool id, then attach role to the Cognito pool id, the role being accessing your API GATEWAY
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: 'REGION:YOUR_POOL_ID',
});
Use AWS STS to get temporary credentials with limited privileges. After that you can use API Gateway with AWS_IAM authentication
The generated SDK accepts AMI credentials, you have to initiate the client with the one you got from STS:
var apigClient = apigClientFactory.newClient({
accessKey: 'ACCESS_KEY',
secretKey: 'SECRET_KEY',
sessionToken: 'SESSION_TOKEN', //OPTIONAL: If you are using temporary credentials you must include the session token
region: 'eu-west-1' // OPTIONAL: The region where the API is deployed, by default this parameter is set to us-east-1
});
NB: Put strictly minimum roles on your pool, that is a publicly available id, every body can use it to get a temporary or a fixed (to track users across devices) user_/app_ id.
Update April 2016:
For Christine comment's: Documentation on how to use STS.
TL;DR: Basically after your Identity provider calls you back (Google, in my case), you will have a Token (OpenID, in my case), just feed it to STS:
AWS.config.credentials = new AWS.WebIdentityCredentials({
RoleArn: 'arn:aws:iam::<AWS_ACCOUNT_ID>:role/<WEB_IDENTITY_ROLE_NAME>',
ProviderId: 'graph.facebook.com|www.amazon.com', // Omit this for Google
WebIdentityToken: ACCESS_TOKEN
});
You'd have to replicate API Gateway AWS v4 request signature logic to be able to do that. Ideally you should look at the the generated Javascript/Java SDK for your API to get an idea on how these request signatures get calculated. I suggest you turn the authentication off for your testing requests.

How can I call AssumeRoleWithWebIdentity to access Amazon DynamoDB?

Scenario:
I create an app on Amazon, and use Login with Amazon, which returns an "access_token". Then I run:
AWS.config.credentials = new AWS.WebIdentityCredentials({
RoleArn: 'arn:aws:iam::416942672???:role/???_amazon_role',
ProviderId: 'www.amazon.com',
WebIdentityToken:"?????????"
});
AWS.config.region = 'us-west-2';
dynamodb = new AWS.DynamoDB() dynamodb.listTables({}, function a(error,data){
alert( "error: " + JSON.stringify(error) );
alert( JSON.stringify(data) );
});
When I later run the ListTable function it will return:
error: {"message":"Missing credentials in config","code":"SigningError","name":"SigningError","statusCode":403,"retryable":false}
I found it seems that I have to call AssumeRoleWithWebIdentity. But how can I call it in AWS SDK for JavaScript? Or is there any other process I missed?
The process of Getting Temporary Credentials indeed requires a call to AssumeRoleWithWebIdentity - this low level API call is implied in the higher level AWS SDK for JavaScript credentials provider call new AWS.WebIdentityCredentials() though, see e.g. Class: AWS.WebIdentityCredentials:
Represents credentials retrieved from STS Web Identity Federation
support.
By default this provider gets credentials using the
AWS.STS.assumeRoleWithWebIdentity() service operation. This operation
requires a RoleArn containing the ARN of the IAM trust policy for the
application for which credentials will be given. In addition, the
WebIdentityToken must be set to the token provided by the identity
provider. See constructor() for an example on creating a credentials
object with proper RoleArn and WebIdentityToken values.
Given the error message "Missing credentials in config", you are obviously passing an incorrect WebIdentityToken, which isn't a surprise given you just specified some ????????? placeholders ;) - since you already use Login with Amazon, which returns an access_token, you'll just need to pass the content of that ACCESS_TOKEN instead of those ????????? placeholders as value for WebIdentityToken and should be all set.
For other readers: Section 6. Putting it all together of Configuring Web Identity Federation in the Browser provides an example for retrieving the access token via Facebook Login. As noted there, Other identity providers will have a similar setup step that involves loading the respective SDK, logging in, and receiving an access token - in particular, how to handle Login with Amazon is documented in detail within Getting Started for Web.
Use AWS instance in this way:
var aws = AWS ;
var region = aws.config.region = 'us-east-1';
var cred = new aws.Credentials(<YOUR_ACCESS_KEY_ID>,
<YOUR_SECRET_ACCESS_KEY>, sessionToken = null);
To get ACCESS KEY ID and SECRET ACCESS_KEY go to:
AWS IAM>Users>Security Credentials>Access Keys
Now use aws instance for further operations.