Skip to content

Instantly share code, notes, and snippets.

@leepa
Created December 5, 2018 12:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save leepa/bb4415dd18f95ee39e6ca73f827b986a to your computer and use it in GitHub Desktop.
Save leepa/bb4415dd18f95ee39e6ca73f827b986a to your computer and use it in GitHub Desktop.
extern crate lambda_runtime as lambda;
#[macro_use]
extern crate log;
extern crate simple_logger;
extern crate serde_derive;
extern crate chrono;
use lambda::{error::HandlerError, lambda};
use chrono::{DateTime, Utc};
use serde_derive::{Deserialize};
use std::error::Error;
use std::collections::HashMap;
#[derive(Deserialize, Debug)]
struct S3Event {
#[serde(rename = "Records")]
#[allow(dead_code)]
records: Vec<S3EventRecord>,
}
#[derive(Deserialize, Debug)]
struct S3EventRecord {
#[serde(rename = "eventVersion")]
#[allow(dead_code)]
event_version: String,
#[serde(rename = "eventSource")]
#[allow(dead_code)]
event_source: String,
#[serde(rename = "awsRegion")]
#[allow(dead_code)]
aws_region: String,
#[serde(rename = "eventTime")]
#[allow(dead_code)]
event_time: DateTime<Utc>,
#[serde(rename = "eventName")]
#[allow(dead_code)]
event_name: String,
#[serde(rename = "userIdentity")]
#[allow(dead_code)]
user_identity: S3UserIdentity,
#[serde(rename = "requestParameters")]
#[allow(dead_code)]
request_parameters: S3RequestParameters,
#[serde(rename = "responseElements")]
#[allow(dead_code)]
response_elements: HashMap<String, String>,
#[serde(rename = "s3")]
#[allow(dead_code)]
s3: S3Entity,
}
#[derive(Deserialize, Debug)]
struct S3RequestParameters {
#[serde(rename = "sourceIPAddress")]
#[allow(dead_code)]
source_ip_address: String,
}
#[derive(Deserialize, Debug)]
struct S3UserIdentity {
#[serde(rename = "principalId")]
#[allow(dead_code)]
principal_id: String,
}
#[derive(Deserialize, Debug)]
struct S3Entity {
#[serde(rename = "s3SchemaVersion")]
#[allow(dead_code)]
schema_version: String,
#[serde(rename = "configurationId")]
#[allow(dead_code)]
configuration_id: String,
#[serde(rename = "bucket")]
#[allow(dead_code)]
bucket: S3Bucket,
#[serde(rename = "object")]
#[allow(dead_code)]
object: S3Object,
}
#[derive(Deserialize, Debug)]
struct S3Bucket {
#[serde(rename = "name")]
#[allow(dead_code)]
name: String,
#[serde(rename = "ownerIdentity")]
#[allow(dead_code)]
owner_identity: S3UserIdentity,
#[serde(rename = "arn")]
#[allow(dead_code)]
arn: String,
}
#[derive(Deserialize, Debug)]
struct S3Object {
#[serde(rename = "key")]
#[allow(dead_code)]
key: String,
#[serde(default)]
#[serde(rename = "size")]
#[allow(dead_code)]
size: i64,
#[serde(default)]
#[serde(rename = "urlDecodedKey")]
#[allow(dead_code)]
url_decoded_key: String,
#[serde(default)]
#[serde(rename = "versionId")]
#[allow(dead_code)]
version_id: String,
#[serde(default)]
#[serde(rename = "eTag")]
#[allow(dead_code)]
etag: String,
#[serde(rename = "sequencer")]
#[allow(dead_code)]
sequencer: String,
}
fn main() -> Result<(), Box<dyn Error>> {
simple_logger::init_with_level(log::Level::Debug).unwrap();
lambda!(handler);
Ok(())
}
fn handler(e: S3Event, _c: lambda::Context) -> Result<String, HandlerError> {
info!("Logging S3 Event {:?}", e);
Ok("Foo".to_string())
}
#[cfg(test)]
mod tests {
use super::*;
extern crate serde_json;
#[test]
fn parse_delete_event() {
let s3_delete_event = r#"
{
"Records": [
{
"eventVersion": "2.0",
"eventSource": "aws:s3",
"awsRegion": "eu-west-1",
"eventTime": "1970-01-01T00:00:00.000Z",
"eventName": "ObjectRemoved:Delete",
"userIdentity": {
"principalId": "EXAMPLE"
},
"requestParameters": {
"sourceIPAddress": "127.0.0.1"
},
"responseElements": {
"x-amz-request-id": "EXAMPLE123456789",
"x-amz-id-2": "EXAMPLE123/5678abcdefghijklambdaisawesome/mnopqrstuvwxyzABCDEFGH"
},
"s3": {
"s3SchemaVersion": "1.0",
"configurationId": "testConfigRule",
"bucket": {
"name": "example-bucket",
"ownerIdentity": {
"principalId": "EXAMPLE"
},
"arn": "arn:aws:s3:::example-bucket"
},
"object": {
"key": "test/key",
"sequencer": "0A1B2C3D4E5F678901"
}
}
}
]
}
"#;
let _deserialized: S3Event = serde_json::from_str(&s3_delete_event).unwrap();
}
#[test]
fn parse_put_event() {
let s3_put_event = r#"
{
"Records": [
{
"eventVersion": "2.0",
"eventSource": "aws:s3",
"awsRegion": "eu-west-1",
"eventTime": "1970-01-01T00:00:00.000Z",
"eventName": "ObjectCreated:Put",
"userIdentity": {
"principalId": "EXAMPLE"
},
"requestParameters": {
"sourceIPAddress": "127.0.0.1"
},
"responseElements": {
"x-amz-request-id": "EXAMPLE123456789",
"x-amz-id-2": "EXAMPLE123/5678abcdefghijklambdaisawesome/mnopqrstuvwxyzABCDEFGH"
},
"s3": {
"s3SchemaVersion": "1.0",
"configurationId": "testConfigRule",
"bucket": {
"name": "example-bucket",
"ownerIdentity": {
"principalId": "EXAMPLE"
},
"arn": "arn:aws:s3:::example-bucket"
},
"object": {
"key": "test/key",
"size": 1024,
"eTag": "0123456789abcdef0123456789abcdef",
"sequencer": "0A1B2C3D4E5F678901"
}
}
}
]
}
"#;
let _deserialized: S3Event = serde_json::from_str(&s3_put_event).unwrap();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment