19

I am using AWS Lambda and can use Alias feature to point to multiple code promotion stages that we have (e.g. dev, qa, prod etc). I have setup the alias the same name as stages. Most of these functions gets triggered from S3 or SNS which has a different instance for each stage.

How can I setup a alias based environment variable so the function can get the specific info. The env vars setup in the base function(typically dev) gets carried over to all alias which does not work for deployment.

I know how to use stage variables in API gateway but the current use is not via gateway.

1
  • 2
    I'm currently encountering this same issue, we're using Lambdas in Amazon Connect, and we need to start using aliases to denote between different environments. For my use case, I'll be using a configuration file in the code to define the environment variables as part of the deployment package. For any secure information, I'll be leveraging the Secrets Manager to store tokens/keys/credentials. This article has some very good information on this that I'll reference while building this out, and thou Commented Apr 6, 2020 at 16:02

4 Answers 4

14

I don't believe there is a way to achieve what you are trying to. You would need to publish three versions of your Lambda function each with the correct environment variables and point each of your aliases to the correct version of the function.

You could use the description fields to help describe the versions before you point the aliases to them too, to make the changes more understandable.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for the reply. Just wanted to make sure I am not missing something here. I have it exactly the way you suggested but the issue is to keep the code in sync as we do not have any automation yet. It will be very nice addition to the AWS Lambda imho.
It's funny how the AWS docs on versioning and aliasing lambdas have their primary example use case as having an alias for each environment and promoting from one to another, but lacks environment specific variables. The moment you need to introduce environment variables, aliasing and versioning completely falls apart.
this may have changed over the years but AWS now explicitly recommends separate accounts as the way to manage environments: aws.amazon.com/blogs/compute/… but if the requirement is to use one account, you would need to build the environment variables setting for each version into your deployment process like other comments suggest
10

I also find it interesting this isn't part of the plan for aliases, however you do have the context available in your code - Context.InvokedFunctionArn

I think the MINDSET is that you may call, for example, a S3 bucket and have a prefix of TEST or DEV or PROD (based on context InvokedFunctionArn you know which alias). Given this context and security based on the ARN you can use bucket policy / IAM to restrict your TEST ARN can only reach TEST s3 prefix files. That solves security between environments.

NOTE: I disagree with this model and think environment variables should be in he aliases, and if not specified in the alias fall back to what is in the version.

Although this works, the complexity around extra conditions on prefix, etc. is something many times will be misconfigured - Having a separate bucket seems much safer and matches the Serverless Application Model documentation better.

1 Comment

This is what I was thinking of doing but it seemed a bit messy. I guess if there's no other way...
3

The lambda context has invoked_function_arn – The Amazon Resource Name (ARN) that's used to invoke the function. Indicates if the invoker specified a version number or alias.

You can then use the alias to find the variables via Systems Manager parameter store, instead of environment variables.

Comments

1

EDIT I'll leave this answer here as it may help some people but note that I found AspNetCoreStartupMode.FirstRequest caused longer cold starts by a few seconds.


I added some code to the LambdaEntryPoint to get the alias at Startup which means you can use it to load environment specific config:

public class LambdaEntryPoint : Amazon.Lambda.AspNetCoreServer.APIGatewayProxyFunction
{
    private ILambdaContext LambdaContext;

    public LambdaEntryPoint()
        : base(AspNetCoreStartupMode.FirstRequest)
    {

    }

    [LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]
    public override async Task<APIGatewayProxyResponse> FunctionHandlerAsync(APIGatewayProxyRequest request, ILambdaContext lambdaContext)
    {
        LambdaContext = lambdaContext;

        return await base.FunctionHandlerAsync(request, lambdaContext);
    }

    protected override void Init(IWebHostBuilder builder)
    {
        var alias = LambdaContext?.InvokedFunctionArn.Substring(LambdaContext.InvokedFunctionArn.LastIndexOf(":") + 1);

        // Do stuff based on the environment

        builder
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.AddJsonFile($"appsettings.{alias}.json", optional: true, reloadOnChange: true);
            })
            .UseStartup<Startup>();
    }
}

I've added a gist here: https://gist.github.com/secretorange/710375bc62bbc1f32e05822f55d4e8d3

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.