Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the best way to store token signing certificate for an AWS web app?

I am using IdentityServer4 with .NET Core 2.0 on AWS's ElasticBeanstalk. I have a certificate for signing tokens. What's the best way to store this certificate and retrieve it from the application? Should I just stick it with the application files? Throw it in an environment variable somehow?

Edit: just to be clear, this is a token signing certificate, not an SSL certificate.

like image 554
Ben Zuill-Smith Avatar asked Jan 16 '18 23:01

Ben Zuill-Smith


1 Answers

I don't really like the term 'token signing certificate' because it sounds so benign. What you have is a private key (as part of the certificate), and everyone knows you should secure your private keys!

I wouldn't store this in your application files. If someone gets your source code, they shouldn't also get the keys to your sensitive data (if someone has your signing cert, they can generate any token they like and pretend to be any of your users).

I would consider storing the certificate in AWS parameter store. You could paste the certificate into a parameter, which can be encrypted at rest. You then lock down the parameter with an AWS policy so only admins and the application can get the cert - your naughty Devs dont need it! Your application would pull the parameter string when needed and turn it into your certificate object.

This is how I store secrets in my application. I can provide more examples/details if required.

Edit -- This was the final result from Stu's guidance

The project needs 2 AWS packages from Nuget to the project

  • AWSSDK.Extensions.NETCORE.Setup
  • AWSSDK.SimpleSystemsManagement

Create 2 parameters in the AWS SSM Parameter Store like:

  • A plain string named /MyApp/Staging/SigningCertificate and the value is a Base64 encoded .pfx file
  • An encrypted string /MyApp/Staging/SigningCertificateSecret and the value is the password to the above .pfx file

This is the relevant code:

// In Startup class
private X509Certificate2 GetSigningCertificate()
{
    // Configuration is the IConfiguration built by the WebHost in my Program.cs and injected into the Startup constructor
    var awsOptions = Configuration.GetAWSOptions();
    var ssmClient = awsOptions.CreateServiceClient<IAmazonSimpleSystemsManagement>();

    // This is blocking because this is called during synchronous startup operations of the WebHost-- Startup.ConfigureServices()
    var res = ssmClient.GetParametersByPathAsync(new Amazon.SimpleSystemsManagement.Model.GetParametersByPathRequest()
    {
        Path = "/MyApp/Staging",
        WithDecryption = true
    }).GetAwaiter().GetResult();

    // Decode the certificate
    var base64EncodedCert = res.Parameters.Find(p => p.Name == "/MyApp/Staging/SigningCertificate")?.Value;
    var certificatePassword = res.Parameters.Find(p => p.Name == "/MyApp/Staging/SigningCertificateSecret")?.Value;
    byte[] decodedPfxBytes = Convert.FromBase64String(base64EncodedCert);
    return new X509Certificate2(decodedPfxBytes, certificatePassword);
}

public void ConfigureServices(IServiceCollection servies)
{
    // ...
    var identityServerBuilder = services.AddIdentityServer();
    var signingCertificate = GetSigningCertificate();
    identityServerBuilder.AddSigningCredential(signingCertificate);
    //...
}

Last, you may need to set an IAM role and/or policy to your EC2 instance(s) that gives access to these SSM parameters.

Edit: I have been moving my web application SSL termination from my load balancer to my elastic beanstalk instance this week. This requires storing my private key in S3. Details from AWS here: Storing Private Keys Securely in Amazon S3

like image 76
F_SO_K Avatar answered Oct 08 '22 16:10

F_SO_K