Skip to content

Commit f7d5742

Browse files
Finish README docs
1 parent d86257a commit f7d5742

File tree

1 file changed

+235
-53
lines changed

1 file changed

+235
-53
lines changed

README.md

Lines changed: 235 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,24 @@ What you will learn at the end of this tutorial is how to execute a Lambda Funct
66

77
If you want to learn why you should care about image optimizations I encourage you to visit [web.dev](web.dev), especially [Fast load times](https://web.dev/fast).
88

9+
## Notice
10+
11+
This Lambda function uses a pure Javascript image optimizaction ([Jimp](https://www.npmjs.com/package/jimp)). For a better performant solution consider using Imagemin or GraphicsMagic.
12+
913
## Architecture
1014

1115
![Architecture overview](/assets/architecture_overview.jpg)
1216

1317
S3 Bucket structure will be the following:
1418

15-
\- prefix-gallery
16-
   |--- /original 
 

17-
   |---  | --- /image.jpg 
 

18-
   |--- /thumbs 
 

19-
   |---  | --- /image_original.jpg 
 

20-
   |---  | --- /image_thumb_1200.jpg 
 

21-
   |---  | --- /image_thumb_640.jpg 
 

22-
   |---  | --- /image_thumb_420.jpg 
 

19+
* prefix-gallery
20+
*  ├─── /original
21+
*  ├────┼─── /image.jpg
22+
*  ├─── /thumbs
23+
*  ├────┼─── /image_original.jpg
24+
*  ├────┼─── /image_thumb_1200.jpg
25+
*  ├────┼─── /image_thumb_640.jpg
26+
*  └────┴─── /image_thumb_420.jpg
2327

2428
### Workflow
2529

@@ -29,6 +33,10 @@ S3 Bucket structure will be the following:
2933
4. Lambda Function resize and compress image to generate 4 new images.
3034
5. Lambda Function upload optimized images to `/thumbs` folder.
3135

36+
## prerequisites
37+
38+
This tutorial asumes you have an AWS account and you've configured AWS credentials for CLI, if you haven't [please do so](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html#post-install-configure).
39+
3240
## S3
3341

3442
Let's create an S3 bucket. You can do this though the console or using the AWS CLI. named it `{prefix}-gallery`. Replace prefix with a unique identifier so that S3 name is [globally unique](https://docs.aws.amazon.com/AmazonS3/latest/dev/BucketRestrictions.html). I'll use `rtalexk-gallery`, as my username.
@@ -37,14 +45,16 @@ Let's create an S3 bucket. You can do this though the console or using the AWS C
3745

3846
```bash
3947
(bash)$ aws s3 mb s3://rtalexk-gallery
40-
output: make_bucket: rtalexk-gallery
48+
----------------
49+
make_bucket: rtalexk-gallery
4150
```
4251

4352
You can list your buckets to make sure it was created successfuly:
4453

4554
```bash
4655
(bash)$ aws s3 ls
47-
output: 2019-08-13 10:53:34 rtalexk-gallery
56+
----------------
57+
2019-08-13 10:53:34 rtalexk-gallery
4858
```
4959

5060
## Execution role
@@ -83,25 +93,25 @@ And now we can create the role:
8393
Output:
8494
```json
8595
{
86-
"Role": {
87-
"AssumeRolePolicyDocument": {
88-
"Version": "2012-10-17",
89-
"Statement": [
90-
{
91-
"Action": "sts:AssumeRole",
92-
"Effect": "Allow",
93-
"Principal": {
94-
"Service": "lambda.amazonaws.com"
95-
}
96-
}
97-
]
98-
},
99-
"RoleId": "AROAWLOEJBDOVF57FGKGJ",
100-
"CreateDate": "2019-08-13T16:44:30Z",
101-
"RoleName": "role-lambda-s3",
102-
"Path": "/",
103-
"Arn": "arn:aws:iam::123456789123:role/role-lambda-s3"
104-
}
96+
"Role": {
97+
"AssumeRolePolicyDocument": {
98+
"Version": "2012-10-17",
99+
"Statement": [
100+
{
101+
"Action": "sts:AssumeRole",
102+
"Effect": "Allow",
103+
"Principal": {
104+
"Service": "lambda.amazonaws.com"
105+
}
106+
}
107+
]
108+
},
109+
"RoleId": "AROAWLOEJBDOVF57FGKGJ",
110+
"CreateDate": "2019-08-13T16:44:30Z",
111+
"RoleName": "role-lambda-s3",
112+
"Path": "/",
113+
"Arn": "arn:aws:iam::123456789123:role/role-lambda-s3"
114+
}
105115
}
106116
```
107117

@@ -121,12 +131,12 @@ Output:
121131

122132
```json
123133
{
124-
"AttachedPolicies": [
125-
{
126-
"PolicyName": "AWSLambdaExecute",
127-
"PolicyArn": "arn:aws:iam::aws:policy/AWSLambdaExecute"
128-
}
129-
]
134+
"AttachedPolicies": [
135+
{
136+
"PolicyName": "AWSLambdaExecute",
137+
"PolicyArn": "arn:aws:iam::aws:policy/AWSLambdaExecute"
138+
}
139+
]
130140
}
131141
```
132142

@@ -144,7 +154,8 @@ This command will install dependencies for the function and generate a zip file.
144154

145155
```bash
146156
(bash) $ aws s3 cp code.zip s3://rtalexk-gallery/code.zip
147-
output: upload: ./code.zip to s3://rtalexk-gallery/code.zip
157+
----------------
158+
upload: ./code.zip to s3://rtalexk-gallery/code.zip
148159
```
149160

150161
Now we can create the function and reference the code from S3:
@@ -169,22 +180,22 @@ Output:
169180

170181
```json
171182
{
172-
"TracingConfig": {
173-
"Mode": "PassThrough"
174-
},
175-
"CodeSha256": "jz9MRd5XnUBqMdqncN7d7Fxg+edH2ctkqPbMFTteNmU=",
176-
"FunctionName": "imageProcessing",
177-
"CodeSize": 49657600,
178-
"RevisionId": "293ca655-251f-4400-a13b-fc2241c5ea23",
179-
"MemorySize": 512,
180-
"FunctionArn": "arn:aws:lambda:us-east-1:123456789123:function:imageProcessing",
181-
"Version": "$LATEST",
182-
"Role": "arn:aws:iam::123456789123:role/role-lambda-s3",
183-
"Timeout": 60,
184-
"LastModified": "2019-08-13T17:10:23.926+0000",
185-
"Handler": "index.handler",
186-
"Runtime": "nodejs10.x",
187-
"Description": ""
183+
"TracingConfig": {
184+
"Mode": "PassThrough"
185+
},
186+
"CodeSha256": "jz9MRd5XnUBqMdqncN7d7Fxg+edH2ctkqPbMFTteNmU=",
187+
"FunctionName": "imageProcessing",
188+
"CodeSize": 49657600,
189+
"RevisionId": "293ca655-251f-4400-a13b-fc2241c5ea23",
190+
"MemorySize": 512,
191+
"FunctionArn": "arn:aws:lambda:us-east-1:123456789123:function:imageProcessing",
192+
"Version": "$LATEST",
193+
"Role": "arn:aws:iam::123456789123:role/role-lambda-s3",
194+
"Timeout": 60,
195+
"LastModified": "2019-08-13T17:10:23.926+0000",
196+
"Handler": "index.handler",
197+
"Runtime": "nodejs10.x",
198+
"Description": ""
188199
}
189200
```
190201

@@ -194,6 +205,177 @@ This step is easier within the Console. From the Lambda console, select `Add tri
194205

195206
To achieve this, we'll require to perform two actions:
196207

197-
1) Add permissions to the Lambda Function to be executed by S3,
208+
1) Add permissions to the Lambda Function to be executed by S3, and
198209
2) Add notification configuration to the S3 bucket so that when an object is created, it performs an action, which is the function execution.
199210

211+
**To add permissions to the function policy**
212+
213+
1. Run the following Lambda CLI add-permission command to grant Amazon S3 service principal (s3.amazonaws.com) permissions to perform the lambda:InvokeFunction action. Note that permission is granted to Amazon S3 to invoke the function only if the following conditions are met:
214+
215+
* An object-created event is detected on a specific bucket.
216+
* The bucket is owned by a specific AWS account. If a bucket owner deletes a bucket, some other AWS account can create a bucket with the same name. This condition ensures that only a specific AWS account can invoke your Lambda function.
217+
218+
```bash
219+
(bash) $ aws lambda add-permission --function-name imageProcessing --principal s3.amazonaws.com \
220+
--statement-id S3Execution --action "lambda:InvokeFunction" \
221+
--source-arn arn:aws:s3:::rtalexk-gallery --source-account 123456789123
222+
```
223+
224+
Output:
225+
```json
226+
{
227+
"Statement": {
228+
"Sid": "S3Execution",
229+
"Effect": "Allow",
230+
"Principal": {
231+
"Service": "s3.amazonaws.com"
232+
},
233+
"Action": "lambda:InvokeFunction",
234+
"Resource": "arn:aws:lambda:us-east-1:436887685341:function:imageProcessing",
235+
"Condition": {
236+
"StringEquals": {
237+
"AWS:SourceAccount": "436887685341"
238+
},
239+
"ArnLike": {
240+
"AWS:SourceArn": "arn:aws:s3:::rtalexk-gallery"
241+
}
242+
}
243+
}
244+
}
245+
```
246+
247+
2. Verify the function's access policy by running the AWS CLI get-policy command:
248+
249+
```bash
250+
(bash) $ aws lambda get-policy --function-name imageProcessing
251+
```
252+
253+
Output:
254+
```json
255+
{
256+
"Policy": {
257+
"Version": "2012-10-17",
258+
"Id": "default",
259+
"Statement": [
260+
{
261+
"Sid": "S3Execution",
262+
"Effect": "Allow",
263+
"Principal": {
264+
"Service": "s3.amazonaws.com"
265+
},
266+
"Action": "lambda:InvokeFunction",
267+
"Resource": "arn:aws:lambda:us-east-1:436887685341:function:imageProcessing",
268+
"Condition": {
269+
"StringEquals": {
270+
"AWS:SourceAccount": "436887685341"
271+
},
272+
"ArnLike": {
273+
"AWS:SourceArn": "arn:aws:s3:::rtalexk-gallery"
274+
}
275+
}
276+
}
277+
]
278+
},
279+
"RevisionId": "0bd4c17d-4fc2-4395-93b1-09b23f4d792a"
280+
}
281+
```
282+
283+
**To configure S3 notifications**
284+
285+
1. Create a `JSON` file contaning the following configuration (I'll use vim):
286+
287+
```bash
288+
(bash) $ vim s3_notifications.json
289+
```
290+
291+
```json
292+
{
293+
"LambdaFunctionConfigurations": [
294+
{
295+
"Id": "ObjectCreated",
296+
"LambdaFunctionArn": "arn:aws:lambda:us-east-1:436887685341:function:imageProcessing",
297+
"Events": [ "s3:ObjectCreated:*" ],
298+
"Filter": {
299+
"Key": {
300+
"FilterRules": [
301+
{
302+
"Name": "prefix",
303+
"Value": "original/"
304+
}
305+
]
306+
}
307+
}
308+
}
309+
]
310+
}
311+
```
312+
313+
2. Use `s3api` command to create the notification:
314+
315+
```bash
316+
(bash) $ aws s3api put-bucket-notification-configuration --bucket rtalexk-gallery --notification-configuration file://s3_notifications.json
317+
```
318+
319+
3. Use `s3api` command to verify the notification configuration:
320+
321+
```bash
322+
(bash) $ aws s3api get-bucket-notification-configuration --bucket rtalexk-gallery
323+
```
324+
325+
Output:
326+
327+
```json
328+
{
329+
"LambdaFunctionConfigurations": [
330+
{
331+
"Filter": {
332+
"Key": {
333+
"FilterRules": [
334+
{
335+
"Name": "Prefix",
336+
"Value": "original/"
337+
}
338+
]
339+
}
340+
},
341+
"LambdaFunctionArn": "arn:aws:lambda:us-east-1:436887685341:function:imageProcessing",
342+
"Id": "ObjectCreated",
343+
"Events": [
344+
"s3:ObjectCreated:*"
345+
]
346+
}
347+
]
348+
}
349+
```
350+
351+
> Note: Notice that in the S3 section, where whe created the bucket, we used the `s3` command, and here we used `s3api` command. These commands are different: `s3` is used to manipulate buckets and its content, whilst `s3api` is used to command the S3 service to perform certain actions using its API. Refer to [Leveraging the s3 and s3api Commands](https://aws.amazon.com/blogs/developer/leveraging-the-s3-and-s3api-commands/) for a clearer explanation.
352+
353+
## Testing
354+
355+
Upload either a `png` or a `jpg` image to S3 with the prefix of `original/`, you can use the following command (make sure you have an image in your current directory):
356+
357+
```
358+
(bash) $ ls -lh cat.jpg
359+
----------------
360+
-rw-r--r--@ 1 alejandro rivera 1780047346 244K Aug 8 16:54 cat.jpg
361+
```
362+
363+
```bash
364+
(bash) $ aws s3 cp cat.jpg s3://rtalexk-gallery/original/cat.jpg
365+
----------------
366+
upload: ./cat.jpg to s3://rtalexk-gallery/original/cat.jpg
367+
```
368+
369+
Now you can list objects created in the `thumbs` folder:
370+
371+
```bash
372+
(bash) $ aws s3 ls s3://rtalexk-gallery/thumbs/ --human-readable
373+
```
374+
Output:
375+
376+
```
377+
2019-08-13 16:05:38 170.8 KiB cat_original.jpg
378+
2019-08-13 16:05:38 60.3 KiB cat_thumb_1200.jpg
379+
2019-08-13 16:05:38 11.3 KiB cat_thumb_420.jpg
380+
2019-08-13 16:05:38 21.6 KiB cat_thumb_640.jpg
381+
```

0 commit comments

Comments
 (0)