EventBridge bus receives events from S3 bucket.
I need to create a rule that only handles S3 events from objects with Key prefix dir/sub-dir/ and suffix .pdf.
Tried the rule below, but it is handled as OR statement:
new events.Rule(this, 'MyRule', {
eventPattern: {
source: ['aws.s3'],
detailType: ['Object Created'],
detail: {
object: {
key: [
{ prefix: 'dir/sub-dir/' },
{
suffix: '.pdf',
},
],
},
},
},
})
Found a way to make it work, but I hope there is a better answer:
new events.Rule(this, 'MyRule', {
eventPattern: {
source: ['aws.s3'],
detailType: ['Object Created'],
detail: {
object: {
key: [
{ prefix: 'dir/sub-dir/' },
$or: [{ key: [{ suffix: '.pdf' }] }, { fieldThatDoesntExist: ['its a hack'] }],
],
},
},
},
})
Related
What is the way to convert the following data from
[{
"browsing_itemid": {
"list": [{
"element": "yyy"
}]
}
}, {
"browsing_itemid": {
"list": [{
"element": "xxx"
}]
}
}]
to this format?
[{
"browsing_itemid": {
"bag": [{
"array_element": "yyy"
}]
}
}, {
"browsing_itemid": {
"bag": [{
"array_element": "xxx"
}]
}
}]
Altering nested column names are not working using ALTER TABLE? Is Custom JS function, best way to do this?
I get the exception ValidationException: One of the required keys was not given a value
when I click on the Play button as instructed in an AWS workshop page. Any advice would be really helpful!
AppSync Mock endpoint is running at http://192.168.20.3:20002
Error while executing Local DynamoDB
{
"version": "2018-05-29",
"operation": "PutItem",
"attributeValues": {
"type": {
"S": "post"
},
"content": {
"S": "test"
},
"timestamp": {
"N": "1668425585"
},
"owner": {
"S": "7d8ca528-4931-4254-9273-ea5ee853f271::user1"
},
"__typename": {
"S": "Post"
}
},
"condition": {
"expression": "attribute_not_exists(#id)",
"expressionNames": {
"#id": "id"
}
},
"key": {}
}
ValidationException: One of the required keys was not given a value
Schema file
input AMPLIFY {
globalAuthRule: AuthRule = { allow: public }
} # FOR TESTING ONLY!
type Post
#model(
mutations: { create: "createPost", delete: "deletePost", update: null }
timestamps: null
subscriptions: { level: public }
)
#auth(
rules: [
{
allow: owner
ownerField: "owner"
provider: userPools
operations: [read, create, delete]
}
{ allow: private, provider: userPools, operations: [read] }
]
) {
type: String! # always set to 'post'. used in the SortByTimestamp GSI
id: ID!
content: String!
owner: String
timestamp: Int!
}
(I tried adding and removing the exclamation to the ID here)
Screenshot
i am experiencing very strange behaviour with my serverless application,
here is my serverless.ts file
import type { AWS } from '#serverless/typescript';
import {
hello,
} from '#functions';
const serverlessConfiguration: AWS = {
service: 'users',
frameworkVersion: '2',
// org: '<MY-ORG-NAME>',
// app: '<MY-APP-NAME>',
custom: {
esbuild: {
bundle: true,
minify: false,
sourcemap: true,
exclude: ['aws-sdk'],
target: 'node14',
define: { 'require.resolve': undefined },
platform: 'node',
},
'serverless-offline': {
httpPort: 4000,
},
ngrokTunnel: {
tunnels: [
{
port: 4000,
},
],
},
avatarUploadBucket: '<NAME>',
userReplicationTopic: '<NAME>',
replicatedUserRemovalTopic:
'<NAME>',
},
plugins: [
'serverless-esbuild',
'serverless-offline',
'serverless-ngrok-tunnel',
],
provider: {
name: 'aws',
runtime: 'nodejs14.x',
profile: '<MY-AWS-PROFILE>',
region: '<MY-REGION>',
stage: 'dev',
apiGateway: {
minimumCompressionSize: 1024,
shouldStartNameWithService: true,
},
iamRoleStatements: [
{
Effect: 'Allow',
Action: ['s3:*', 'sns:*'],
Resource: '*',
},
],
environment: {
AWS_NODEJS_CONNECTION_REUSE_ENABLED: '1',
NODE_OPTIONS: '--enable-source-maps --stack-trace-limit=1000',
USER_REPLICATION_TOPIC_ARN: {
Ref: 'UserReplicationSNSTopic',
},
REPLICATED_USER_REMOVAL_TOPIC_ARN: {
Ref: 'ReplicatedUserRemovalSNSTopic',
},
},
lambdaHashingVersion: '20201221',
},
functions: {
hello
},
resources: {
Resources: {
AvatarUploadBucket: {
Type: 'AWS::S3::Bucket',
Properties: {
BucketName: '${self:custom.avatarUploadBucket}',
AccessControl: 'PublicRead',
},
},
UserReplicationSNSTopic: {
Type: 'AWS::SNS::Topic',
Properties: {
TopicName: '${self:custom.userReplicationTopic}',
},
},
ReplicatedUserRemovalSNSTopic: {
Type: 'AWS::SNS::Topic',
Properties: {
TopicName: '${self:custom.replicatedUserRemovalTopic}',
},
},
},
},
outputs: {
snsTopics: {
ReplicatedUserRemovalSNSTopicARN: '!Ref ReplicatedUserRemovalSNSTopic',
},
},
};
module.exports = serverlessConfiguration;
i currently have org and app commented out and it works but if i uncomment them, and send request to the api endpoint i get following error Runtime.ImportModuleError: Error: Cannot find module 's_hello'
it is not about the contents of file since i get this error for every microservice i have and for every function in that microservice, for this commented out version, this is the handler (in aws console)
but if i uncomment it, this is the result
why does this happen?
P.S: I can see the upload also happen in serverless dashboard.
Our project use django-rest-swagger to manage API, and we would like to export all api and import Postman, I can get JSON by below url localhost:5000/swagger/?format=openapi, but when I import the file, postman says Error while importing: format not recognized, How to import swagger/?format=openapi to postman from django-rest-swagger without error of format not recognized?
Is there anyone who knows some easy way to solve it? Thanks so much for any advice!!!!!
{
swagger: "2.0",
info: {
title: "TestProjectAPI",
description: "",
version: ""
},
host: "localhost:5000",
schemes: [
"http"
],
paths: {
/api-token/: {
post: {
operationId: "api-token_post",
responses: {
201: {
description: ""
}
},
parameters: [
{
name: "data",
in: "body",
schema: {
type: "object",
properties: {
pic_id: {
description: "",
type: "string"
},
phonenumber: {
description: "",
type: "string"
},
checkcode: {
description: "",
type: "string"
},
user_phone: {
description: "",
type: "string"
},
phone_code: {
description: "",
type: "string"
},
username: {
description: "",
type: "string"
},
password: {
description: "",
type: "string"
}
}
}
}
],
description: "User Login",
summary: "User Login",
consumes: [
"application/json"
],
tags: [
"api-token"
]
}
},
/porject_management/: {
get: {
operationId: "porject_management_list",
responses: {
200: {
description: ""
}
},
parameters: [
{
name: "page",
required: false,
in: "query",
description: "A page number within the paginated result set.",
type: "integer"
},
{
name: "page_size",
required: false,
in: "query",
description: "Number of results to return per page.",
type: "integer"
},
{
name: "search",
required: false,
in: "query",
description: "A search term.",
type: "string"
},
{
name: "project",
required: false,
in: "query",
description: "",
type: "string"
},
{
name: "state",
required: false,
in: "query",
description: "",
type: "number"
},
{
name: "ordering",
required: false,
in: "query",
description: "Which field to use when ordering the results.",
type: "string"
}
],
description: "porject management",
summary: "porject management",
tags: [
"porject_management_post"
]
},
post: {
operationId: "porject_management_post",
responses: {
201: {
description: ""
}
},
parameters: [
{
name: "data",
in: "body",
schema: {
type: "object",
properties: {
project: {
description: "",
type: "string"
},
tc_code: {
description: "",
type: "string"
},
visitors_number: {
description: "",
type: "integer"
},
site_selection: {
description: "",
type: "string"
},
contact_name: {
description: "",
type: "string"
},
contact_number: {
description: "",
type: "string"
},
remark: {
description: "",
type: "string"
},
type: {
description: "",
type: "integer"
},
state: {
description: "",
type: "integer"
},
status: {
description: "",
type: "integer"
},
creater: {
description: "",
type: "string"
},
modifier: {
description: "",
type: "string"
}
}
}
}
],
description: "Porject management",
summary: "Porject management",
consumes: [
"application/json"
],
tags: [
"homemanager"
]
}
},
securityDefinitions: {
basic: {
type: "basic"
}
}
}
Have you tried using:
python3 manage.py generateschema --file openapi-schema.yml
in terminal? Then you can directly import the schema to your POSTMAN. You are providing JSON format, use yaml format for postman it should work.
Finally, I solved my problem by eolink.com,
Firstly, import JSON from localhost:5000/swagger/?format=openapi
Secondly, export Swagger by eolink.com, and then you can import that file to postman!!!
I am using Cloudformation template to create a stack including IoT fleet provisioning template and according to the document the IoT provisioning template body should be string type.
I have the IoT fleet provisioning template like this:
{
"Parameters": {
"SerialNumber": {
"Type": "String"
},
"AWS::IoT::Certificate::Id": {
"Type": "String"
}
},
"Resources": {
"certificate": {
"Properties": {
"CertificateId": {
"Ref": "AWS::IoT::Certificate::Id"
},
"Status": "Active"
},
"Type": "AWS::IoT::Certificate"
},
"policy": {
"Properties": {
"PolicyName": "mypolicy"
},
"Type": "AWS::IoT::Policy"
},
"thing": {
"OverrideSettings": {
"AttributePayload": "MERGE",
"ThingGroups": "REPLACE",
"ThingTypeName": "REPLACE"
},
"Properties": {
"AttributePayload": {
"SerialNumber": {
"Ref": "SerialNumber"
}
},
"ThingName": {
"Ref": "SerialNumber"
}
},
"Type": "AWS::IoT::Thing"
}
}
}
The Cloudformation template is like this:
AWSTemplateFormatVersion: '2010-09-09'
Description: "Template to create iot"
Resources:
FleetProvisioningTemplate:
Type: AWS::IoT::ProvisioningTemplate
Properties:
Description: Fleet provisioning template
Enabled: true
ProvisioningRoleArn: "arn:aws:iam::1234567890:role/IoT-role"
TemplateBody: String
TemplateName: mytemplate
I tried to use the JSON string of the IoT provisioning template for the template body but it didn't work. My question is how I can create an IoT provisioning template using Cloudformation template?
update
It turned out I can add the IoT provisioning template as a 'literal block'
AWSTemplateFormatVersion: '2010-09-09'
Description: "Template to create iot"
Resources:
FleetProvisioningTemplate:
Type: AWS::IoT::ProvisioningTemplate
Properties:
Description: Fleet provisioning template
Enabled: true
ProvisioningRoleArn: "arn:aws:iam::1234567890:role/IoT-role"
TemplateBody: |
{
"Parameters": {
"SerialNumber": {
"Type": "String"
},
"AWS::IoT::Certificate::Id": {
"Type": "String"
}
},
"Resources": {
"certificate": {
"Properties": {
"CertificateId": {
"Ref": "AWS::IoT::Certificate::Id"
},
"Status": "Active"
},
"Type": "AWS::IoT::Certificate"
},
"policy": {
"Properties": {
"PolicyName": "cto-full-function-dev"
},
"Type": "AWS::IoT::Policy"
},
"thing": {
"OverrideSettings": {
"AttributePayload": "MERGE",
"ThingGroups": "DO_NOTHING",
"ThingTypeName": "REPLACE"
},
"Properties": {
"AttributePayload": {},
"ThingGroups": [],
"ThingName": {
"Ref": "SerialNumber"
},
"ThingTypeName": "cto"
},
"Type": "AWS::IoT::Thing"
}
}
}
TemplateName: mytemplate
But as soon as I added the PreProvisioningHook as the cloudformation document says, the template fails with invalid request error.
AWSTemplateFormatVersion: '2010-09-09'
Description: "Template to create iot"
Resources:
LambdaHook:
Type: AWS::Lambda::Function
....
FleetProvisioningTemplate:
Type: AWS::IoT::ProvisioningTemplate
Properties:
Description: Fleet provisioning template
Enabled: true
ProvisioningRoleArn: "arn:aws:iam::1234567890:role/IoT-role"
PreProvisioningHook:
TargetArn: {
"Fn::GetAtt": [
"LambdaHook",
"Arn"
]
}
PayloadVersion: "1.0"
TemplateBody: |
{
"Parameters": {
"SerialNumber": {
"Type": "String"
},
"AWS::IoT::Certificate::Id": {
"Type": "String"
}
},
"Resources": {
"certificate": {
"Properties": {
"CertificateId": {
"Ref": "AWS::IoT::Certificate::Id"
},
"Status": "Active"
},
"Type": "AWS::IoT::Certificate"
},
"policy": {
"Properties": {
"PolicyName": "cto-full-function-dev"
},
"Type": "AWS::IoT::Policy"
},
"thing": {
"OverrideSettings": {
"AttributePayload": "MERGE",
"ThingGroups": "DO_NOTHING",
"ThingTypeName": "REPLACE"
},
"Properties": {
"AttributePayload": {},
"ThingGroups": [],
"ThingName": {
"Ref": "SerialNumber"
},
"ThingTypeName": "cto"
},
"Type": "AWS::IoT::Thing"
}
}
}
TemplateName: mytemplate
I also asked question on here but no luck. Did any one have the same issue and fix it?
I finally figured it out but want to share it in case someone is having the same question.
AWS IoT document doesn't mention this but if you want to add a PreProvisioningHook for your provisioning template, you need to give IoT access to the lambda, AKA PreProvisioningHook, so in the Cloudformation template, add something like this:
LambdaAddPermission:
Type: AWS::Lambda::Permission
Properties:
Action: lambda:InvokeFunction
FunctionName: !GetAtt PreProvisionHook.Arn
Principal: iot.amazonaws.com
In the Provisioning Template resource, make sure you have this:
PreProvisioningHook:
PayloadVersion: '2020-04-01'
TargetArn: {
"Fn::GetAtt": [
"PreProvisionHook",
"Arn"
]
}
in CDK you can opt to use a shorthand too:
preProvisioningHookLambda.grantInvoke(new iam.ServicePrincipal('iot.amazonaws.com')) // allow iot to invoke this function
This is the TS code I am using for everyones reference:
import * as cdk from '#aws-cdk/core';
import * as iam from '#aws-cdk/aws-iam';
import * as lambdaNodeJS from '#aws-cdk/aws-lambda-nodejs';
import * as iot from "#aws-cdk/aws-iot";
const props = {
stage: 'development'
}
const PolicyName = "DevicePolicy";
const templateName = 'DeviceProvisioningTemplateV1';
const templateBody = {
Parameters: {
SerialNumber: {
Type: "String"
},
ModelType: {
Type: "String"
},
"AWS::IoT::Certificate::Id": {
Type: "String"
}
},
Resources: {
certificate: {
Properties: {
CertificateId: {
Ref: "AWS::IoT::Certificate::Id"
},
Status: "Active"
},
Type: "AWS::IoT::Certificate"
},
policy: {
Properties: {
PolicyName
},
Type: "AWS::IoT::Policy"
},
thing: {
OverrideSettings: {
AttributePayload: "MERGE",
ThingGroups: "DO_NOTHING",
ThingTypeName: "REPLACE"
},
Properties: {
ThingGroups: [],
ThingName: {
Ref: "SerialNumber"
}
},
Type: "AWS::IoT::Thing"
}
}
};
const preProvisioningHookLambda = new lambdaNodeJS.NodejsFunction(this, `provisioning-hook-lambda-${props?.stage}`, {
entry: './src/lambda/provisioning/hook.ts',
handler: 'handler',
bundling: {
externalModules: [
]
},
timeout: cdk.Duration.seconds(5)
});
preProvisioningHookLambda.grantInvoke(new iam.ServicePrincipal('iot.amazonaws.com')) // allow iot to invoke this function
// Give the AWS IoT service permission to create or update IoT resources such as things and certificates in your account when provisioning devices
const provisioningRole = new iam.Role(this, `provisioning-role-arn-${props?.stage}`, {
assumedBy: new iam.ServicePrincipal('iot.amazonaws.com'),
});
provisioningRole.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSIoTThingsRegistration'));
new cdk.CfnOutput(this, 'provisioningRoleArn ', { value: provisioningRole.roleArn || 'undefined' });
const provisioningTemplate = new iot.CfnProvisioningTemplate(this, `provisioning-hook-template-${props?.stage}`, {
provisioningRoleArn: provisioningRole.roleArn,
templateBody: JSON.stringify(templateBody),
enabled: true,
templateName,
preProvisioningHook: {
payloadVersion: '2020-04-01',
targetArn: preProvisioningHookLambda.functionArn,
}
});
new cdk.CfnOutput(this, 'preProvisioningLambdaFunctionName ', { value: preProvisioningHookLambda.functionName || 'undefined' });
new cdk.CfnOutput(this, 'provisioningTemplateName ', { value: provisioningTemplate.templateName || 'undefined' });
Base on the answer by Z Wang, this is how you do it in the AWS CDK:
myLambda.addPermission('InvokePermission', {
principal: new ServicePrincipal('iot.amazonaws.com'),
action: 'lambda:InvokeFunction',
});