Appsync Query Returning Null with Cognito Auth - amazon-web-services

I'm trying to do some appsync in the console using a userpool user who is a part of the group.
However, my query is returning null in the response.
The below PK in my query definitely exists.
I suspect that the issue is related to cognito. I can't pin it down exactly. The user I am testing is in the customers group and I am not receiving an error there due to cognito group permissions.
Logs are not helpful.
If I create a new API in the console (using an API key rather than cognito for auth) and import the dynamodb table (using the same role), the same query returns data.
Do I need to give my cognito group a role that allows them to interact with appsync?
My query:
query MyQuery {
getTable(PK: "PRODUCT#cb699976-153c-4852-a455-bc9a7bce6a93", SK: "PRODUCT#BLEND") {
DK1
PK
SK
}
}
The response:
{
"data": {
"getTable": null
}
}
The Schema:
type Query {
getTable(PK: String!, SK: String!): Table
#aws_auth(cognito_groups: ["customers"])
}
type Table #aws_auth(cognito_groups: ["customers"]) {
DK1: String
PK: String!
SK: String!
}
iam role for dynamodb (least permission access is still todo)
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Action": "dynamodb:*",
"Resource": [
"arn:aws:dynamodb:us-east-1:blah_account:table/blah_table/index/GSI1",
"arn:aws:dynamodb:us-east-1:blah_account:table/blah_table"
]
}
]
}
appsync role trust relationship
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "appsync.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
appsync config ($ aws appsync get-graphql-api):
{
"graphqlApi": {
"name": "blah_dev_appsync",
"apiId": "blah",
"authenticationType": "AMAZON_COGNITO_USER_POOLS",
"userPoolConfig": {
"userPoolId": "us-east-1_blah",
"awsRegion": "us-east-1",
"defaultAction": "DENY"
},
"arn": "arn:aws:appsync:us-east-1:blah_id:apis/blah_",
"xrayEnabled": false
}
}

Can you check if there is a resolver attached to your (failing) Appsync API ?
If you have access to the web console look for this screen:
If there is nothing attached to getTable then that's probably why you are having null answers.
Resolvers Docs

Thanks to Ivan Caracamo's response, I learned that I needed to properly configure my resolvers.
I was able to get there with the resolver docs and this post.
Here's my request template
{
"version": "2017-02-28",
"operation": "GetItem",
"key": {
"PK": $util.dynamodb.toDynamoDBJson($ctx.args.PK),
"SK": $util.dynamodb.toDynamoDBJson($ctx.args.SK),
},
}
And here's my response template
$util.toJson($ctx.result)

Related

500 Internal Server Error using DeleteItem from DynamoDB using API-Gateway

Steps to reproduce:
Create a new DynamoDB table Events with partition key id
Create a new item in Events with an id of 123456. All other fields are blank.
Create an API-Gateway. Create path of events and a resource of remove-event under it.
Create a method of POST. AWS Service, DynamoDB, , and an action of DeleteItem. Add an IAM role that has access to the Events table too.
Open postman. Fill out the authorization and add the following parameters:
POST https://<DB GOES HERE>.execute-api.us-east-2.amazonaws.com/prod/events/remove-event
In the body, put (This is following the provided sample request here):
{
"TableName": "Events",
"Key": {
"id": {
"S": "123456"
}
},
"ReturnValues": "NONE"
}
Finally, hit send.
{
"message": "Internal server error"
}
I have no idea what is causing this. Create, Update, and Read work with issue. It is ONLY Delete that fails.
EDIT: In case anyone is curious about my policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "execute-api:Invoke",
"Resource": "arn:aws:execute-api:*:<sensitive infomation>:*/*/*/*"
}
]
}
Removing this changes the 500 response to a 403, so this is not a policy issue.

AWS Amplify Storage.get() - AWSAccessKeyId is undefined

I'm struggling with a react native project utilizing AWS amplify, both Auth and Storage.
Calling Storage from this service file in my project:
import Amplify, {Auth, Storage} from 'aws-amplify'
import config from './config'
Amplify.configure({
Auth: config.Auth,
Storage: config.Storage,
})
export {
Auth,
Storage,
}
config is:
AWS: {
Auth: {
region: 'us-east-X',
userPoolId: 'us-east-XXXXXXX',
userPoolWebClientId: 'XXXXXXXXX',
identityPoolId: 'us-east-X:XXXXXXXXXXXXXX',
},
Storage: {
AWSS3: {
bucket: 'XXXXXXX',
region: 'us-east-X',
},
},
},
By this point, the user has authenticated with Auth. Calling:
Storage.get('public/fileName.gif', { expires: 120 })
Results in a signed URL that appears to be missing the access key, which it should be generating from the IAM logged in user.
Here's an example signed URL it generates:
https://expyhealth-stg.s3.amazonaws.com/public/activityImages/Ankle%20Pumps.gif?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=undefined%2F20201020%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20201020T204616Z&X-Amz-Expires=120&X-Amz-Signature=f40bad142a9b190f9d9959bb9db0ad077c0cecab5171098f033a700cb9aa45b5&X-Amz-SignedHeaders=host&x-amz-user-agent=aws-sdk-js-v3-react-native-%40aws-sdk%2Fclient-s3%2F1.0.0-gamma.8%20aws-amplify%2F3.6.0%20react-native&x-id=GetObject"
Notice the X-Amz-Credential=undefined
I've been following the thread here for hours and keep coming up short. I cannot determine why it isn't generating the access key.
Using aws-amplify version 3.3.4
Here is the bucket policy:
{
"Version": "2012-10-17",
"Id": "Policy1599854584652",
"Statement": [
{
"Sid": "Stmt1599854581275",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::XXXXXXXXXXXX:role/Cognito_ExpyHealthStagingAuth_Role"
},
"Action": "s3:GetObject",
"Resource": [
"arn:aws:s3:::XXXXXXXX",
"arn:aws:s3:::XXXXXXXX/*"
]
}
]
}
I solve a similar issue by editing the IAM trust relationship as follows:
Open the AWS console
Go to IAM
Go to roles
Select the role specified as the Authenticated role of your identity pool
Open "Trust Relationship" tab
Click "Edit trust relationship"
Paste the following:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "cognito-identity.amazonaws.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"cognito-identity.amazonaws.com:aud": "eu-west-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
},
"ForAnyValue:StringLike": {
"cognito-identity.amazonaws.com:amr": "authenticated"
}
}
}
]
}
Tip: compare your configuration with the one generated by the AWS Amplify CLI.

How to solve the error ""Message":"User: anonymous is not authorized to perform: iam:PassRole on resource"

I am trying to register a snapshot for my elasticsearch on AWS. My goal is to create a snapshot of elasticsearch domain on a s3 bucket. Below is the command I am using:
curl -XPUT https://vpc-xxxxxxx.ap-southeast-2.es.amazonaws.com/_snapshot/es-snapshot -d '
{
"type": "s3",
"settings": {
"bucket": "$MY_BUCKET",
"region": "ap-southeast-2",
"role_arn": "arn:aws:iam::xxxx:role/es-snapshot-role"
}
}'
But I got this error:
{"Message":"User: anonymous is not authorized to perform: iam:PassRole on resource: arn:aws:iam::xxxx:role/es-snapshot-role"}
It seems like a role permission issue. I have configured the role policy as:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Action": [
"es:*",
"s3:*",
"iam:PassRole",
"es:ESHttpPut"
],
"Resource": [
"*"
]
}
]
}
And its trust relationship is:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "es.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
I wonder what else I missed here.
This post AccessDenied for EC2 Instance with attached IAM Role doesn't seem to relate to my issue.
Registering a Manual Snapshot Repository
You must register a snapshot repository with Amazon Elasticsearch Service before you can take manual index snapshots. This one-time operation requires that you sign your AWS request with credentials that are allowed to access TheSnapshotRole, as described in Manual Snapshot Prerequisites.
You can't use curl to perform this operation, because it doesn't support AWS request signing. Instead, use the sample Python client, Postman, or some other method to send a signed request to register the snapshot repository. The request takes the following form:
PUT elasticsearch-domain-endpoint/_snapshot/my-snapshot-repo
{
"type": "s3",
"settings": {
"bucket": "s3-bucket-name",
"region": "region",
"role_arn": "arn:aws:iam::123456789012:role/TheSnapshotRole"
}
}
Reference from AWS Documentation: Working with Amazon Elasticsearch Service Index Snapshots
Add iam:PassRole permissions to your IAM user and try the command,

AWS IoT policy doesn't restrict access

I am trying to restrict access to my AWS IoT devices with a Policy, but my policy doesn't seem to do that. It still lets me do whatever I want to the device. The policy is practically useless. To test this, I removed the following action.
{
"Effect": "Allow",
"Action": "iot:UpdateThingShadow",
"Resource": "arn:aws:iot:us-east-1:**********:thing/${iot:Connection.Thing.ThingName}"
}
So now my policy is this:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "iot:GetThingShadow",
"Resource": "arn:aws:iot:us-east-1:**********:thing/${iot:Connection.Thing.ThingName}"
}
]
}
However, when I try to update my thing shadow like so:
var params = {
thingName: "bar",
payload: JSON.stringify({ // payload is in string form according to docs
"state": {
"desired": {
"state": 0
}
}
})
};
await iotdata.updateThingShadow(params, function (err, data) {
if (err){
}
else{
}
});
... it still updates my device's shadow. My policy says it can't do that though! How can I get my policy to work?
In my experience,
It takes some minutes to apply completely.
I think you changed your policy and then run your test code ASAP. right?

Assigning permission to single cognito user access to a secret created on AWS's Secret Manager

I have created a secret on AWS's Secrets Manager. I have a python service with cognito authentication, and I want to assign to a particular user permission to get this secret. I created the following policy to allow users to get the secret's value.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue",
"secretsmanager:DescribeSecret"
],
"Resource": "arn:aws:secretsmanager:*:*:secret:test_secret*"
}
]
}
I've then assigned this policy to my cognito identity pool's Authenticated role. Now every user in this pool has permission to get this secret's value. But I need to assign this permission to a single user, not all of them. Is there any way to do this?
You can put this user in a group and let this group assume a IAM Role.
Then attach the right to the IAM Role.
Role-Based Access Control
You can write your authenticated user IAM policy in a way that it only allows them permission to access resources that they create. E.g.:
Instantiate an AWS secretsmanager client using the ID token you get from CognitoIdentity
Specify your authenticated policy to look something like this:
{
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Action": [
"secretsmanager:UpdateSecret",
"secretsmanager:PutSecretValue",
"secretsmanager:DescribeSecret",
"secretsmanager:DeleteSecret"
],
"Resource": "*",
"Condition": {
"ForAllValues:StringEquals": {
"aws:TagKeys": [
"Sub",
"Service"
]
},
"StringEquals": {
"secretsmanager:ResourceTag/Service": "MYSERVICE",
"secretsmanager:ResourceTag/Sub": "${cognito-identity.amazonaws.com:sub}"
}
}
},
{
"Sid": "",
"Effect": "Allow",
"Action": [
"secretsmanager:TagResource",
"secretsmanager:CreateSecret"
],
"Resource": "*",
"Condition": {
"ForAllValues:StringEquals": {
"aws:TagKeys": [
"Sub",
"Service"
]
},
"StringEquals": {
"aws:RequestTag/Service": "MYSERVICE",
"aws:RequestTag/Sub": "${cognito-identity.amazonaws.com:sub}"
}
}
}
]
}
}
3) When you create the secret, be sure to apply tags in the CreateSecret request that map to your users identitypoolid and service name. (If you don't, your request will fail.)
Your users will now only be able to access secrets that they create. This is secure because the "${cognito-identity.amazonaws.com:sub}" value will be interpolated based on the AWS SDK session credentials. I.e. your other users' clients will have different "sub" values embedded as part of their session credentials, so they won't be able to access secrets they didn't create.