why method for signing url for AWS CloudFront is not working when deployed on AWS Elastic Beanstalk (500 Error)?

228 Views Asked by At

I and my colleagues are developing Spring Boot project for study purpose. We use AWS S3 as cloud storage for storing images. Aslo we decided to use AWS CloudFront as content delivery network for retrieving images and use a CloudFront origin access identity (OAI) to access the S3 bucket. For this purpose our server generate signed url using ssl private key and keyPairId. Code look like this:

    @Value("${cloud.front.distribution.domain}")
    String distributionDomain;
    @Value("${cloud.front.key.pair.id}")
    private String keyPairId;
    @Value("${cloud.front.private.key.filePath}")
    String privateKeyFilePath;

    try {
           return CloudFrontUrlSigner.getSignedURLWithCannedPolicy(SignerUtils.Protocol.https,
              distributionDomain, new File(privateKeyFilePath), fileName,
              keyPairId, calendar.getTime());
        } catch (Exception e) {
            throw new RuntimeException("Can't generate signed URL", e);
        }

Everything worked just fine when I am using localhost but when project is deployed on AWS Elastic Beanstalk it gives 500 Error.

I was thinking that problem is that file with private key is located in static directory and it can not be read at deploy stage. But relocating to other place doesn't helped. It is hard for me understand in what direction I have to search.

1

There are 1 best solutions below

1
Max Visser On

I would store your private key in a S3 bucket which you retrieve on app deploy.

You can do this by creating an .ebextension for example 00_copy_private_key.config which uses the instance role attached to the EC2 instance to safely connect to a s3 bucket containing your private key.

# Replace `elasticbeanstalk-eu-central-1-xxxxxxxxxxxx` with the bucket that AWS created
# when you created your first Elastic Beanstalk environment.

# Make sure that the IAM Role for the EC2 Instance set in the Elastic Beanstalk configuration
# has attached the `AWSElasticBeanstalkFullAccess` policy.

Resources:
  AWSEBAutoScalingGroup:
    Metadata:
      AWS::CloudFormation::Authentication:
        S3Auth:
          type: "s3"
          buckets: ["elasticbeanstalk-eu-central-1-xxxxxxxxxxxx"]
          roleName:
            "Fn::GetOptionSetting":
              Namespace: "aws:autoscaling:launchconfiguration"
              OptionName: "IamInstanceProfile"
              DefaultValue: "aws-elasticbeanstalk-ec2-role"

# From the created bucket, point to the .env file which you want to
# copy to this app during deployment.

# The file will be copied first in /tmp/.env, then moved to the app
# in the deployment process.

files:
  "/tmp/private.key":
    mode: "000400"
    owner: root
    group: root
    authentication: "S3Auth"
    source: https://elasticbeanstalk-eu-central-1-xxxxxxxxxxxx.s3.eu-central-1.amazonaws.com/private.key

source: https://github.com/rennokki/laravel-aws-eb/blob/23524d112398720a2759ab13076a98f2203b1b1f/.ebextensions/00_copy_env_file.config

After copying over the private key you still need to move it to the right location where you app expects it:

container_commands:
  00_copy_private_key:
    command: "mv /tmp/private.key /var/app/staging/private.key"