1

I am in over my head a bit.

I have a system setup right now that uses an S3 backed (s3fs) FTP server and a S3 Lambda function (written in Go) to serve, archive, and thumbnail still images from Axis Webcams. However running an FTP server backed on S3 is proving to be issue prone with S3FS, which makes sense as S3 is not a file system.

I am looking to move from using the FTP upload setting in the camera to the HTTP/HTTPS upload option in the camera, but I don't have a good grasp of how to ingest the data the camera puts out with its HTTP request. My only clue is the following bit of code I found on the Axis website, for how to ingest this HTTP data, in a Perl CGI script (I have no knowledge of perl or CGI)

#!/usr/bin/perl -w

my $upload_dir = "/var/www/cgi-bin/upload/";

print "Content-Type: text/plain\r\n\r\n";
print "Upload OK\r\n";

my $file_name = $ENV{'HTTP_CONTENT_DISPOSITION'};
$file_name =~ s/^attachment; filename=\"(.*)\"$/$1/;

open (IMG_FILE, "> $upload_dir$file_name") or die "can't open 
>$upload_dir$file_name";
binmode(IMG_FILE);
while (<STDIN>) {

print IMG_FILE $_;

}
chmod 0666, "$upload_dir$file_name";

exit 0;

I believe the camera sends an HTTP POST (?) request with a multipart formdata attachment (?) with the image in that attachment, but that is a guess.

I am hoping someone can provide me a suggestion on a simple / lightweight way to ingest these images, with some basic auth, and pass them either to a Lambda function direct, or to S3, to be picked up by Lambda later.

My thoughts were possibly AWS API Gateway, a minimal EC2 linux instance, or perhaps Lambda@Edge?

  • As of now, Lambda@Edge doesn't provide access to the request body, so it can't be used for this application, but API Gateway + Lambda could. There are also some default values for s3fs that are not quite sane, and the tweaks at https://stackoverflow.com/a/23946418/1695906 have served me well for several years. The Perl script example does have a security vulnerability because it doesn't check the filename for something fishy, like a filename of `../../../etc/passwd`. – Michael - sqlbot Jul 03 '18 at 09:16
  • Ok, so I can setup an API gateway, to accept this POST request from the camera, pull in the image data, and then shove that off to S3 or Lamda using the normal SDK options? – desertRain4 Jul 03 '18 at 19:23

1 Answers1

0

Here is a solution in PHP. I'm only posting to help anyone that needed the solution. However, this is not a secure way of uploading an image. So please get advice on how to secure this script before use.

<?php

// get filename
$filename = '';
$content_disposition = $_SERVER['HTTP_CONTENT_DISPOSITION'];
if (!$content_disposition) {
    throw new Exception('Content-Disposition header missing');
}
if (preg_match(
    '/^attachment; filename="(?P<file_name>.*)"$/',
    $content_disposition,
    $matches
)) {
    // do something with $matches['file_name']
    $filename = $matches['file_name'];
} else {
    throw new Exception(
        'filename match in Content-Disposition header failed, error: ' .
        preg_last_error()
    );
}

// stream file to server
$rawInput = fopen('php://input', '+r');
$fileout = fopen($filename, 'w');
stream_copy_to_stream($rawInput, $fileout);
fclose($rawInput);
fclose($fileout);


echo "Upload OK";
?>
skymook
  • 3,401
  • 35
  • 39