Strange error disallow my .NET core application to start

Today I cloned in my workstation a .NET core application that works perfectly on my laptop, but when I started it I got this error

An attempt was made to access a socket in a way forbidden by its access permissions

I’ve spent almost 10 minutes to find why my netsh rule is not working (I work with a user that is not administrator of the machine) and finally, by frustration I opened Visual Studio with administrator user, just to verify that the error is still there.

For whatever reason (I’ve not time to investigate right now) port 21000 is somewhat blocked by some firewall rule apparently, because it is free, but kesterel is continuing giving me that error even if runs as admin.

Changing port solved the issue, but left me puzzled :/

Gian Maria.

Release software with GitHub actions and GitVersion

One of the nice aspect of GitHub actions is that you can automate stuff simply with command line tools. If you want to do continuous release of your software and you want to use GitVersion tool to determine a unique SemVer version from the history, here is the sequence of steps.

1) Iinstall/update gitversion tool with commandline tools
2) Run GitVersio to determine SemVer numbers
3) Issue a standard build/test using SemVerNumbers of step 2
4) If tests are ok, use dotnet publish command (with SemVer numbers) to publish software
5) Zip and upload publish result
6) It the branch is Master publish a GitHub release of your software.

Automating your CI pipeline using only CommandLine tools makes your build not dependent on the Engine you are using.

I’ve done such small exercise on a public project you can found here (https://github.com/AlkampferOpenSource/StupidFirewallManager) and it is composed by two command line tools, one is server version the other is the client.

Complete workflow definition can be found here (https://github.com/AlkampferOpenSource/StupidFirewallManager/blob/master/.github/workflows/dotnetcore.yml).

In this example I’m simply using some open source tasks to automate the whole process with GitHub Actions. The first step is being sure that right version of DotNetCore Sdk is used, and that GitVersion tool is installed.

    steps:
    - uses: actions/checkout@v1
      
    - name: Fetch all history for all tags and branches
      run: git fetch --prune
    
    - name: Setup .NET Core
      uses: actions/setup-dotnet@v1
      with:
        dotnet-version: '5.0.100-preview.1.20155.7'  

    - name: Install GitVersion
      uses: gittools/actions/gitversion/setup@v0.9
      with:
          versionSpec: '5.1.x'

The cool part is that I do not need to have anything preinstalled on the machine that runs the action, everything will be downloaded and installed by action definition. In this specific example my software is build with a pre-release of .NET Sdk (5.0.100-preview), a tooling that probably is not preinstalled in the action machine, but thanks to the capability of GitHub actions I can simply require installation on the fly before compiling everything. 

Being able to install required toolchain directly from Action definition allows you to run your action on public available GitHub agents.

Point 2 is achieved simply running GitVersion tool (installed from point 1) with a dedicated action. Another cool part of GitHub action is that you can simply refer custom action directly from your definition, no need to install anything.

- name: Use GitVersion
      id: gitversion # step id used as reference for output values
      uses: gittools/actions/gitversion/execute@v0.9
    - run: |
        echo "Major: ${{ steps.gitversion.outputs.major }}"
        echo "Minor: ${{ steps.gitversion.outputs.minor }}"
        echo "Patch: ${{ steps.gitversion.outputs.patch }}"
        echo "PreReleaseTag: ${{ steps.gitversion.outputs.preReleaseTag }}"
        echo "PreReleaseTagWithDash: ${{ steps.gitversion.outputs.preReleaseTagWithDash }}"
        echo "PreReleaseLabel: ${{ steps.gitversion.outputs.preReleaseLabel }}"
        echo "PreReleaseNumber: ${{ steps.gitversion.outputs.preReleaseNumber }}"
        echo "WeightedPreReleaseNumber: ${{ steps.gitversion.outputs.weightedPreReleaseNumber }}"
        echo "BuildMetaData: ${{ steps.gitversion.outputs.buildMetaData }}"
        echo "BuildMetaDataPadded: ${{ steps.gitversion.outputs.buildMetaDataPadded }}"
        echo "FullBuildMetaData: ${{ steps.gitversion.outputs.fullBuildMetaData }}"
        echo "MajorMinorPatch: ${{ steps.gitversion.outputs.majorMinorPatch }}"
        echo "SemVer: ${{ steps.gitversion.outputs.semVer }}"
        echo "LegacySemVer: ${{ steps.gitversion.outputs.legacySemVer }}"
        echo "LegacySemVerPadded: ${{ steps.gitversion.outputs.legacySemVerPadded }}"
        echo "AssemblySemVer: ${{ steps.gitversion.outputs.assemblySemVer }}"
        echo "AssemblySemFileVer: ${{ steps.gitversion.outputs.assemblySemFileVer }}"
        echo "FullSemVer: ${{ steps.gitversion.outputs.fullSemVer }}"
        echo "InformationalVersion: ${{ steps.gitversion.outputs.informationalVersion }}"
        echo "BranchName: ${{ steps.gitversion.outputs.branchName }}"
        echo "Sha: ${{ steps.gitversion.outputs.sha }}"
        echo "ShortSha: ${{ steps.gitversion.outputs.shortSha }}"
        echo "NuGetVersionV2: ${{ steps.gitversion.outputs.nuGetVersionV2 }}"
        echo "NuGetVersion: ${{ steps.gitversion.outputs.nuGetVersion }}"
        echo "NuGetPreReleaseTagV2: ${{ steps.gitversion.outputs.nuGetPreReleaseTagV2 }}"
        echo "NuGetPreReleaseTag: ${{ steps.gitversion.outputs.nuGetPreReleaseTag }}"
        echo "VersionSourceSha: ${{ steps.gitversion.outputs.versionSourceSha }}"
        echo "CommitsSinceVersionSource: ${{ steps.gitversion.outputs.commitsSinceVersionSource }}"
        echo "CommitsSinceVersionSourcePadded: ${{ steps.gitversion.outputs.commitsSinceVersionSourcePadded }}"
        echo "CommitDate: ${{ steps.gitversion.outputs.commitDate }}"

Point 3 requires only a run of dotnet restore followed by a dotnet test, to verify that code compiles and all tests are green.

    - name: Restore nuget with dotnet
      run: dotnet restore src/StupidFirewallManager.sln
           
    - name: dotnet tests
      run: dotnet test src/StupidFirewallManager.sln /p:AssemblyVersion=${{ steps.gitversion.outputs.assemblySemFileVer }} /p:FileVersion=${{ steps.gitversion.outputs.assemblySemFileVer }} /p:InformationalVersion=${{ steps.gitversion.outputs.Sha }}

A special mention is made to dotnet test parameters, where I specified AssemblyVersion, FileVersion and InformationalVersion directly from command line, using the SemVer number of GitVersion as assembly and file version, but full SHA for informational version.

You have various method to choose version number of the software during build phase, with full Framework you are forced to modify attributes in AssemblyInfo.cs (or AssemblyInfo.vb) before issuing the build. That options is available in GitVersion with UpdateAssemblyInfo options, but it is really clumsy because it does not gave you the ability to choose exactly what number goes in InformationalVersion, that, in my opinion, is most important of all the three. This is why in the past I’ve always use a PowerShell version to update AssemblyInfo.cs.

To be fair, GitVersion does an excellent work in updating AssemblyInfo.cs, but I’ve found a couple of problems, the first is that it actually only Updates the attributes, so you should not forget to insert an AssemblyInformationalVersion in your source code. The second problem is that it uses a too long name for that value, something like 0.5.0-alpha.11+Branch.develop.Sha.21fa38932256d7b64661e6363982dda39eb48b23. While it contains the Sha of the repository, that in my opinion is the most important value, it should be at first position of the string, due to limiting space you have when you look at file property in windows (Figure 5).

Using full Git Sha as informational version gives you the exact version of the code used to produce that artifacts. No way to alter the code and have the same Git Sha makes that number really important and usually it is the only information you need as Informational Version.

Points 4 and 5 are a simple set of Publish/compress/upload artifacts steps, made easy by the presence of 7zip in all machines (thanks Giulio for pointing me in the right direction).

    - name: dotnet publish server
      run: dotnet publish src/StupidFirewallManager/StupidFirewallManager.csproj --configuration release /p:AssemblyVersion=${{ steps.gitversion.outputs.assemblySemFileVer }} /p:FileVersion=${{ steps.gitversion.outputs.assemblySemFileVer }} /p:InformationalVersion=${{ steps.gitversion.outputs.Sha }}

    - name: dotnet publish client
      run: dotnet publish src/StupidFirewallManager.Client/StupidFirewallManager.Client.csproj --configuration release /p:AssemblyVersion=${{ steps.gitversion.outputs.assemblySemFileVer }} /p:FileVersion=${{ steps.gitversion.outputs.assemblySemFileVer }} /p:InformationalVersion=${{ steps.gitversion.outputs.Sha }}
    
    - name: 7Zip client
      run: 7z a -t7z -mx=9 client.7z ./src/StupidFirewallManager.Client/bin/release/netcoreapp5.0/publish/
    
    - name: 7Zip server
      run: 7z a -t7z -mx=9 server.7z ./src/StupidFirewallManager/bin/release/netcoreapp5.0/publish/

    - uses: actions/upload-artifact@v1
      with:
        name: "StupidFirewallManagerServer-${{ steps.gitversion.outputs.fullSemVer }}"
        path: server.7z

    - uses: actions/upload-artifact@v1
      with:
        name: "StupidFirewallManagerClient-${{ steps.gitversion.outputs.fullSemVer }}"
        path: client.7z

I’ve chosen to always create 7zip file with the same name (client.7z and server.7z) but when it is time to upload to pipeline as artifacts, it is nice to change name and give a full SemVer number. As you can verify, since we are in .NET Core, I was able to specify Assembly, File and Informational version directly in command line, without any need to have attributes in AssemblyInfo.cs files. An approach that I really like and prefer (no file to search and modify before the build).

In Figure 1 you can finally find how the artifacts are named in Action run summary page.

Artifacts uploaded by action run, you can notice the full semver.

Figure 1: Artifacts uploaded by action run, you can notice the full semver.

For final step (release) I’ve chosen to use a custom action to publish file on GitHub release and to automatically create release if no one with that name was created. I know that there are now official actions (from GitHub team) but this custom action worked perfectly in the past and it is still perfectly working today, so why change.

    - name: Upload server binaries to release
      if: contains(github.ref, 'master')
      uses: svenstaro/upload-release-action@v1-release
      with:
        repo_token: ${{ secrets.GITHUB_TOKEN }}
        file: server.7z
        asset_name: Server.7z
        tag: "${{ steps.gitversion.outputs.fullSemVer }}"
        overwrite: true
        
    - name: Upload client binaries to release
      if: contains(github.ref, 'master')
      uses: svenstaro/upload-release-action@v1-release
      with:
        repo_token: ${{ secrets.GITHUB_TOKEN }}
        file: client.7z
        asset_name: Client.7z
        tag: "${{ steps.gitversion.outputs.fullSemVer }}"
        overwrite: true

The only peculiarity of these two steps is the if clause, that allows me to ask Action engine to run this step only if the the ref is master. If you look at execution steps of a branch different from master, those two steps are not executed.

Action ran on branch different from master, upload release steps are skipped

Figure 2: Action ran on branch different from master, upload release steps are skipped

If you instead look at logs from an execution of master branch, the two steps are executed. As usual the name of the release is taken from SemVer numbers returned by GitVersion.

image

Figure 3: Publish artifacts to a standard GitHub release output

After the action ran on master, you should see a brand new release of your Repository, containing not only source code, but also published artifacts. As you can see, I’ve decided to upload artifacts with current name (server.7z and client.7z) because number was already present in Release Number

image

Figure 4: Release created by action run for branch master.

You can choose to release whatever branch you like, usually you release hotfix, release and master branch, but you can always grab the artifacts directly from action run output, so I’ve opted to create a real release only from master and stable version.

As final check you should download the release and verify that AssemblyVersion, FileVersion and InformationalVersion were correctly set in the assembly. As you can see in Figure 5 my released software was correctly marked with the correct version.

Versioning of the assembly is present and correct

Figure 5: Versioning of the assembly is present and correct

This last check is especially important, not only for software that will be release with Nuget Packages, but also for executable, because it can immediately tells you the exact version and the exact source code that was used to compile that specific version of the software.

Gian Maria.

One Team Project to rule them all

A similar post was made lots of time ago, but since this is always an hot topic, it is probably the time to refresh with new UI and new concepts of Azure DevOps.

The subject is, how can I apply security to backlogs if I adopt the strategy one single Team Project subdivided by teams?

The approach One Team Project to rule them all is still valid as today, because, once you have a team project, you can divide it with Teams, where each team has its own backlog (or share a single backlog between teams) making everything more manageable.

If you adopt the Single Team Project approach, usually a question of security arise, what if I need people of Team A being able to view only backlog of Team A and Team B are able to view backlog of Team B? Clearly if you create more than on Team Project the solution is obvious, if John is in Team Project A  and Jane is in Team Project B, each one will see only the backlog of Team Projects he/she belongs. This happens because each Team Project has its own user and you can see code, work items, pipeline of a Team Project only if you belong to that Team Project.

Team Project is useful if you need to segregate information between various member, so members of one Team Project cannot see information of other Team Projects.

If you create a single Team Project ad then create Team A and Team B, with the default option you will have two sub areas called TeamProject\Team A and TeamProject\Team B, and two security groups, one for each team. The problem is: is you put John in Team A and Jane in Team B both of them can see Work Items belonging to both teams.

This happens because once you are added in a Team Project, you are usually added also to a security group of the corresponding team, that in turn belongs to a special group called Team Project contributors, that in turn can see all Work Items and work with code etc etc.

Lets recap: this is the dialog you got when you are creating a new team.

image

Figure 1: Interface of new Team Creation

Two are the important points in Figure 1, the first is that the security behind that group is [Team Project Name]\Contributors, the second is that a new area path with the name of the team will be created. After you press create, a new security group with the name of the team will be created, and that group will be part of [Team Project Name]\Contributors default group. This imply that each person that is added to Team A will be alos part of Contributors, a special group that has access to all Work Items, Code and other resources in the project.

This is the default behavior, you can remove group in (1), but if you already created the team, this is the situation you got.

Now you need to solve your original problem: member of Team A should see only Work Items of Team A and members of Team B should see only Work Item of Team B. An obvious solution is to change security of corresponding area. Just go to project administration page where you configure areas as shown in Figure 2.

image

Figure 2: Administration of Area for security of Team A,

This shows actual permission for Work Items in area of Team A, as you can see from Figure 3 Contributors group can edit everything. From that figure you can see (3) that you have also an option that allows this area to inherit all permissions from parent areas.

image

Figure 3: Contributors permission for Work Item of area belonging to Team A.

First step is to remove inheritance and remove contributors from permission list as shown in Figure 4. To remove the group you can simply press the trash bin icon.

image

Figure 4: Remove permissions for Contributors Group and disable inheritance for the area.

Now only administrators, readers and Build administrators can access Work Item, and it is time to add corresponding team to current area as shown in Figure 5.

image

Figure 5: Just start typing in search textbox to find the team corresponding to current area. PAY ATTENTION to choose the group that belongs to the right Team Project because you could have multiple Team A in different Team Projects

Since you are configuring Team A area, select corresponding team called Team A (pay attention at team project name if you have more team called Team A in different Team Project). Now you should give permission to see and edit Work Items in that area as shown in Figure 6.

image

Figure 6: Give all permission to Team A to access work item in area Team A

Now people that are only in Team B, cannot access Work Item that are in area Team A, they cannot even find Work Item with a query. If you want to explicitly check permission level of another team, just search Team B in the same UI and check effective permission. As you can see in Figure 7 Team B has no permission in this area.

image

Figure 7: Permission of Team B

It is important that permission are “not set”  and not deny because a deny wins over all other settings.

Now you should repeat this configuration for each area and for each team. To recap

1) Choose settings for the corresponding area
2) Remove contributors
3) Stop inheritance
4) add the corresponding team group and give it permission

Enjoy.

Gian Maria.

Publish artifacts in GitHub actions

GitHub action is perfect to automate simple build workflow and can also be used to publish “releases” of our software. While we can do actions to publish on cloud or elsewhere, what I appreciate from a tool is: allow me to make simple things with simple workflow.

While I appreciate being able to obtain complex result and indeed, sometimes we evaluate products on the ability to fulfill complex scenario, often we forgot about the simple things. Is it true that, if a product allows me to solve complex scenarios, it will surely allow me to solve simple scenario, but I wonder about the complexity.

To automate a complex build and release workflow, currently I’d prefer Azure DevOps pipelines, but if I have a simple tool or library opensource on GitHub, quickly creating an action is the simplest way to go.

GitHub actions is still in its infancy and while it probably lack the ability to orchestrate complex workflows, it makes extremely simple to publish something, especially if the source uses command line tooling lile .NET core.

Here it is a small piece of GH action where I publish two distinct .NET core projects and then upload as artifact attachment to action run result.

    - name: dotnet publish server
      run: dotnet publish src/StupidFirewallManager/StupidFirewallManager.csproj --configuration release

    - name: dotnet publish client
      run: dotnet publish src/StupidFirewallManager.Client/StupidFirewallManager.Client.csproj --configuration release

    - uses: actions/upload-artifact@v1
      with:
        name: Publish server
        path: src/StupidFirewallManager/bin/release/netcoreapp3.1/publish

    - uses: actions/upload-artifact@v1
      with:
        name: Publish client
        path: src/StupidFirewallManager.Client/bin/release/netcoreapp3.1/publish

As you can see I can use dotnet publish commanline to simple publish software written in .NET core, then using actions/upload-artifact@v1 I can publish artifact to the action result.

SNAGHTML4b1e49

Figure 1: Artifacts attached to execution actions, simply downloadable from the UI.

With a simple task I can simply upload folders with build/publish result as execution artifacts, and I can simply download the result from the web interface. Artifacts are downloadable also from action run summary page.

image

Figure 2: Artifacts of the build in the summary page of action run.

Few lines of YAML, push on GH and you have each build to allow download of artifacts. Simple thing made simple.

Gian Maria

Home Made Zero trust Security step 2

If you read my old post about how to create a simple program that can manage Windows Firewall to open ports with a simple udp request you surely got disappointed by the complete lack of security in the request. That program was no more than a mere proof of concept to understand if I can manage windows firewall programmatically in .NET Core.

The absolute critical problem in that program is that, UDP request to open a Tcp port is sent in clear text.

Basically the protocol is, a client C send to the server S a UDP packet in a specific port with a secret key, the server S check if the secret is correct and opens a corresponding TCP port, associated by UDP port in configuration, for requesting IP only and for a predetermined period of time.

You can easily spot the problem: the UDP packet was sent in clear text, everyone that intercept the communication will be able to open port because the secret is sent in clear text.

We have obvious solution to the problem, the most simple one is using the shared secret password to derive a symmetric cryptographic key to encrypt the message. This is far from being perfect, but it is a further step towards a more secure solution.

Since reusing the very same cryptographic key multiple time is not encouraged (even if using a different Initialization Vector solves the problem), a special class called PassdowrdDeriveBytes can be used to derive a sequence of bytes from a password, using a salt and it is cryptographically secure.

public static ICryptoTransform GetEncryptorFromPassword(
    this Aes aes,
    string password,
    byte[] salt)
{
    using (var pdb = new PasswordDeriveBytes(password, salt))
    {
        var key = pdb.GetBytes(32);
        var IV = pdb.GetBytes(16);
        return aes.CreateEncryptor(key, IV);
    }
}

The salt is a sequence of bytes to be used only once, to avoid generating the very same key each time you sent a message. You can use another approach, where you use the very same key and each time you change the Initialization vector, but using the salt to generate a unique Key and IV is probably a better method.

Given this brief introduction we can create a function to generate a random salt to be used for each message.

public static byte[] GenerateRandomSalt()
{
    using (var csp = new RNGCryptoServiceProvider())
    {
        byte[] salt = new byte[saltSize];
        csp.GetBytes(salt);
        return salt;
    }
}

Even for this simple method, it is important to use a random number generator that is cryptographically secure, such as RNGCryptoServiceProvider.  Armed with these two functions we can create a method to encrypt a generic stream of bytes.

public static Byte[] SimmetricEncrypt(string password, byte[] salt, byte[] data)
{
    using (var aes = Aes.Create())
    using (var encryptor = aes.GetEncryptorFromPassword(password, salt))
    using (MemoryStream msEncrypt = new MemoryStream())
    {
        using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
        {
            csEncrypt.Write(data, 0, data.Length);
        }

        // important, dispose CryptoStream before accessing the array
        return msEncrypt.ToArray();
    }
}

As you can see the shared password and the salt are needed and clearly the sequence of byte to encrypt. Encrypted message can be decrypted by a corresponding method that basically accepts the very same set of parameters.

public static Byte[] SimmetricDecrypt(string password, byte[] salt, byte[] data)
{
    try
    {
        using (var aes = Aes.Create())
        using (var encryptor = aes.GetDecryptorFromPassword(password, salt))
        using (MemoryStream msDecrypt = new MemoryStream())
        {
            using (MemoryStream msOriginalData = new MemoryStream(data))
            using (CryptoStream csDecrypt = new CryptoStream(msOriginalData, encryptor, CryptoStreamMode.Read))
            {
                csDecrypt.CopyTo(msDecrypt);
            }

            // important, dispose CryptoStream before accessing the array
            return msDecrypt.ToArray();
        }
    }
    catch (CryptographicException cex)
    {
        Log.Error(cex, "Error decrypting message");
        //Do not disclose anything to the caller.
        throw new SecurityException("Error in decrypting");
    }
}

Code is really simple to read, the only special care is I’ve intercepted each CryptographicException that the code can raise (such as bad password) and I rethrow a generic Security Exception with no any information. The aim is avoiding to give to the caller any possible clue on what went wrong.

Armed with these two simple functions, we can change communication protocol between client and server, using the shared key to encrypt the request message, so anyone that intercepts the message cannot understand what is contained inside.

To avoid reply attack, were an attacker simple retransmit the very same intercepted UDP packet, content of encrypted packet is a simple class that contains three properties

        /// <summary>
        /// This is the port we want to open
        /// </summary>
        public Int32 PortToOpen { get; private set; }

        /// <summary>
        /// This is the end of opening Date, remember that the
        /// server could leave the port opened for a lesser time
        /// if needed.
        /// </summary>
        public DateTime EndOpeningDate { get; private set; }

        /// <summary>
        /// Ip address to scope port opening to.
        /// </summary>
        public String IpAddress { get; private set; }

Now an attacker can reply an intercepted request, but the net result is to reapply the very same request, opening a port for a required IpAddress. Since the message is encrypted he/she cannot read what is inside the message, nor they can alter it.

This solution is more secure and starts to be almost production ready.

As usual the code is on GitHub (as today encryption is still on a feature branch) https://github.com/alkampfergit/StupidFirewallManager 

Gian Maria.