Table of Contents
- 1 The Cloud Impacts Application Security
- 2 An Insider’s View on Kubernetes/Azure Cloud Protection
- 3 Steps and Prerequisites Summary
- 4 DEPLOYING THE CONTRAST PLATFORM FOR AZURE KUBERNETES INSTANCES
- 4.1 Find your application code
- 4.2 Find the Dockerfile used to build your application image
- 4.3 Pull the Application code from GitHub
- 4.4 Update Kubernetes YAML file(s) with new image and Kubernetes secrets reference
- 4.5 Create a Kubernetes secret/configMap file
- 4.6 Deploy the Kubernetes secret
- 4.7 Deploy the application manifests
- 4.8 Verify the results
The Cloud Impacts Application Security
Organizations everywhere are making their way into the cloud with some form of digital transformation initiative. As a part of these efforts, organizations usually have multiple strategies to execute as they move through their cloud journey, which includes focusing on delivering more value to their customers while positioning themselves for future investments in order to gain market share across their respective verticals.
One of the leading areas for strategic investment is application security. With more development happening now than ever before in history, it makes sense—there are more applications and more moving parts that all need to be kept safe in order to operate. This blog addresses how organizations can incorporate application security into their application stacks using Microsoft’s Azure Kubernetes Service (AKS) and the Contrast Application Security Platform.
An Insider’s View on Kubernetes/Azure Cloud Protection
Microsoft AKS is a Platform-as-a-Service (PaaS) offering from Azure Cloud. The service enables users to deploy and manage containerized applications with myriad use cases, all on a fully managed Kubernetes service. The Contrast Application Security Platform allows organizations to integrate and scale application security with any application stack across distributed environments through the use of embedded security instrumentation.
For this example, let’s assume that an application developer and a platform team are working together in onboarding an application with Contrast in order to gain some insight into the application’s security posture (both vulnerabilities and exploits) during runtime. In this particular case, this is a legacy application that needs to be containerized and deployed into a Kubernetes cluster as part of the organization’s lift-and-shift strategy. In order to limit the amount of overhead to migrate applications into the cloud, the organization decided to use AKS to fully manage their Kubernetes clusters in the Azure Cloud as their deployment target.
Securing an Azure/Kubernetes application with Contrast
In order to onboard the application using a Contrast agent, a Dockerfile is created to first containerize the legacy application. The produced Docker image can then be stored in Azure’s Container Registry (ACR) and ultimately deployed to a cluster hosted on AKS using Kubernetes YAML files.
Steps and Prerequisites Summary
Let’s quickly review how we’re going to approach this process.
- A functioning AKS cluster
- A Contrast Security Account on a licensed Team Server Instance (you can use the free Contrast Community Edition [CE] if desired)
- A working application (we will be using a .NET application .NetFlicks for this demo)
- Working knowledge of AKS
- Working knowledge of Docker builds, images, and containers
- Edit the Dockerfile to embed Contrast into the application deployment
- Update the Kubernetes YAML file to reflect the change in image
- Create a Kubernetes secret file
- Log into your AKS console or CLI
- Create a Kubernetes secret using kubectl
- Deploy the .NetFlicks application’s pod and service using kubectl and our Kubernetes deployment file
- Verify the results
DEPLOYING THE CONTRAST PLATFORM FOR AZURE KUBERNETES INSTANCES
Now we’re ready to get started securing an actual application.
Find your application code
.NetFlicks is a sample application built using Microsoft’s .NET framework. For this demo, we added some vulnerabilities. The application uses the traditional Model View Controller structure (the sample repository is found here).
We will be deploying a Docker image to an existing AKS cluster. In order to do so, we’ll start by editing the application’s Dockerfile.
Find the Dockerfile used to build your application image
Let’s find the Dockerfile, which is located in the root directory of the application’s GitHub repository.
The Dockerfile should resemble the file below:
Dockerfile with commands highlighted
The commands highlighted in red are used to download, authenticate, and install a Contrast agent with our .NetFlicks application.
We will be editing the Dockerfile by removing the environment variables and passing the environment variables and agent configurations via Kubernetes secrets/configMaps. The secrets will be made available to the deployed pods by volume mount from within the deployment YAML configuration. Passing sensitive data and configurations via Kubernetes secrets/configMaps brings our application closer to the cloud-native 12-factor application model because it removes configurations from source code. At a high level, 12-factor applications for cloud-native design push forth best practices when designing services/applications for the cloud (more information can be found here). Another great way to store Kubernetes secrets in AKS is Microsoft’s Secrets Store CSI Driver.
Pull the Application code from GitHub
Using your favorite CLI, run the following command:
$ git clone https://github.com/Contrast-Security-OSS/azure-aks-example.git
Move into the cloned directory, and let’s see what is inside by typing the following commands:
$ cd azure-aks-example
You should see the following files:
$ Dockerfile contrast_security.yaml main.tf
Dockerfile-original database-deployment.yaml outputs.tf
DotNetFlicks.Accessors database-service.yaml package.json
DotNetFlicks.Common deploy parseyaml.py
DotNetFlicks.Engines deploy.sh variables.tf
DotNetFlicks.Managers docker-compose.yml versions.tf
DotNetFlicks.ViewModels entire-minus-netflix-stack-deploy.yaml web-claim0-persistentvolumeclaim.yaml
DotNetFlicks.Web entire-netflix-stack-deploy.yaml web-deployment.yaml
DotNetFlicks.sln exercise.js web-service.yaml
Next, using either Visual Studio Code or the Azure Cloud CLI, open the Dockerfile and remove the environment variables.
Your new Dockerfile should look like this:
$ FROM mcr.microsoft.com/dotnet/core/sdk:2.2 AS publish
COPY ./DotNetFlicks.Accessors ./DotNetFlicks.Accessors
COPY ./DotNetFlicks.Common ./DotNetFlicks.Common
COPY ./DotNetFlicks.Engines ./DotNetFlicks.Engines
COPY ./DotNetFlicks.Managers ./DotNetFlicks.Managers
COPY ./DotNetFlicks.ViewModels ./DotNetFlicks.ViewModels
COPY ./DotNetFlicks.Web ./DotNetFlicks.Web
COPY ./DotNetFlicks.sln ./DotNetFlicks.sln
#Add in the contrast sensors
RUN dotnet add "DotNetFlicks.Web/Web.csproj" package Contrast.SensorsNetCore --package-directory ./contrast
#Compile the app
RUN dotnet publish "DotNetFlicks.Web/Web.csproj" /p:Platform=x64 -c Release -o /app
FROM mcr.microsoft.com/dotnet/core/aspnet:2.2 AS final
RUN uname -a
RUN apt-get update && apt-get --assume-yes install libnss3-tools
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "DotNetFlicks.Web.dll"]
This produces a new Docker image, which will be deployed to our AKS cluster via Kubernetes YAML file. (For more information on how to deploy a Contrast agent using a .NET agent and Docker, please refer to the following Contrast Security documentation.)
Now that we have our code and Dockerfile set, let’s build the docker image using the Dockerfile and the following command. You should be in the directory where your Dockerfile is located; otherwise, you will need to explicitly pass the location of your Dockerfile to your docker build command.
$ docker build -t <REGISTRY_NAME>.azure.io/<REPOSITORY_NAME>:<TAG>.
You will now have the docker image available locally. Next, log into your Azure Container Registry using your docker login (official docs can be found here).
Push your local image by running the following command:
$ docker push <REGISTRY_NAME>.azure.io/<REPOSITORY_NAME>:<TAG>
We can now create our Kubernetes secret and Kubernetes deployment YAML for our .NetFlicks application.
Update Kubernetes YAML file(s) with new image and Kubernetes secrets reference
In order to deploy our application to our AKS cluster, we will have to pass Kubernetes YAML file(s) that will deploy our .NetFlicks application, database, and services.
Note: It is a best practice to use native cloud database solutions and connect those into your applications. We are using a containerized database solution for this blog.
In the same application root directory, there is a directory called “kubernetes/manifests.” This directory houses all the manifest files needed to deploy the application. But before we deploy to our AKS cluster, we’ll need to create the secrets and configMaps to pass our Contrast agent details.
Create a Kubernetes secret/configMap file
This demo will be using a Kubernetes secret/configMap file to house the environment variables used by the Contrast agent to communicate with the Contrast Security Team Server during the application onboarding. Let’s create this file.
Open the file called “contrast_security.yaml” in the root directory. It should look like this:
user_name: <[email protected]>
Make sure to replace the application programming interface (API) information with your own specific environment information. The information needed can be found in your Contrast Security Team Server Portal. Click on the profile pic in the top right and navigate to ‘Organization Settings’, then to ‘API’. Scroll to the bottom of the screen.
The page will look like the following:
Contrast UI organization settings
Include any environment/configuration information that you want to pass to the container itself as it runs in the AKS cluster. This is where we will take the environment variables that were originally hard-coded in our Dockerfile above and insert them into this file so they can be used as a Kubernetes secret.
The updated secrets file for our application should resemble the following:
user_name: <AGENT USERNAME FROM CONTRAST TEAM SERVER>
CORECLR_PROFILER_PATH_64: ‘./contrast/runtimes/linux-x64/native/ContrastProfiler.so’CORECLR_PROFILER: ‘8B2CE134-0948-48CA-A4B2-80DDAD9F5791’
CONTRAST__APPLICATION__NAME: <YOUR APPLICATION’S NAME>
CONTRAST__SERVER__NAME: <SERVER NAME APPLICATION RESIDES ON>
ASPNETCORE_ENVIRONMENT: <NAME OF THE ENVIRONMENT THIS APP IS RUNNING IN>
Deploy the Kubernetes secret
After you have created the Kubernetes secret file, use the following command to create the secret within our AKS cluster:
$ kubectl create secret generic contrast-security --from-file=./contrast_security.yaml
(More information on the use of Kubernetes secrets can be found here.)
Next, we will be deploying our application’s manifest files using kubectl. Prior to deployment, make sure the YAML manifest files contain the correct secret references we created in the previous section.
Deploy the application manifests
Before you execute the .NetFlicks deployment into your AKS cluster, make sure you are in the correct directory:
$ cd kubernetes/manifests
Now that we’re in the correct directory, update the image field in the web-deployment-updated.yaml file with the location of your ACR:
- name: ConnectionStrings__DotNetFlicksConnection
value: Server=tcp:database,1433;Initial Catalog=DotNetFlicksDb;Persist Security Info=False;User
- name: "CONTRAST_CONFIG_PATH"
Type the following commands to deploy the .NetFlicks application stack:
$ kubectl apply -f web-deployment-updated.yaml,web-service.yaml,database-deployment.yaml,database-service.yaml,volume-claim.yaml
The command above will create the deployment along with anything else specified in our deployment file—in this case, the service associated with the .NetFlicks application (LoadBalancer). The Kubernetes service is what makes the application accessible to the outside world via network connectivity.
Verify the results
Now that we have our application deployed into our AKS cluster, let’s hit our application URL. The application’s URL can be found by inspecting the ingress loadbalancer service and entering the following into your browser:
$ <IP FROM LOADBALANCER SERVICE>:90
You can get the IP by using the following code snippet:
$ kubectl get svc web -o=jsonpath=’.status.loadBalancer.ingress.ip’
The following page should render:
.NetFlicks page render
Now that the application is up and running, let’s dive into Contrast. The Contrast Application Security Platform embeds protection in the application code via the Contrast agent. Deploying the Contrast agent gives developers and operations teams access to the following instrumentation-based solutions:
No additional deployments are required.
Let’s look at leveraging Contrast Assess, which gives users the ability to monitor vulnerabilities in real time as a user interacts with an application.
Log into the .NetFlicks application using the following credentials:
Navigate to Admin Settings >> Movies. The top right will have an input search box. Enter the following string and click the search button:
'); UPDATE Movies SET Name="Pwned" --
Now clear the search input so no filter is applied to the results.
The screen should look like the following:
NetFlicks Movies page
What we’ve done is performed a simple SQL injection command that sent a string into the application that changed all the owner names to “Pnwed.” The vulnerability was recorded by the Contrast agent using Contrast Assess as we clicked through our application and sent it to the Contrast Team Server.
Let’s make our way back to the Contrast Security login, and log back into our Contrast Security Team Server instance.
Once we make our way to the “Applications” page, let’s navigate to our .NetFlicks application and take a look at some vulnerabilities that have been analyzed by Contrast as we onboarded our application.
The Contrast Applications page
When we click on the “Vulnerabilities” tab, we can see our list of vulnerabilities encountered as we clicked through our application.
The Contrast Vulnerabilities tab
Remember, Contrast instruments its capabilities and features through the Contrast agent, so you also get the Contrast OSS and Contrast Protect products out of the box. Let’s now take a look at how Contrast Protect blocks a user from exploiting the SQL injection vulnerability—which is a natural extension into higher-level environments, since this is where the application is made available to the outside world.
Navigate to the “Servers” page—top left, next to “Applications.” Make sure Contrast Protect is turned on (green).
Note: Contrast Community Edition does not include Contrast Protect. In order to use Contrast Protect, you will need to obtain a license (Contrast contact information can be found here).
The Contrast Servers page
Next, navigate back to the .NetFlicks Application View and you should see Contrast Protect enabled.
Contrast Protect is enabled in Application View
Now that we have Contrast Protect enabled, let’s make our way to “Policy,” click “Protect,” and then search for “sql” in order to find the SQL injection rule that Contrast Protect will be referring to. Switch the capability from “Monitor” to “Block” in order to prevent the user from being able to exploit the SQL injection vulnerability we found in our .NetFlicks search.
Blocking SQL injection exploitation with Contrast
Note: The Contrast agent takes a minute or two to enable the change in configuration.
Let’s now navigate back to our .NetFlicks application to see what happens when we try to run the same search using the string “’); UPDATE Movies SET Name = ‘Pwned’ –.”
Successfully blocking a potential SQL injection attack
Contrast has successfully blocked the potential attack—all we had to do was turn on Contrast Protect! This, in turn, gives you the ability to block attacks and enable your teams to enhance the application without having to worry about outside users exploiting vulnerabilities. No changes to higher-level environments are needed until your teams are able to deliver the enhancements necessary to address the exploits Contrast finds.
Now we can evaluate our application security posture (vulnerabilities and exploits) and proceed to enhance our application—making it safer and more secure. Remember, security (especially at the application layer) is required to ensure that your organization is not only safe from attacks but also protected against threats that may try to compromise your users or IP.
Once you’re up and running with your first application, it makes sense to incorporate the steps above into your application’s SDLC processes via automation. GitHub Actions is a great way to achieve this kind of enterprise