Continuous Integration, DevOps, Docker

CosmosDB linux container for your CI builds

4 min read

If you have been following Microsoft Build 2021, you may have seen the news that the CosmosDB linux container is now out. This is great news for the ones who finally want to test on a *nix environment.

As of this post, the CosmosDB linux container is in preview. As stated in the documentation, there are some limitations:

The Cosmos DB Linux Emulator is currently in preview mode and supports only the SQL API. Users may experience slight performance degradations in terms of the number of requests per second processed by the emulator when compared to the Windows version. The default number of physical partitions which directly impacts the number of containers that can be provisioned is 10.

We do not recommend use of the emulator (Preview) in production. For heavier workloads, use our Windows emulator.

Today, I will show you how you can automate the CosmosDB container for your CI builds, in particular Azure DevOps, running on Linux and Windows machines. If you plan to use the container on a machine running Windows, but using Docker Linux container mode, you will run into some Windows limitations while automating the process. Read more about that below.

Note that the CosmosDB linux image needs to be refreshed, until I believe, the preview will be done. The container has an evaluation period until it is deemed not usable anymore. This is the same idea when you use Windows preview builds.

Using the container on Windows build agents

As mentioned earlier, there are some limitations if you want to automate the creation of the containers on the fly on a Windows agent.

The CosmosDB linux container uses self-signed certificates to secure the connectivity to its endpoint. Once you start the container, a new self-signed Root CA certificate is created, and, using that Root CA certificate, a child certificate is created to secure the endpoint. This means that this Root CA certificate needs to be manually trusted each time the container is created (does not apply if the container is stopped and restarted).

The limitation you will run into is that, for security reasons, when you want to trust a self-signed certificate on Windows, you will get a security warning of the sort when trying to import this Root CA certificate into the CurrentUser/Root store.

Unfortunately, it is impossible on Windows to bypass this security warning when installing the certificate to the CurrentUser/Root store. As stated this post, the popup is raised by a crypt32.dll library when calling CertAddCertificateContextToStore function and attempting to install the certificate to for instance, CurrentUser\Root store (other stores are not affected). This was made to prevent malicious applications to silently install certificates to current user’s trust store.

If you try to import the certificate to the LocalMachine/Root store (running administrator), you will not get the popup. If you are running your own agent, and the VSTS (azure devops) agent is setup with administrative access*, you will have access to the LocalMachine store and this will not be a problem.

*: You just need to make sure your build service account (which can be a local account, a domain account, or Local Service in a workgroup) also has administrative permission.

Configuring the container for Azure DevOps

As the CosmosDB SDK is, by default, using Direct connectivity mode, the CosmosDB container needs to have the IP of the machine overridden in its settings. Moreover, you will also need to trust the Root CA certificate.

Getting the IP address

Windows

To get the machine’s IP address, you can run the following in PowerShell. Replace the interfaceName with your interface name. You can get it by executing the Get-NetIpAddress cmdlet

Linux

Starting the emulator

The container needs to setup its partitions before it can be used. As such you need to wait until the container is fully started. The following is an inline script that starts the container using PowerShell.

As you can realize in the script, I keep track of the containerId generated with a variable. Set isOutput=true if you want to use it in another job/stage.

Trusting the Root CA certificate

Windows

If you want to add the certificate to the LocalMachine/Root store, you will need administrator privileges as mentioned above.

Replace <CI-Build-Number> with your CI build number. This will help in case you need to cleanup stuff that are lingering/not needed anymore. If you aren’t using this for your CI build, you can remove this.

Note: as mentioned above, if you are adding it to CurrentUser/Root store, you will get a popup. This will not work in an automated environment.

Linux

The certificate can be copied to the folder that contains custom certificates in the Linux distribution. Commonly on Debian distributions, it is located on /usr/local/share/ca-certificates/.

Stopping the emulator

Stopping the emulator is as easy as running docker rm -f $(variables.containerId). You can have a script task that wraps that command.

To remove the certificate, you can execute the following command

Linux: rm -f /usr/local/share/ca-certificates/emulatorcert.crt

Windows: Get-ChildItem -Path Cert:\LocalMachine\Root\$(rootCAThumbprint) | Remove-Item -Force

Task example

The following are examples on how to accomplish the initial steps, the start and stop of the container.

Linux

Windows