Error when using update-data-set-permissions to share dataset with custom namespace | Amazon Quicksight - amazon-quicksight

The cli documentation (https://docs.aws.amazon.com/cli/latest/reference/quicksight/update-data-set-permissions.html) mentions
The ARN of an Amazon QuickSight user, group, or namespace associated with an analysis, dashboard, template, or theme. (This is common.)
for Principal but using an ARN of a principal is returning the error
An error occurred (InvalidParameterValueException) when calling the UpdateDataSetPermissions operation: Malformed principal arn:aws:quicksight:us-east-1: 11122233344:namespace/10
The command I used is
aws quicksight update-data-set-permissions --cli-input-json file://datapermissions.json
The Json file contains:
{
"AwsAccountId": "11122233344",
"DataSetId": "dummy-3d53-4e31-b6cb-c53d445ea75b",
"GrantPermissions": [
{
"Principal": "arn:aws:quicksight:us-east-1:11122233344:namespace/10",
"Actions": [
"quicksight:DescribeDataSet",
"quicksight:DescribeDataSetPermissions",
"quicksight:PassDataSet",
"quicksight:DescribeIngestion",
"quicksight:ListIngestions"
]
}
]
}

Related

Testing Java lambda function via API Gateway: Unable to determine service/operation name to be authorized

I'm playing around with API Gateway. Basically, I have a simple java code that aims to return a greetings message:
public class Greetings implements RequestHandler<GreetingsRequest, String> {
//enable pretty print JSON output
Gson gson = new GsonBuilder().setPrettyPrinting().create();
public String handleRequest(GreetingsRequest input, Context context) {
LambdaLogger logger = context.getLogger();
System.out.println("Welcome to lambda function");
// log execution details
logger.log("ENVIRONMENT VARIABLES: " + gson.toJson(System.getenv()));
logger.log("CONTEXT: " + gson.toJson(context));
// process event
logger.log("EVENT: " + gson.toJson(input));
logger.log("EVENT TYPE: " + input.getClass().toString());
return "Hello " + input.getName();
}
}
I've attached to the lambda function a role with the following characteristics:
4 default policies (AmazonAPIGatewayInvokeFullAccess, CloudWatchFullAccess, AmazonAPIGatewayAdministrator, AWSLambdaBasicExecutionRole) and a custom one (lambda_execute).
Role's Trust Relationship:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": [
"lambda.amazonaws.com",
"apigateway.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
}
In relation to the custom policy "lambda_execute":
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "lambda:InvokeFunction",
"Resource": "*"
}
]
}
In relation to the API Gateway:
The resource:
The method request:
The integration request:
When I am testing out the resource, the following message is sent out:
<AccessDeniedException>
<Message>Unable to determine service/operation name to be authorized</Message>
</AccessDeniedException>
Anyone could point me out what I'm missing or doing wrong? Tks so much in advance.
Two options to invoke Lambda function from Api Gateway REST Api.
Integration Type Lambda: just need to give Lambda function name.
Integration Type AWS Service: This method is also used to send events directly from Api Gateway to other aws services like Sns, Sqs, Kinesis, etc.
Question is about using second method of invoking lambda using AWS Service.
PathOverride proxies request from Api Gateway to different endpoint.
Full endpoint to invoke a Lambda function is https://lambda.us-east-1.amazonaws.com/2015-03-31/functions/arn:aws:lambda:us-east-1:111122223333:function:my-function-name/invocations
First part https://lambda.us-east-1.amazonaws.com/ will be appended by Api Gateway, second part 2015-03-31/functions/arn:aws:lambda:us-east-1:111122223333:function:my-function-name/invocations should be given in path override.
if path override is incorrect, thats when we get Unable to determine service/operation name to be authorized Error.

Laravel / AWS S3 - How to validate a file being uploaded using a Pre-Signed URL

How does one validate files uploaded straight to S3 using a Pre-Signed URL?
Normally when uploading through Laravel, you can just validate the request using rules, such as:
[
'image' => 'required|file|mimes:jpeg,png,pdf|max:2500',
]
However when using a Pre-Signed URL, the file goes straight to the S3 storage and Laravel only receives a string for the path or URL to the file/image.
Is there a way to determine rules when creating the S3 Pre-Signed URL for them to only accept certain files? Or can I get the Laravel app to retrieve the file from S3 storage afterwards and validate it using the same Validation rules?
In terms of your web app, there are no additional parameters to limit file type and such (as of now). You could implement additional client-side validation (which could help but most likely won't solve the problem).
However, you could use S3 policy statements to limit file types and other things:
Allow the s3:PutObject action only for objects that have the extension of the file type that you want
Explicitly deny the s3:PutObject action for objects that don't have the extension of the file type that you want Note: You need this
explicit deny statement to apply the file-type requirement to users
with full access to your Amazon S3 resources. The following example
bucket policy allows the s3:PutObject action only for objects with
.jpg, .png, or .gif file extensions.
Important: For the first Principal value, list the Amazon Resource
Names (ARNs) of the users that you want to grant upload permissions
to. For the Resource and NotResource values, be sure to replace
bucket-name with the name of your bucket.
{
"Version": "2012-10-17",
"Id": "Policy1464968545158",
"Statement": [
{
"Sid": "Stmt1464968483619",
"Effect": "Allow",
"Principal": {
"AWS": "IAM-USER-ARN"
},
"Action": "s3:PutObject",
"Resource": [
"arn:aws:s3:::bucket-name/*.jpg",
"arn:aws:s3:::bucket-name/*.png",
"arn:aws:s3:::bucket-name/*.gif"
]
},
{
"Sid": "Stmt1464968483619",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:PutObject",
"NotResource": [
"arn:aws:s3:::bucket-name/*.jpg",
"arn:aws:s3:::bucket-name/*.png",
"arn:aws:s3:::bucket-name/*.gif"
]
}
]
}
Another thing is to use CORS to specify the allowed origin.

Correct terraform syntax for adding permissions to AWS Lambda

I'm learning Terraform and I'm trying to get the correct syntax to specify the IAM role permissions for it. I want these capabailities:
Lambda can be invoked from an API Gateway that I also create in Terraform
Lambda can write to Cloudwatch logs
I have the following which allows the API gateway to invoke the Lambda:
resource "aws_iam_role" "my_lambda_execution_role" {
name = "my_lambda_execution_role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": [
"lambda.amazonaws.com",
"apigateway.amazonaws.com"
]
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
I have seen the snippet below allows the Lambda to write to CloudWatch. I'm trying to combine these snippets to get all of the permissions but I can't get it right. What is the correct syntax to give all of these permissions to the role?
{
"Statement": [
{
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Effect": "Allow",
"Resource": "arn:aws:logs:*:*:*"
}
]
}
https://www.terraform.io/docs/providers/aws/r/iam_role_policy_attachment.html
You need to create the policy and then attach it to your role. The link above includes a more complete example than on the iam role page.
IAM policy along with role.
# iam
data "aws_iam_policy_document" "policy" {
statement {
sid = ""
effect = "Allow"
principals {
identifiers = ["lambda.amazonaws.com"]
type = "Service"
}
actions = ["sts:AssumeRole"]
}
}
resource "aws_iam_role" "iam_for_lambda" {
name = "iam_for_lambda"
assume_role_policy = "${data.aws_iam_policy_document.policy.json}"
}
resource "aws_iam_role_policy" "frontend_lambda_role_policy" {
name = "frontend-lambda-role-policy"
role = "${aws_iam_role.iam_for_lambda.id}"
policy = "${data.aws_iam_policy_document.lambda_log_and_invoke_policy.json}"
}
data "aws_iam_policy_document" "lambda_log_and_invoke_policy" {
statement {
effect = "Allow"
actions = [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
]
resources = ["*"]
}
statement {
effect = "Allow"
actions = ["lambda:InvokeFunction"]
resources = ["arn:aws:lambda:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:function:*"]
}
}
Please find the complete terraform code at my github
In a previous answer I wrote up some background information on how IAM roles work and what an "assume role policy" is. I'm going to assume that background information in this answer.
The policy you've given in your assume_role_policy argument in the resource "aws_iam_role" "my_lambda_execution_role" block is the policy governing which users and services are allowed to "assume" this role. In this case, you are allowing AWS Lambda and Amazon API Gateway to make requests using the privileges granted by this role.
However, by default the role doesn't grant any privileges at all. To address that, we need to attach one or more access policies to the role. The other policy JSON you shared here is an access policy, and to associate it with the role we need to use the aws_iam_role_policy resource type:
resource "aws_iam_role_policy" "logs" {
name = "lambda-logs"
role = aws_iam_role.my_lambda_execution_role.name
policy = jsonencode({
"Statement": [
{
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
],
"Effect": "Allow",
"Resource": "arn:aws:logs:*:*:*",
}
]
})
}
Usually Terraform automatically infers dependencies between resource blocks by noticing references like the aws_iam_role.my_lambda_execution_role expression in the above, and indeed in this case Terraform will determine automatically that it needs to complete the creation of the role before attempting to attach the policy to it.
However, Terraform cannot see automatically here that the policy attachment must complete before the policy itself is operable, and so when you refer to the role from your API Gateway and Lambda resources you must use depends_on to tell Terraform that the policy attachment must complete before the policy will become usable:
resource "aws_lambda_function" "example" {
filename = "${path.module}/example.zip"
function_name = "example"
role = aws_iam_role.my_lambda_execution_role.arn
handler = "example"
# (and any other configuration you need)
# Make sure the role policy is attached before trying to use the role
depends_on = [aws_iam_role_policy.logs]
}
If you don't use depends_on like this, there is a risk that the function will be created and executed before the role attachment is complete, and thus initial executions of your function could fail to write their logs. If your function is not executed immediately after it's created then this probably won't occur in practice, but it's good to include the depends_on to be thorough and to let a future human maintainer know that the role's access policy is also important for the functionality of the Lambda function.

Using AWS lambda function to call lex chat bot

I am trying to use boto3 from within AWS lambda function in order to do post_text to a Lex chat bot.
Python code:
client = boto3.client('lex-runtime')
data = "string input"
response = client.post_text(
botName='xxx',
botAlias='yyy',
userId='id',
inputText= data)
but i get:
An error occurred (AccessDeniedException) when calling the PostText
operation: User: arn:aws:sts::111111111:assumed-
role/functionName/functionName is not authorized to perform: lex:PostText on
resource: arn:aws:lex:us-east-1:111111111:bot:xxx:yyyy"
So i set up IAM rule an and policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"lex:PostText"
],
"Resource": [
"arn:aws:lex:us-east-1:111111111:bot:xxx:yyyy"
]
}
]
}
Trust relationship:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
But it still doesn't work and i get the same error.
I experienced the same issue recently.
It is most certainly related to the permissions assigned to the IAM role that you're using when running the Lambda function.
The easiest way to resolve this is below:-
Open the Lambda function on the AWS Console.
Scroll down to the "Execution role" section.
Click the link under the role to view the role in a new window. It
should look something like this: "View the role".
In the new window under the permissions tab click on "Attach
policies".
This takes you to a new screen. On this screen filter the listed
policies by typing in "lex" in the input field.
The filtered list will contain a policy call "AmazonLexRunBotsOnly".
Attach this policy to your role.
Save the changes and make your way back to your lambda function.
Save the lambda function and retest.
This will resolve your issue.

Serverless framework Lambda AppSync error

I'm using the serverless framework to upload an AWS Lambda function to be used as a data source in AppSync. The serverless.yml that I have is very basic:
service: mongoose-lambda-srvrls
provider:
name: aws
runtime: nodejs6.10
region: us-west-2
functions:
mongoose:
handler: index.handler
When I run an AppSync GraphQL query I get the error:
{
"data": {
"getPost": null
},
"errors": [
{
"path": [
"getPost"
],
"data": null,
"errorType": "Lambda:AWSLambdaException",
"errorInfo": null,
"locations": [
{
"line": 43,
"column": 2
}
],
"message": "User: arn:aws:sts::433333333335:assumed-role/appsync-datasource-lam-kkzuep-mongoose-lambda-srvr/APPSYNC_ASSUME_ROLE is not authorized to perform: lambda:InvokeFunction on resource: arn:aws:lambda:us-west-2:43333333333335:function:mongoose-lambda-srvrls-dev-mongoose (Service: AWSLambda; Status Code: 403; Error Code: AccessDeniedException; Request ID: 9fa82eb9-3a64-11e8-88a1-09c4e639fc45)"
}
]
}
I'm pretty sure that I need to flesh out my YML so that this lambda stack will play nice with AppSync but I'm not quite sure what to do.
A little more info. When looking at the resources in Lambda's CloudFormation, I see:
IamRoleLambdaExecution mongoose-lambda-srvrls-dev-us-west-2-lambdaRole AWS::IAM::Role
MongooseLambdaFunction mongoose-lambda-srvrls-dev-mongoose AWS::Lambda::Function
MongooseLambdaVersionwCQ1... arn:aws:lambda:us-west-2:4542242445:function:mongoose-lambda-srvrls-dev-mongoose:4 AWS::Lambda::Version
MongooseLogGroup /aws/lambda/mongoose-lambda-srvrls-dev-mongoose AWS::Logs::LogGroup
ServerlessDeploymentBucket mongoose-lambda-srvrls-d-serverlessdeploymentbuck-qwp8sdfgjr AWS::S3::Bucket
Whereas in the Lambda that I made using the AppSync docs (AWS CLI) has the following CloudFormation resources:
AppSyncLambdaInvokePolicy Fulls-AppS-15SHASDFSADZ03N AWS::IAM::Policy
AppSyncServiceRole Fullstack-Lamba-AppSyncServiceRole-DK8QHASDFE5R AWS::IAM::Role
LambdaExecutionRole Fullstack-Lamba-LambdaExecutionRole-OJHASDF3AHG1 AWS::IAM::Role
LambdaFunction fullstack-lambda AWS::Lambda::Function
It looks like the role you gave AppSync to run the lambda function does not have permission to invoke that particular lambda.
You will need to create or modify a role so it has the following permissions.
The IAM role should have a policy which enables anybody who assumes it to run/invoke your lambda function:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"lambda:Invoke"
],
"Resource": "arn:aws:lambda:REGION:ACCOUNTNUMBER:function/LAMBDA_FUNCTION"
}
]
}
The role should also have a trust policy. This trust policy will allow AppSync to assume the role on your behalf. This is how AppSync invokes your lambda whenever a graphQL request comes in.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "appsync.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
Once you have an IAM role with necessary permissions, you will need to make sure it is associated with the lambda data source in AppSync. You can select the role in the Data Sources section of the AppSync console or use the AppSync CLI to update the lambda data source and make it use your role.
For more information about creating a lambda function which plays nice with AppSync, here is the documentation: https://docs.aws.amazon.com/appsync/latest/devguide/tutorial-lambda-resolvers.html#configure-data-source-for-aws-lambda
I think they made a mistake in the https://docs.aws.amazon.com/appsync/latest/devguide/tutorial-lambda-resolvers.html#configure-data-source-for-aws-lambda documentation.
The allowed action should be lambda:InvokeFunction and NOT lambda:Invoke
This is working:
{
"Version" : "2012-10-17",
"Statement" : [{
"Effect" : "Allow",
"Action" : "lambda:InvokeFunction",
"Resource" : "arn:aws:lambda:REGION:ACCOUNTNUMBER:function/LAMBDA_FUNCTION"
}]
}

Resources