Programming Azure – A Journey toward configuring a DevSecOps ecosystem using Visual Studio and C#

Written and Published by: Mark Wireman, June 14, 2020

The blog is going to take a bit of a left-curve in the content shifting from the talk of what DevSecOps is toward more practical implementation of not only what it is I am going to show how the “is” can be used to drive DevSecOps all through a single programming platform. A very powerful display of the flexibility and ease of implementing DevSecOps from a Developer’s, Security’s, and Operation’s perspective!

Microsoft Azure is becoming a powerful platform that provides a nice integration of Visual Studio IDE and the Azure SDK to create, manage, build, and deploy a DevSecOps pipeline without the need to navigate a Web-based management console. The issue with a Web-based console is that it always seems to be changing making it frustrating to find out that particular actions or links used regularly are moved to one location or tucked under as sub-actions or disappear altogether. And even some of the static content is either updated or modified with little to no explanation. Hence, Visual Studio and the SDK are coming to the rescue to provide a more constant and consistent way to perform common and day-to-day functions that can be performed manually or can be turned into automated tasks as part of an automation factory.

This is going to be a multi-part series as all of you will be taking the journey with me as I build a Windows application that will leverage the powerful features of the Azure SDK through the programming functionality and capability of the Visual Studio 2019 IDE. The next series of several blogs will be peppered with code samples, screenshots, and a flow that will allow you to understand the concepts and follow along with a solid understanding of what the code is and doing.

Before we get to the fun stuff, there is a bit of a disclaimer: The proceeding series does assume you already have experience with working in the Visual Studio IDE and have some programming experience with C#. If you are new to programming and new to the Visual Studio IDE it is recommended you first spend some time with understanding the basics and concepts of programming in C# via the Visual Studio IDE before taking this journey. I do not go into the depth of how to create a solution or project in Visual Studio or how to create a class or details of how certain basic data types or collections work, for example. However, if you are adventurous and want to dive into learning the Azure SDK while simultaneously learning how to code in C# through the Visual Studio 2019 IDE, hey, who am I to stop you!

Now let’s dive right in!

Setting up the Solution and Referencing the Azure SDK

The very first step is to get the solution created and a few projects added. Then we’ll get the Azure SDK components installed that we will initially need to create our storage account and to create a new resource group (hang tight we’ll get to these elements later!).

The solution I created is ‘Azure Playground’ with two projects ‘AzureObjects’ (a Class Library) and ‘AzurePlayground” (a Windows Desktop Application). The ‘AzureObjects’ library will be used as the business logic layer and the ‘AzurePlayground’ desktop application will be the UI layer. Given that we are using the Azure SDK to work with the Azure platform we do not need a data object layer to interact with a data source (a huge sigh of relief!). The only sensitive information we will need to manage is the authentication file we will use to authenticate through the ‘AzurePlayground’ application with the Azure platform (more on this in the next blog series). For now, however, we are going to proceed with setting up the prerequisite elements that do not require the use of the authentication file.

Figure 1 is the layout of the ‘Azure Playground’ solution. We will walk through the projects and the classes in short order, beginning with the steps to program the capability to create a storage account through the Azure SDK (this will be our first set of blog series).

Programming Azure – A Journey toward configuring a DevSecOps ecosystem using Visual Studio and C#
Figure 1. The ‘Azure Playground’ solution layout.

After you set up the solution with the two projects, the next step is to add the Azure SDK components that we will initially use and can be easily installed using the Nuget Package Manager. Figure 2 shows the installed components that we will be using for this first blog series.

Figure 2. The Azure SDK elements installed through NuGet.

One final item to install is the Azure CLI. While we will be doing the majority of the work through the C# code, there are a few items that we can only perform through the Azure CLI (e.g. obtaining the authentication file). These items are mostly administrative items and we will not be calling the Azure CLI directly from the C# code (this is very bad from a security perspective – one should avoid at all costs executing command-line functions directly from application code).

Creating a Storage Account – The design

We are going to begin the journey with the ability to add a Storage Account through the ‘Azure Playground’ application. This will require a Windows form to allow the user to input the required attributes for creating the storage account and the business logic to take the attributes and tell Azure to create the account using the Azure SDK.

A storage account takes the following required attributes:

  • Resource group
  • Storage account
  • Location
  • Performance
  • Account kind
  • Replication
  • Access tier

So, we begin by creating the ‘StorageAccountManagement’ Windows form with the required attributes as shown in Figure 3 (plus a few others that will be explained in a bit).

Figure 3: Storage Accounts Management Windows form layout.

Figure 4 is the list of the Windows form controls that make up the Form layout (I use the “Clean Code” concept so matching the label name to the labels should be self-explanatory)

Figure 4: Windows forms components used in the ‘StorageAccountsManagement’ Windows form layout.

You’ll notice some additional attributes like Keys and Connection String. These are attributes that are provided after the Storage Account is created and will not be required when creating a new Storage Account. More on this later in this blog post.

Ok, now that we have the design layout for the Windows form, it is time to turn our attention toward populating some of the form elements with values for the user to select that is not, necessarily, dependent on the login information (well, this is mostly true – the Location attribute, which is coming up, is, technically, dependent on the User’s Azure subscription; however, we are not going to apply the filtering at this point instead opting to show all the possible Locations available in Azure platform).

Since we are still in our design stage, there are three important classes that are created as part of the ‘AzureObjects’ library – ResourceGroups, StorageAccounts, and Utilities. The Utilities class will be used to handle the common set of functions that are used by the other class objects and will only be accessible to the classes in the ‘AzureObjects’ library (using the internal declarative for the function definitions). The ResourceGroups class will be used to manage the Resource Groups objects in Azure and the StorageAccounts class will be used the manage the Storage Accounts in Azure.

Stage 1 of Implementation – UI flow

The UI is designed to both display existing Storage Account details and to create a new Storage Account. Additionally, the UI will allow the User to either select an existing Resource Group to place the new Storage Account into or create assign a new Resource Group.

Figure 5 is the run-time view of the ‘Storage Accounts Management’ visible controls. The implementation concept here is the ComboBox for the list of existing Storage Accounts will show the details of any existing Storage Accounts in the Azure instance for a selected Storage Account in the drop-down. However, the more sensitive information – Keys and Connecting String – are not shown by default. The User will be required to click the CheckBox ‘Show Keys and Connection String’ (see Figure 6).

Figure 5: UI layout of the ‘Storage Accounts Management’ Windows form at run-time.
Figure 6: The UI form showing the TextBox where the Storage Account Keys and Connection string data will be displayed after checking the ‘Show Keys and Connection String’ CheckBox.

Then next step is to implement the flow for adding a new Storage Account to the Azure subscription. To do this the User will click the ‘Add New Storage’ Button which will then hide the ‘Show Keys and Connection String’ CheckBox and make visible a CheckBox ‘Create New Resource Group?’ that, when checked, will display a TextBox control to input the new Resource Group name. Otherwise, a ComboBox will be shown with a list of existing Resource Groups that the User will then select from (see Figure 7). When the User clicks ‘Save’ the display will return to the view in Figure 6.

Figure 7: UI display for adding a new Storage Account and a creating a new Resource Group.

The code to make this happen is the following:

    private void AddNewStorage_Click(object sender, EventArgs e)
    {
       setVisibilityAddNewStorage(true);
    }
    
    private void setVisibilityAddNewStorage(bool visible)
    {
        this.CreateResourceGroup.Visible = visible;
        this.Save.Visible = visible;
        this.ShowKeysAndConnectionString.Checked = false;
        this.ShowKeysAndConnectionString.Visible = !visible;
    }

    private void CreateResourceGroup_CheckedChanged(object sender, EventArgs e)
    {
        if(this.CreateResourceGroup.Checked)
        {
            this.NewResourceName.Visible = true;
        }
        else
        {
            this.NewResourceName.Visible = false;
        }
    }

    private void Save_Click(object sender, EventArgs e)
    {
        setVisibilityAddNewStorage(false);
        this.CreateResourceGroup.Checked = false;

    }

    private void ShowKeysAndConnectionString_CheckedChanged(object sender, EventArgs e)
    {
        if(this.ShowKeysAndConnectionString.Checked)
        {
            this.KeysAndConnectionString.Visible = true;
        }
        else
        {
            this.KeysAndConnectionString.Visible = false;
        }
    }

Stage 2 of Implementation – Wiring up the Locations to the ComboBox

Now it is time to dive into the wiring up of the UI to information obtained from the objects in the Azure SDK. The journey will begin by listing all of the available Azure Locations to the Locations ComboBox control on the ‘Storage Accounts Management’ Windows form. The ComboBox will be populated will the Locations during the Windows form initialization process. We will use the ‘AzureObjects’ library and the StorageAccounts and Utilities class to implement the functionality to populate the ComboBox along with a cool technique called Reflection to avoid having to maintain and manage a list of Azure locations and to keep the locations up-to-date without having to update the code in the future.

The first step is to add an internal static method in the Utilities class that will use the Azure SDK’s Microsoft.Azure.Management.ResourceManager.Fluent.Core class to then reference the Region class that will be used to get the list of Locations available in the Azure platform. However, the list is not available as a method so we’ll use Reflection to get the Field display names and the corresponding Field values which will then be stored in a Hashtable in a Key/Value pair. While the Region class does provide a method to get the values (Region.Values) this is not a user-friendly way to visually show the User the list of Locations. So we are going to the cool trick of reflecting the Region class that will pull the information we need while always keeping the Location list up-to-date as the SDK is updated without the need to modify the code (unless, of course, Microsoft deprecates the Region object or makes other drastic changes that will break the reflection technique).

The following is the Utilities.GetLocationList source code:

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.ComponentModel.Design;
using Microsoft.Azure.Management.ResourceManager.Fluent.Core;
using System.ComponentModel;
using System.Collections;

namespace AzureObjects
{
public static class Utilities
{
      internal static Hashtable GetLocationsList()
      {
         Type myType = typeof(Region);
        
        FieldInfo[] myField = myType.GetFields();
        Hashtable locationnames = new Hashtable(myField.Length);

        for (int i = 0; i < myField.Length; i++)
        {
            locationnames.Add(myField[i].Name, myField[i].GetValue(null));
        }

        return locationnames;
      }

}
}

The Utilities.GetLocationsList() method will now be a commonly used method as we continue to journey through the development of the ‘Azure Playground’ because locations and resource groups are two of the most frequently required attributes for resources in the Azure platform. And it is the beauty of reflection and the use of a HashTable that gives this method simplicity while simultaneously given it immutability with the only dependency on the Azure SDK’s management of the available Azure locations!

Now that the hard part is done, the next steps are to connect the dots from the UI ComboBox form control to the list of locations provided by the Utillities.GetLocationsList method. Given that we are working with Storage Accounts, the StorageAccounts class in the ‘AzurePlayground’ library will handle the call to the Utilities.GetLocations method on behalf of the Windows Form component. And, given that the work is actually being handled in the Utilities class this is a simple task as shown in the following code segment:

public Hashtable GetListOfLocations()
{
return Utilities.GetLocationsList();
}

Ah, the simplistic beauty of the abstract nature of OO programming that provides easy of flow and abstracts away the complexities of processing with only a simple call to the processor knowing the information will be returned with ease!

With the work complete at the business logic layer, now it is time to populate the Locations ComboBox with the list of available locations. The following code from the Windows Form ‘StorageAccountsManagement’ will make the magic happen using the list of locations from the HashTable collection:

...
StorageAccounts storageaccount = new StorageAccounts();
...
public StorageAccountsManagement()
{
InitializeComponent();
this.populateLocations();
}
    
private void populateLocations()
    {
        this.Location.DataSource = new BindingSource(storageaccount.GetListOfLocations(),null);
        this.Location.DisplayMember = "Key";
        this.Location.ValueMember = "Value";
    }

Summary

And now we have our Locations populated without the need to maintain or manage a list by harnessing the power of Reflection and leveraging the robust functionality provided by the Azure SDK!

The journey to leveraging Visual Studio 2019, C#, and the Azure SDK has now begun as we wrap up our initial design and implementation approach for working with Storage Accounts. The next blog will continue to build on this foundation and finish the functionality for displaying, modifying, removing, and adding new Storage Accounts and Resource Groups. And, as an added bonus, we’ll also add the source code to an Azure source code repository that can be shared either Publicly or Privately (I will share mine Publicly).

By admin