Git Product home page Git Product logo

awspics's Introduction

AWSPics

An AWS CloudFormation stack to run a serverless password-protected photo gallery

Demo: https://awspics.net

Credentials: "username" / "password"

Goals

Host a self-contained, declarative infrastructure, password-protected, data-driven static photo gallery to share personal pictures with friends and family, without needing to run, maintain (or pay for) servers.

Architecture

There are 7 main components:

  1. CloudFront with restricted bucket access to prevent unauthenticated access to the site or its pictures.
  2. Login lambda function to validate authentication and sign cookies to allow access to restricted buckets.
  3. Source S3 bucket to store original pictures and metadata driving the site.
  4. Resized S3 bucket to store resized versions of the original pictures.
  5. Web S3 bucket to store the static website generated from the data in the source bucket.
  6. Resize lambda function to automatically resize images added to the source S3 bucket and store them in the resized S3 bucket.
  7. Site builder lambda function to automatically rebuild the static website when changes are made to the source S3 bucket a regularly scheduled event fires from Cloudwatch Events.

Pre-requisites

Requires that aws-cli, docker and htpasswd be installed.

You'll also need a domain whose CNAME DNS value you can update.

Instructions

A video walkthrough is available on YouTube.

  1. Configure aws-cli (recommended to use us-east-1, see "Miscellaneous" below):

    $ aws configure
    AWS Access Key ID [None]: AKIA...
    AWS Secret Access Key [None]: illx...
    Default region name [None]: us-east-1
    Default output format [None]:
    $ aws configure set preview.cloudfront true
    
  2. Create KMS encryption key: aws kms create-key. Keep note of its KeyId in the response. Note that each KMS key costs $1/month.

  3. Create CloudFront Key Pair (note, you must do this as the root user of your AWS account, not an administrator), take note of the key pair ID and download the private key: https://console.aws.amazon.com/iam/home?region=us-east-1#/security_credential.

  4. Encrypt the CloudFront private key:

    aws kms encrypt --key-id $KMS_KEY_ID --plaintext fileb://pk-*.pem \
                    --query CiphertextBlob --output text
    
  5. Create a local htpasswd file with your usernames and passwords. You can generate the hashes from the command line:

    $ htpasswd -nB username > htpasswd
    New password: **********
    Re-type new password: **********
    
  6. Encrypt your htpasswd file using KMS again:

    aws kms encrypt --key-id $KMS_KEY_ID --plaintext fileb://htpasswd) \
                    --query CiphertextBlob --output text
    
  7. Create CloudFront Origin Access Identity, take note of the identity in the response:

    aws cloudfront create-cloud-front-origin-access-identity \
                   --cloud-front-origin-access-identity-config \
                   "CallerReference=$(cat /dev/urandom | base64 | base64 | head -c 14),Comment=AWSPics OAI"
    
  8. Create Image Magick Lambda Layer for Amazon Linux 2 AMIs.

    ~~While logged into AWS, go to this link:

    <https://serverlessrepo.aws.amazon.com/applications/arn:aws:serverlessrepo:us-east-1:145266761615:applications~image-magick-lambda-layer>
    

    Click Deploy (currently the orange button on the upper right).

    Then click on your Lambda - Layers and you will see a version ARN that looks like:~~

    The best practice for image magick for the resize function is now is to create your own lambda layer. Download this zip file from here: https://github.com/CyprusCodes/imagemagick-aws-lambda-2/tree/master/archive Upload it to AWS Lambda as a layer (and select runtime of node.js 20 and architecture arm64) as a runtime, and note the change to arm64 architecture on the image resize function in the app.yml file, because the zip file referenced is actually compiled for arm64 and node.js 20. Use the arn of the lambda layer in your dist/config.json file.

    Name          Version  Version ARN
    image-magick  1        arn:aws:lambda:us-east-1:000000000000:layer:image-magick:1
    

    Hold on to that ARN for later.

Deployment

Create a configuration file called dist/config.json, based on config.example.json. Make sure you don't commit this file to source control (the dist folder is ignored).

It should contain the following info - minus the comments:

[
  // -------------------
  // PLAIN TEXT SETTINGS
  // -------------------

  // website domain
  "website=website.com",
  // title for the website
  "websiteTitle=My awesome private photo gallery",
  // S3 bucket where the static website generated from the data in the
  // source bucket will be stored
  "webBucket=html-files-here",
  // S3 bucket where original pictures and metadata driving the site will be
  // stored
  "sourceBucket=original-images-here",
  // S3 bucket where resized images will be stored
  "resizedBucket=resized-images-here",
  // Origin Access Identity from step 7
  "originAccessIdentity=EJG...",
  // how long the CloudFront access is granted for, in seconds
  // note that the cookies are session cookies, and will get deleted when the
  // browser is closed anyway
  "sessionDuration=86400",
  // Optional tracking ID for Google Analytics, if specified then a GA JS
  // snippet will be outputted in the site's HTML, or leave blank for no GA
  "googleanalytics=",
  // Optionally override the path prefix for where original albums and their
  // pictures live, or leave blank to have this default to "pics/original/"
  "picsOriginalPath=",
  // Optionally sort albums by name when building the homepage (if
  // groupAlbumsIntoCollections is disabled), or when building collection pages
  // (if groupAlbumsIntoCollections is enabled), specify either "asc" or "desc",
  // or leave blank to output albums in the order that they're returned from
  // the S3 list objects call
  "albumSort=",
  // Optionally sort pictures in all albums by name when building album pages,
  // specify either "asc" or "desc", or leave blank to output pictures in the
  // reverse order that they're returned from the S3 list objects call
  "pictureSort=",
  // Optionally sort collections by name when building the homepage (if
  // groupAlbumsIntoCollections is enabled), specify either "asc" or "desc", or
  // leave blank to output collections in the order that they're returned from
  // the S3 list objects call
  "collectionSort=",
  // Optionally specify "true" to indicate that the pictures have two grouping
  // levels, collections (first-level folders in the bucket) and albums
  // (second-level folders in the bucket), or leave blank to indicate that
  // the pictures just have one grouping level, albums
  "groupAlbumsIntoCollections=",
  // Indent homepage and album HTML output with spaces, specify "true" to
  // enable, or leave blank to instead indent HTML output with tabs
  "spacesInsteadOfTabs=",
  // Optionally show the specified custom HTML instead of a design credits link
  // to HTML5 UP on the home page, recommended that this be a link in the form:
  // <a href="https://site123.com">Site 123</a>
  // Note: a design credits link to HTML5 UP will still show on album pages
  "homePageCreditsOverride=",
  // Optionally hide the design credits link to HTML5 UP on the home page,
  // specify "true" to enable, or leave blank to show the link
  // Note: a design credits link to HTML5 UP will still show on album pages
  "hideHomePageCredits=",
  // KMS key ID created in step 2
  "kmsKeyId=00000000-0000-0000-0000-000000000000",
  // CloudFront key pair ID from step 3
  // This is not sensitive, and will be one of the cookie values
  "cloudFrontKeypairId=APK...",
  // ------------------
  // Image Magick Lambda Layer ARN
  // - this is needed for ImageMagick to resize images in Node.js 10.x
  // - from step 8 above
  // - context above in README
  // ------------------
  "ImageMagickLayer=arn:aws:lambda:us-east-1:........:layer:image-magick:...",

  // ------------------
  // ENCRYPTED SETTINGS
  // ------------------

  // encrypted CloudFront private key from step 4
  "encryptedCloudFrontPrivateKey=AQICAH...",

  // encrypted contents of the <htpasswd> file from step 6
  "encryptedHtpasswd=AQICAH...",

  // ------------------
  // SSL Certificate ARN
  // - provide this if you want to use an existing ACM Certificate.
  // - see below in the README
  // ------------------
  "sslCertificateArn=arn:aws:acm:us-east-1..."

]

You can then deploy the full stack using:

# name of an S3 bucket for storing the Lambda code
# bucket will be created if it doesn't already exist
./deploy <unique_bucket_name_here>

Or optionally deploy and specify the stack name (otherwise it defaults to AWSPics):

./deploy --stack-name=<stack_name_here> <unique_bucket_name_here>

Any subsequent changes that you make to this code can be redeployed with the same command. CloudFormation will create a "changeset" to only update the modified resources.

The first deployment should take about 30 minutes since there's a lot to set up. You'll also receive an email to approve the SSL certificate request, which you should complete quickly, so that the rest of the deployment can proceed.

You will want to update the frequency of the Cloudwatch Events Rule from its default setting at 365 days to something more appropriate to your needs. You can adjust this pre-deployment in the app.yml file or after the fact in the AWS Management console.

Note on ImageMagick Layer for Lambda

When Amazon deprecated Node.js 8.10, they removed ImageMagick from the Amazon Linux 2 AMIs that are required to run Node.js 10.x. Again, ImageMagick is no longer bundled with the Node.js 10.x runtime. This fix may also help with running on Node.js 12.x in the future. This provides a Lambda Layer (essentially a library) for your Lambda function that makes the existing code work with Node.js 10.x.

Release notes for update December 2023

The best practice for image magick for the resize function is now is to create your own lambda layer. Download this zip file from here: https://github.com/CyprusCodes/imagemagick-aws-lambda-2/tree/master/archive

Upload it to AWS Lambda as a layer (and select runtime of node.js 20 and architecture arm64) as a runtime, and note the change to arm64 architecture on the image resize function in the app.yml file, because the zip file referenced is actually compiled for arm64 and node.js 20. Use the arn of the lambda layer in your dist/config.json file.

htpasswd-auth was outdated and using bcrypt which reached end of life and was failing. This was updated to bcrypt 5.0.1+ and node.js 20. Also a minor update to the login function updating the buffer function (Buffer -> Buffer.from in login index.js) for the latest node.js 20.x.

Note that Amazon removed aws-sdk from the Amazon Linux base image that lambda functions run on, so it was added to the package.json, and it increases the size of each lambda function zip file by 13 MB or so. This could be added as a lambda layer to save space if needed, but this was an easier change to make.

When manually uploading files (e.g. photos) to S3 Buckets for this application, because of the encryption, you want to select the option of an encryption by default.

Also, the site-builder function used to be cloudwatch events, but it has been renamed by AWS. The best way to rerun the site-builder is to just hit the test button from AWS Lambda. That generates the site building on demand. Otherwise the default is to run infrequently, as configured in the app.yml.

Note on SSL Cert

AWS Certificate Manager now supports SSL cert verification via DNS validation. It is recommended that you manually request the certificate for your hosted zone and chose DNS validation method for much faster validation. Then use the resulting ARN in your config. You can also leave this config key empty to create the certificate as normal.

Once the initial deployment is done, you'll need to point your domain's DNS settings to add a CNAME to the newly created CloudFront Distribution URL, which you can find by visiting the CloudFront section of the AWS Console. Once the DNS update has propagated, you'll be able to access your private photo gallery at that domain. However, there's no content yet, so you won't see much of anything. You can generate sample albums to see it in action.

Generate Sample Albums

There's a script included that will pull random images from Unsplash to populate your photo gallery with sample content.

./generate_random_albums <number of albums>

How the Authentication Works

The Lambda function responsible for logging in creates signed session cookies when given valid credentials. CloudFront will verify that every request has valid cookies before forwarding them.

Browser                   CloudFront             Lambda              S3
  |                           |                    |                 |
  | ---------- get ---------> |                    |                 |
  |                           |                    |                 |
  |                      [no cookie]               |                 |
  |                           |                    |                 |
  |                           |                    |                 |
  |                           |                    |                 |
  | <------ error page ------ |                    |                 |
  |                                                |                 |
  | -------------------- login ------------------> |                 |
  | <------------------- cookies ----------------- |                 |
  |                                                                  |
  | ---------- get ---------> |                                      |
  |                           |                                      |
  |                      [has cookie]                                |
  |                           |                                      |
  |                           | -----------------------------------> |
  |                           | <------------ html page ------------ |
  | <------ html page ------- |

Miscellaneous

This project only works as-is if everything is set up in the us-east-1 AWS region, because CloudFormation only supports SSL certificates from that region. It's not too difficult to adapt this to work in another region, but you can't rely on the SSL certificate being created in CloudFormation. Create it manually (using either the AWS Console or the CLI) and reference it in the WebDistribution by its ARN explicitly rather than the !Ref SSLCert reference.

GeoRestriction is commented out in the CloudFront configuration in the app.yaml. If you are sharing with friends and family in a specific geographic area, this is a slight improvement to security and cost reduction. The US is provided as an example, but additional countries can be added to a (whitelist/blacklist) based on their two letter ISO 3166-1 alpha-2 country code.

S3 Server Side AES256 encryption is enabled for the source and resized photo buckets and encrypts files using the AWS S3 Master key. Each bucket is configured to force encryption of any file it receives (you will need to check the upload box or specify it in the CLI when uploading photo files to the buckets) and you will get access denied messages if you don't. The Resize function re-encrypts the resized photos with AES256 SSE before uploading them into the resized bucket. Cloudfront with an OAI is able to access files using the S3 Master Key without any issue. One cannot at this time use a KMS key for encrypting bucket data to be accessed via Cloudfront without more complexity.

The EventInvoke config is included for SiteBuilder to prevent it from queueing up invocations and causing multiple cloudfront invalidations at the same time. If you need to run sitebuilder more frequently, adjust the rate of events by editing the CloudWatch Events rule in the Management console or the app.yml file.

Also, you can reduce compute costs and lock down the application several ways: 1) by manually throttling the Resize Function and the SiteBuilder Function in Lambda in the Management console or 2) disabling the CloudWatch Events rule that runs SiteBuilder or 3) manually disabling the trigger for a Lambda function in the Management console.

Default directory for photos is S3://BUCKET_NAME/pics/original/YOUR_ALBUMS_GO_HERE

Troubleshooting

If the project deploys and the login is entered correctly, but you are receiving access denied messages, review your DNS settings. You only need a single DNS A record pointing to the CloudFront Alias for your domain, and time for it to propagate.

If SiteBuilder is hanging or having trouble completing, you may need to adjust the rate limiting delay block in index.js. The current S3 rate limit is 3500 writes a second, and 5500 reads/sec. If you're writing 30 files per album, if you have more than 116 albums, you will hit the rate limit - and SiteBuilder will just hang and you will see the files as a partial listing in the web directory.

Credits

This project is mostly a compilation from multiple existing projects out there.

Credits for update to nodejs 10.x and ImageMagick Layer:

Credits for update to nodejs 20.x and ImageMagick Layer:

License

AWSPics is MIT licensed.

awspics's People

Contributors

agstevens avatar dependabot[bot] avatar jaza avatar jpsim avatar jsloan117 avatar kernelpanicaus avatar mikeder avatar rprieto avatar simbamford avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

awspics's Issues

Are deployments to non-us-east-1 regions broken?

If I deploy to my local region, eu-west-2, I get "The authorization mechanism you have provided is not supported. Please use AWS4-HMAC-SHA256" on image requests. I know this was addressed in 6de470b though (I'm using the latest as per 10th Oct 2019: 9c40fc6).

If I take what I deployed to eu-west-2 and deploy it to us-east-1, it works correctly.

I can't see what I'm doing wrong and could do with someone else confirming that non-us-east-1 deployments work correctly.

I'm sharing some things between the two deployments, such as the CloudFront Key Pair, the unencrypted htpasswd file and the OAI. Everything else is region specific.

cloudfront to api gateway - internal server error

hey @jpsim great work!

i`ve ported this app/stack to terraform. all is working well (fixed a few bugs too) except one thing...the cdn doesnt correctly forwards requests to the login gateway+login_lambda.

do you have an idea what might be wrong? maybe we can (in private) inspect the CDN origins/cache-behavior together?

Cognito

It's a great project beautifully done and demonstrated, very clear written documentation.
I'm not a great fan of .htaccess but if this could also be adapted to work with AWS Cognito user pools also that would be amazing.

Thanks

Security for htpassword

How secure is htpassword over the internet. I believe it is plaintext authentication and can be hacked by sniffing or man in the middle attacks ?

Deploy fails on "node-pre-gyp install --fallback-to-build"

Hi there,

deploy fails with following error message (issue seems to be htpasswd-auth):

npm WARN package.json [email protected] No repository field.
npm WARN package.json [email protected] No README data
WARN engine [email protected]: wanted: {"node":">=4.6.1"} (current: {"node":"4.3.2","npm":"2.14.12"})
WARN engine [email protected]: wanted: {"node":">=4.6.1"} (current: {"node":"4.3.2","npm":"2.14.12"})

> [email protected] install /build/node_modules/htpasswd-auth/node_modules/bcrypt
> node-pre-gyp install --fallback-to-build

node-pre-gyp ERR! UNCAUGHT EXCEPTION 
node-pre-gyp ERR! stack TypeError: this is not a typed array.
node-pre-gyp ERR! stack     at Function.from (native)
node-pre-gyp ERR! stack     at Object.<anonymous> (/build/node_modules/htpasswd-auth/node_modules/bcrypt/node_modules/tar/lib/parse.js:33:27)
node-pre-gyp ERR! stack     at Module._compile (module.js:409:26)
node-pre-gyp ERR! stack     at Object.Module._extensions..js (module.js:416:10)
node-pre-gyp ERR! stack     at Module.load (module.js:343:32)
node-pre-gyp ERR! stack     at Function.Module._load (module.js:300:12)
node-pre-gyp ERR! stack     at Module.require (module.js:353:17)
node-pre-gyp ERR! stack     at require (internal/module.js:12:17)
node-pre-gyp ERR! stack     at Object.<anonymous> (/build/node_modules/htpasswd-auth/node_modules/bcrypt/node_modules/tar/lib/list.js:10:16)
node-pre-gyp ERR! stack     at Module._compile (module.js:409:26)
node-pre-gyp ERR! System Linux 4.9.87-linuxkit-aufs
node-pre-gyp ERR! command "/usr/local/lib64/node-v4.3.x/bin/node" "/build/node_modules/htpasswd-auth/node_modules/bcrypt/node_modules/.bin/node-pre-gyp" "install" "--fallback-to-build"
node-pre-gyp ERR! cwd /build/node_modules/htpasswd-auth/node_modules/bcrypt
node-pre-gyp ERR! node -v v4.3.2
node-pre-gyp ERR! node-pre-gyp -v v0.9.1
node-pre-gyp ERR! This is a bug in `node-pre-gyp`.
node-pre-gyp ERR! Try to update node-pre-gyp and file an issue if it does not help:
node-pre-gyp ERR!     <https://github.com/mapbox/node-pre-gyp/issues>
npm ERR! Linux 4.9.87-linuxkit-aufs
npm ERR! argv "/usr/local/lib64/node-v4.3.x/bin/node" "/usr/local/lib64/node-v4.3.x/bin/npm" "install" "--save" "htpasswd-auth"
npm ERR! node v4.3.2
npm ERR! npm  v2.14.12
npm ERR! code ELIFECYCLE

npm ERR! [email protected] install: `node-pre-gyp install --fallback-to-build`
npm ERR! Exit status 7
npm ERR! 
npm ERR! Failed at the [email protected] install script 'node-pre-gyp install --fallback-to-build'.
npm ERR! This is most likely a problem with the bcrypt package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     node-pre-gyp install --fallback-to-build
npm ERR! You can get their info via:
npm ERR!     npm owner ls bcrypt
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR!     /build/npm-debug.log
The command '/bin/sh -c npm install --save htpasswd-auth' returned a non-zero code: 1

So i changed the dockerfile to:

FROM lambci/lambda-base:build

ENV PATH=/var/lang/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \
    LD_LIBRARY_PATH=/var/lang/lib:/lib64:/usr/lib64:/var/runtime:/var/runtime/lib:/var/task:/var/task/lib \
    AWS_EXECUTION_ENV=AWS_Lambda_nodejs8.10 \
    NODE_PATH=/var/runtime:/var/task:/var/runtime/node_modules \
    npm_config_unsafe-perm=true

RUN rm -rf /var/runtime /var/lang && \
  curl https://lambci.s3.amazonaws.com/fs/nodejs8.10.tgz | tar -zx -C /

CMD ["npm", "rebuild"]

RUN mkdir /build
WORKDIR /build
COPY package.json /build/package.json

RUN npm install --production

COPY index.js /build/index.js

RUN zip -r /build/dist.zip . > /dev/null
CMD ["cat", "/build/dist.zip"]

Which results in a finished deploy. Taking a look at the stack everything seems fine, but I'm unable to login with my credentials on the site.

node.js 20 Resize Function

@agstevens I see there's a new Lambda layer for node.js 20. I don't know node well enough to competently translate the Resize function to code that is compatible with node.js 20. I was wondering if your own code was up-to-date, and if so, could you share it?

AWS has retired older runtimes, so sticking with older versions won't be an option for long.

lambda-login.zip: No such file or directory

Getting this error when running from a Amazon Linux 2 AMI
Step 8/8 : CMD ["cat", "/build/dist.zip"]
---> Using cache
---> 385619951be4
Successfully built 385619951be4
Successfully tagged cloudformation-lambda-login:latest
./deploy: line 20: ../dist/lambda-login.zip: No such file or directory

Any recommendations?

Stack <stack name> does not exist on deploy

When running the deploy function, it checks the bucket name and then creates the bucket correctly. But the deployment process fails and exits the installation process on the next step -

"aws cloudformation deploy --template-file /tmp/tmp. --stack-name "

I am currently using Python 2.4.6 if that makes a difference and I ran the command as ./deploy awspics-lambda without the stack name or editing the default stack name within the deploy app. Is there something different with the DescribeStackResource operation in python 2 or am I missing something?

Include descriptive information on created resources

When creating resources such as keys it is a good practice to include some descriptive information with them to make it easier to identify their intent later.

For example, when creating keys the description field can be set.

$ aws kms create-key --description "for awspics"

The alias value which appears on the kms console can also be set. This will appear on the KMS console in the list of keys.

$ aws kms create-alias --alias-name alias/awspics --target-key-id xxx

AWSPics Costs

Just curious, what are the estimated ongoing costs for AWSPics? I know, in large part, it's due to how many items are stored in your source bucket. Moving that aside, is there anything else that is ongoing?

Encrypted htpasswd

Is anyone else having an issue with the htpasswd encryption steps? In earlier deployments it worked fine for me, but now it is suddenly not working (after a macOS update to mojave 10.14.6 - they might have changed the default shell).

I generate an htpasswd file using the command line:
htpasswd -vB username

(this generates a plaintext output as the command "htpasswd -nB username > htpasswd" includes the "New Password:" text - I don't recall this happening on the previous MacOS version) so I have to paste it into an htpasswd file manually - maybe the newline characters or lack of newline characters at the end of the line are messing with it?

I test the htpasswd file:
htpasswd -vb htpasswd username password

and the password checks out

I encrypt it as follows:
aws kms encrypt --key-id $KMS_KEY_ID --plaintext "$(cat htpasswd)" --query CiphertextBlob --output text

I also try adding the --region us-east-1 for completeness

output is a long string:
AQICAHhVd.....k==

I test it with decryption:
aws kms decrypt --ciphertext-blob fileb://<(echo 'AQICAHhVd.....k==' | base64 -D)

and paste the decrypted string into a base64 yo ascii converter and verify it matches the htpasswd file contents.

When I deploy it, the username password is not accepted. However, when I use an earlier generated password from before the macOS update, it works.
I think the macOS update changed the default shell, but I can't figure out why this is no longer working for me.

Image URLs showing as undefined

After uploading images to the source bucket, I can see that it successfully generates resized images and rebuilds the site.

However, the images won't display... On the main page, all of the image src attributes show undefined where the filename would typically be. And on an individual picture page, the image looks like it is missing altogether.

Any ideas?

screen shot 2019-02-19 at 9 36 24 am

screen shot 2019-02-19 at 9 36 42 am

site-builder only checks against lower-case "jpg"

HI,

I found one issue with site-builder. It only checks against lower-case "jpg" and doesn't check png at all. Although the resize function tales care of png.
Changing line 54 index.js of site-builder to
return object.startsWith(album + "/") && (object.toLowerCase().endsWith('.jpg') || object.toLowerCase().endsWith('.png'));
fixes the issue.

Thanks for the great work.
Best Roman

Mixed content - HTTPS to HTTP request

Hi,

Thank you for a very useful guide and this repo. I was able to deploy the project in AWS but when I try logging in I get Incorrect Username or Password message. When I Inspect the source these are the messages I'm getting:
Mixed Content: The page at 'https://<CF_ID>.cloudfront.net/' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://<CF_ID>.cloudfront.net/Prod/login'. This content should also be served over HTTPS.
and
Access to XMLHttpRequest at 'https://<my_domain>/Prod/login' from origin 'https://<CF_ID>.cloudfront.net' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.

The project is deployed in us-east-1, I followed instructions on https://www.jpsim.com/awspics/, deployed with SSL cert ARN provided via config.json and with the value for this parameter being empty. In both cases the result is the same.
I validated user and password with htpasswd -v command.

I wanted to check if this is a known issue with known quick fix or something I'd need to dig into the code to solve?

Thanks!

lambda-login.zip missing in deploy execution

Step 8/8 : CMD ["cat", "/build/dist.zip"]
---> Using cache
---> 385619951be4
Successfully built 385619951be4
Successfully tagged cloudformation-lambda-login:latest
./deploy: line 20: ../dist/lambda-login.zip: No such file or directory

Am i supposed to zip the folders?

picture sorty by name

Is it possible to add the feature that the pictures will be in the order of the filename? For now it seen rather random.

thanks

Stack name issue

Hey all

have the following issue with the deploy script:

Uploading to 82f57676ab14fe89375a0ec2398442f3 2359567 / 2359567.0 (100.00%)
Successfully packaged artifacts and wrote output template to file /tmp/tmp.ltdw0 kTUmq.
Execute the following command to deploy the packaged template
aws cloudformation deploy --template-file /tmp/tmp.ltdw0kTUmq --stack-name YOUR STACK NAME

Expecting value: line 14 column 1 (char 3213)

An error occurred (ValidationError) when calling the DescribeStackResource opera tion: Stack 'AWSPics' does not exist
usage: aws [options] [ ...] [parameters]
To see help text, you can run:

aws help
aws help
aws help
aws: error: the following arguments are required: outfile

Anyone had this?

Required IAM permissions

You might consider including in the README the IAM role/policies that are required to complete the entire process. Since this has specific functionality it can be useful to do it using a discrete and limited set of capabilities in your account.

S3 Rate Limit Delay Block

In Troubleshooting section of the Readme, it mentions "If SiteBuilder is hanging or having trouble completing, you may need to adjust the rate limiting delay block in index.js."

I presume the SiteBuilder lambda function would need the delay block but I'm unable to find the block in index.js. I'm not a programmer, so it may be there and I just don't know it, but my albums contain hundreds of pictures and I've experienced the site builder hang and partial file listings.

Would someone provide an example delay block of code, that I could insert and where exactly?

Thanks for the great solution.
Darren

Choice to make this public or private

I still enjoy this project! My use for this is for my astrophotography site which I've modified this to make it public. I just wanted to engage everyone else evolved in this project on whether or not this would be liked by others and merged if I did the work while providing an option to select public site vs the default of private.

Node version of Lambdas needs to be upgraded to 8.10

Amazon is deprecating Node 6.10, which is used by 2 of the lambda functions.

"Lambda functions configured to use the node.js 6.10 runtime will be disabled on April 30, 2019. Code updates to existing functions using node.js 6.10 will be disabled 30 days later on May 30, 2019."

Doesn't work with newer S3 regions, because signatureversion v4 requirement

All AWS regions started after 2014 require signatureversion v4 when accessing S3 buckets. The fix is simple - just need to define the signatureversion to be used in the AWS.S3 constructor.

diff --git a/resize/index.js b/resize/index.js
index 007d1ac..7556886 100644
--- a/resize/index.js
+++ b/resize/index.js
@@ -2,7 +2,7 @@ var async = require("async");
 var AWS = require("aws-sdk");
 
 var im = require("gm").subClass({imageMagick: true});
-var s3 = new AWS.S3();
+var s3 = new AWS.S3({signatureVersion: 'v4'});
 
 function getImageType(objectContentType) {
   if (objectContentType === "image/jpeg") {
diff --git a/site-builder/index.js b/site-builder/index.js
index 79cae0e..37a69e1 100644
--- a/site-builder/index.js
+++ b/site-builder/index.js
@@ -1,5 +1,5 @@
 var AWS = require("aws-sdk");
-var s3 = new AWS.S3();
+var s3 = new AWS.S3({signatureVersion: 'v4'});
 var cloudfront = new AWS.CloudFront();
 
 var async = require('async');

Debounce site builder lambda

From jpsim.com/awspics:

Another related problem is that for every new image in the source bucket, two are created in the resized bucket, each one invoking the site builder function. Not only that, but if I upload an album with lots of pictures all in one shot, the site will be rebuilt twice for each picture! ๐Ÿ™€

Unfortunately, S3 buckets can only have a single notification per event type, so we can't trigger both the resize and site builder functions when new objects are created on the source bucket.

I think the solution here would involve publishing S3 events to SNS or SQS and "debouncing" the site builder lambda, but again... #complexity.

falls over at step 10

Step 10/10 : CMD ["cat", "/build/dist.zip"]
 ---> Using cache
 ---> a337470701fa
Successfully built a337470701fa
Successfully tagged cloudformation-lambda-site-builder:latest
usage: aws [options] <command> <subcommand> [<subcommand> ...] [parameters]
To see help text, you can run:

  aws help
  aws <command> help
  aws <command> <subcommand> help
aws: error: argument operation: Invalid choice, valid choices are:

cancel-update-stack                      | continue-update-rollback                
create-change-set                        | create-stack                            
delete-change-set                        | delete-stack                            
describe-account-limits                  | describe-change-set                     
describe-stack-events                    | describe-stack-resource                 
describe-stack-resources                 | describe-stacks                         
estimate-template-cost                   | execute-change-set                      
get-stack-policy                         | get-template                            
get-template-summary                     | list-change-sets                        
list-exports                             | list-stack-resources                    
list-stacks                              | set-stack-policy                        
signal-resource                          | update-stack                            
validate-template                        | wait                                    
help                                   

Can the S3 buckets be encrypted server-side ?

First - thanks for making this. This is amazing.
My question is about the S3 bucket storage encryption.
If I enable the Amazon S3 default encryption or say the SSE-KMS encryption for all the three buckets, do you think this would still continue working ?
Any potential issues you see with that ?

Thanks !

bcrypt module not compatible with nodejs12.x

AWS discontinued support for nodejs8.10. I changed the code to nodejs12.x based on previous commit that updated project nodejs version. This caused an error with bcrypt module:

"errorMessage": "The module '/var/task/node_modules/bcrypt/lib/binding/bcrypt_lib.node'\nwas compiled against a different Node.js version using\nNODE_MODULE_VERSION 57. This version of Node.js requires\nNODE_MODULE_VERSION 72. Please try re-compiling or re-installing\nthe module (for instance, using `npm rebuild` or `npm install`)."

I tried to replace bcrypt in lambda-login.zip with the latest version but it didn't help. Unfortunately, I don't know enough about nodejs deployment to quickly resolve it. I was wondering if you are planning to update to latest supported nodejs version?

Docker build is failing on npm install --production command

Deploy script is failing where it tries to build a docker image at this line.

docker build -t "cloudformation-lambda-$function" .

The error is:
The command '/bin/sh -c npm install --production' returned a non-zero code: 132.

In Dockerfile, this is the particular line which is failing:

RUN npm install --production

I tried googling it but none of the proposed solutions is working. Please help.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.