In this post I'm talking about how you can use something called
secureValue, or secure environment variables, with your Azure Container Instance. Given the sensitive nature of some data you put into the variables, it is a good idea to understand different ways to protect some of that data - with secure environment variables you can hide the values from the UI and API calls to the ACI, and from the Azure Portal.
Running your applications in the cloud has become increasingly popular. Migrating your .NET applications to .NET Core and hosting them as Docker images in the cloud is pretty trivial, even for the more complex types of applications - I've done this a lot, and today .NET Core is so mature that there's no obvious reason to use the full fledged .NET Framework for any of my use cases.
When running your containers in Azure Container Instances, you sometimes pull in sensitive data, like a connection string to an Azure Storage Account, or other information that you shouldn't risk disclosing to any third part.
There's multiple ways to protect sensitive data. The other posts in this series discuss a few of the other options. Right now, we're checking out secure environment variables.
Considerations for Security
Using secure environment variables is great. It helps us protect snooping eyes, screenshots, someone browsing the Azure portal, you name it. But it does not inherently mean greater security of the values themselves - they're still exposed inside the container, so should your container or code be compromised, the environment variables are clearly accessible from inside the containers. This is something to be aware of, so the word "Secure" means you cannot read it after you create it, outside of the container; however it's still possible from within, for obvious reasons.
Another thing to note, which I've seen in the field (yikes), is when someone is defining their
yaml files, they put the secure environment values inside the yaml file, but the file remains on disk or (oh no) in a code repository.
Creating secure environment variables in ACI
Creating environment variables is common for a lot of different types of applications. Sometimes, however, you want them to be treated with a bit more respect than the plain-text visible environment variables. This is where
Secure value comes into play.
There's a couple of ways to accomplish this. The two main options I've used is the Azure CLI directly, or by creating the definition in
yaml and then issue the create command from the CLI.
Option 1: Secret environment variable with a YAML definition
Here's a sample definition file. Mine is called
- name: aci-demo-app-with-secure-enviromentvariables
- name: 'AzureStorageAccountConnectionString'
- server: acrdemomagic.azurecr.io
The difference between a non-sensitive and sensitive value in this case is just whether you specify "secureValue" or "value" in front of the data. Then the system knows how to deal with it. Magic.
Things to note:
acrdemomagic.azurecr.io/aci-demo-app:latest: this is my docker image in ACR.
environmentVariables.AzureStorageAccountConnectionString: this is the name of the variable that my C# app will read.
environmentVariables.secureValue: the value of the variable, which will later be hidden.
imageRegistryCredentials: I'm using a private Azure Container Registry, so we have to specify the credentials to access it when we spin up the new image.
Next, let's prove that it works by creating this container group and container instance by shooting off the following command:
az container create -g demo -f aci-demo-with-secure-variables.yaml
It works to deploy this, and we can see that the secure environment variable is attached. It is displayed as any other environment variable, but there's no value being displayed:
Before we verify that it works, let's try to do the same thing but from the Azure CLI instead. Next up, command line only.
Option 2: Secret environment variables with the Azure CLI
If you're not a declarative type of person, that's cool too. Have no fear, because the CLI is here!
In my previous post I mentioned how to create an ACI and specify an Environment Variable. Now, the only difference is that you specify it slightly differently on the last part.
You can replace the
-e parameter with
--secure-environment-variables, which would then look like this:
az container create
Creating the ACI with this should yield the same result as in the previous section when doing it with YAML, and it should be treated as a normal Environment Variable inside the container.
Verifying that the Secure environment variables are accessible inside the containers
At this point we want to verify that the instance of our container exist, is running and that we cannot see the value of the secure environment variable.
Let's do it both with the Azure CLI and in the portal, depending on which approach you prefer.
Show ACI using Azure CLI
az container show -g demos -n aci-demo-app-with-secure-environmentvariables
We can clearly see that the secretValue is null, and the value is null. Great - we cannot snoop from the outside and see the connection string now.
Show ACI using Azure Portal
If you're a UI person and want to check it out from the Azure Portal, that's okay too. Here's where we can list the variables for our ACI:
Because it's a secret value, it's not displayed in the UI either. Success.
Show the logs of the container to verify that it works
If our app is running correctly, it should produce some log messages in the Logs section of the Container Instance page in the Azure Portal.
My C# .NET Core app is already built to use the storage connection string environment variable, and that it is of type secureValue doesn't matter to the underlying container - variable as variable, it's accessible inside the container - so with C# we can grab it just like before with no code change:
If you want to display the logs directly from the CLI, see my previous post where I explain how you can do that. Search for
az container attach.
We've successfully looked two ways to set secure environment variables on our Azure Container Instance, and have walked through these things:
- Define secure environment variables in your
- Define secure environment variables in your
az containerCLI commands.
- Verify that we cannot read the secure environment variables.
- Verify that our C# app play along and can keep utilizing the
Environment.GetEnvironmentVariable()methods without any code changes.