Thursday, 12 January 2017

Continuous Code Quality with .NET, Sonarqube and Docker

Coming back to the devops world, we have realised that there is a platform is becoming very successful in the Java stack, called Sonarqube. Luckly for .NET developers, Microsoft have decided to lend some of the Microsoft developers to improve the C# side of Sonarqube.

Sonarqube is a product based in a MySql database and a set of rules. This product is free, so if you are a dev I will reconsider to install it in your machine. You will learn good practices, and will have a second opinion of your code. On the top of this, you can develop propel productive code.

We have seen few articles about setting up Sonarqube in Windows for C# but to be honest, we have decided to follow our own way, so instead of installing an Apache server + MySql and all the programs needed, we will be creating an instance of a Docker Sonarqube image. What are the advantages? well, we can spin our own machine whenever we want, and have a configured instance we can carry with us.

So how are we going to do it? To have a different approach than my previous article, we are going to use Kitematic , it is some kind of nice UI for Docker. We assume you have installed Docker for Windows already, so no download Kitematic and install it.

Skip the login and open the program. Go to search and type sonarqube. A list of images should come up, select the official one (the first one)

image

Click in create. It will create an instance of SonarQube, and it will give you an address to access to SonarQube in this case is localhost:32769, bear in mind that SonarQube runs in port 9000 but 9000 in the Docker instance is binded to your local 32769:

image

If the last line looks like this, that means you have SonarQube running

image

Now you can go to your browser and type http://localhost:32769, click in Login and enter as user admin and password admin

image

Now let’s go to create a small windows forms project called MyProject1. We will save it on C:\work\MyProject1\MyProject1\ . The folder content will look like this

image

Time to install the client, Sonar Scanner, which will send our project to SonarQube (it will take one min). Download and unzip the SonarQube Scanner (let's say in "C:\sonar-scanner"). Go “"to “This PC in Windows 10->Right click->Properties” and add in the Environmental Variables area a new Path “C:\sonar-scaner”

image

Then we are going to tell Sonar Scanner where our project lives, so it can analysed it. Open a file called sonar-scanner.properties which lives on C:\sonar-scanner\conf

Edit the file, and add few lines (see below) should look like this after adding the lines:

#Configure here general information about the environment, such as SonarQube DB details for example
#No information about specific project should appear here

#----- Default SonarQube server
#sonar.host.url=
http://localhost:9000

#----- Default source code encoding
#sonar.sourceEncoding=UTF-8

#----- Global database settings (not used for SonarQube 5.2+)
#sonar.jdbc.username=sonar
#sonar.jdbc.password=sonar

#----- PostgreSQL
#sonar.jdbc.url=jdbc:postgresql://localhost/sonar

#----- MySQL
#sonar.jdbc.url=jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8

#----- Oracle
#sonar.jdbc.url=jdbc:oracle:thin:@localhost/XE

#----- Microsoft SQLServer
#sonar.jdbc.url=jdbc:jtds:sqlserver://localhost/sonar;SelectMethod=Cursor

PROJECT_HOME = C:\work\MyProject1\MyProject1\
#sonar.sourceEncoding=UTF-8
sonar.host.url=http://localhost:327689

sonar.sourceEncoding=UTF-8
sonar.cobol.copy.directories=/copy
sonar.visualstudio.enable=true

sonar.projectKey=MyProject1
sonar.projectName=MyProject1
sonar.projectVersion=1.0
sonar.sources=.
sonar.language=cs
sonar.dotnet.visualstudio.solution.file=MyProject1.sln
sonar.dotnet.excludeGeneratedCode=true
sonar.dotnet.4.0.sdk.directory=C:/Windows/Microsoft.NET/Framework/v4.0.30319
sonar.dotnet.version=4.5.2

Save the file and open CMD with “Run as Administrator”, then navigate to your project folder C:\work\MyProject1\MyProject1\ and type sonar-scanner

image

And you should get something like this

image

Let’s go to check the project, go to http://localhost:32769 and navigate to “Projects->explore projects->Click in MyProject1” you should get a screen like this (I have added a condition for the comments, so it fails):
image

Wednesday, 11 January 2017

Publishing a ASP.NET MVC Site or WebApi to a Docker Machine locally in Windows on Windows Server.

It happens sometimes you will want to develop a single project application. One of those, proof of concepts you do to learn new stuff. The problem comes when you have to stop doing Micky Mouse applications and move to a different world where environments and continuous integration becomes the core of the development.

This is where a new position has risen to help the devs, they are called the DevOps. The issue with DevOps, it is sometimes they have too much work to to, so they can be solving your own problems. Especially if you are doing continuous integration in Azure or Amazon AWS.

This is where Docker becomes a big player, we have a tool it is sophisticated enough to do the job, and it is simple enough to be used by devs. Docker comes from the Java and Linux world, so I thought it will be interesting to try to create a Docker image to run .NET stuff.

So step by step…. the first step will be to create a MVC or WebApi application, ASP.NET 4 or ASP.NET Core whatever you prefer.

image

Step 2: Right click in your project (in my case web) –> Publish…

Step 3: Click on custom and enter DockerDeployment and click OK

image

 

Step 4: In the Publish method with the drop down list select File System and in target location, select c:/docker

image

 

Step 5: Click Next->select release->select Publish

image

 

Step 6: It is time to play with Docker. Install Docker (the beta version) https://docs.docker.com/docker-for-windows/ 
and right click on the task bar, then select “Switch to Windows containers…”

image

 

Step 7: Create a file called “Dockerfile” in c:\docker and paste this (see below). This code will get the code from your deployment and will put it in the image microsoft/aspnet copying the data to the root folder

FROM microsoft/aspnet

WORKDIR /inetpub/wwwroot
COPY .  /inetpub/wwwroot

Step 8: Open powershell with admin permissions, and go to the C:\docker folder and execute this command:
image

This will execute the Dockerfile script and will create a new instance

 

Step 9: It is time to run your instance, just type:

image

 

Step 10: You can list the images by doing a Docker ps . Get the first 3 digits of the CONTAINER ID, in this case 989

image

 

Step 11: It is time to know your URL. just type the following and you will get the URL of your docker machine
docker inspect -f "{{ .NetworkSettings.Networks.nat.IPAddress }}" 989

image

 

Step 12: If you want to access to your local machine you can do things like this (where 989 is the Container Id)

Access to MS-DOS: docker exec -i –t 989 cmd

image

To Create a new Site, use this DockerFile (we called the web Webgenerator):
FROM microsoft/aspnet
SHELL ["powershell"]

RUN Install-WindowsFeature NET-Framework-45-ASPNET ; \  
    Install-WindowsFeature Web-Asp-Net45

COPY WebGenerator WebGenerator 
RUN Remove-WebSite -Name 'Default Web Site'  
RUN New-Website -Name 'WebGenerator' -Port 80 \  
    -PhysicalPath 'c:\WebGenerator' -ApplicationPool '.NET v4.5'
EXPOSE 80

CMD ["ping", "-t", "localhost"]  

Saturday, 7 March 2015

Azure AD Cloud silent Authentication with ADAL and TokenCache encryption

The ADAL library was launched a couple of years ago, luckily people from Microsoft like Vittorio Bertocci, have been working hard to have a library capable of doing authentication between native applications, web applications and web services (Web API). ADAL.js is in beta, it is a full working library but there are some issues need to be solved before we can have a robust library (This is when I am writing my article so March 2015) but Vittorio promised me we will have something working in this side by April 2015.
Unfortunately for me, and due to a project we are releasing before April, there is not choice, so I will have to write a wrapper around my Azure Web Api’s and skip Adal.js until we have v1.0. So you will be asking yourself “what is this guy talking about?”.
Ok, let’s go to start from a "simple" scenario, so you can have an  idea of what I am talking about. I have a Web Application (MVC 5) which is talking with few web services (Web API 2’s). All of them are register in Azure AD, so Azure AD acts as a Black Box, and manage the authentication. In this case Azure AD will take care of the MVC Web Application and the Web API’s Authentication.
So where is the problem? Well if I want to be sure that the Web Application and the Web APis share the same authentication, I will have to use refresh tokens, but because the hard work done by Vittorio’s team, now we can use Silent Tokens, so we don’t have to worry about building a whole system to refresh the tokens, but the only place where we need to worry it is about about where to store the Tokens.
It is quite common to store the tokens in Sessions, but there is a small problem with this, you lose the multi-farm factor plus WebApi’s don’t have sessions, so when you have to talk to them becomes an impossible job.
So what is the solution? store the tokens in a persistent area. If we have a native application we could store the token’s in the file system, but if we have a Web Application we could store them in Blob Storage or Databases.
Let’s go to a scenario, when someone, which is not really a user, and it is trying to get our token to access to our farm or MVC application, manage to access to the database or file system. Well, I think we will be in big trouble here. That person will have at least 20 minutes (Time when our token expires) to hack our system.
So… let’s go to make the things more difficult for this person, let’s go to inject encryption in the tokens, with double key encryption, String and Byte Array.
The following example it is a simple call from a MVC Application to a Web API 2 using silent Authentication.
...//## GETTING THE TOKEN TO BE AUTHORISE string userObjectID = ClaimsPrincipal.Current.FindFirst(userSchema).Value; AuthenticationContext authContext = new AuthenticationContext(Startup.Authority, new TokenEncryptedDatabaseCache(userObjectID, "Iamakey"); ClientCredential credential = new ClientCredential(clientId, appKey); AuthenticationResult result = authContext.AcquireTokenSilent(resourceId, credential, new UserIdentifier(userObjectID, UserIdentifierType.UniqueId));string authnHeader = "Authorization: Bearer " + result.AccessToken; ...


Now… check the parameter we are passing on  AcquireTokenSilent , it is a TokenCache.

This is the model we use to store the data in the database:


public class PerUserWebCache { [Key] public int EntryId { get; set; } public string WebUserUniqueId { get; set; } public byte[] CacheBits { get; set; } public DateTime LastWrite { get; set; } }
And finally this is the beauty! TokenEncryptedDatabaseCache, which encapsulates the encryption. You will need to create a dbcontext to store the model with the data…which I am going to add as well, so you can save some time.

using System;using System.Collections.Generic;using System.Data.Entity;using System.Linq;using System.Web;using System.Web.Caching;using Microsoft.IdentityModel.Clients.ActiveDirectory;using System.Security.Cryptography;using System.IO; public class TokenEncryptedDatabaseCache : TokenCache { private TokenCacheDataContext db = new TokenCacheDataContext(); string User; private PerUserWebCache Cache; private string Key; /// <summary> /// Contsructor for the TokenEncryptedDatabaseCache class /// </summary> /// <param name="user">Current User</param> /// <param name="key">Key for the encription</param> public TokenEncryptedDatabaseCache(string user, string key) { Key = key; User = user; this.AfterAccess = AfterAccessNotification; this.BeforeAccess = BeforeAccessNotification; this.BeforeWrite = BeforeWriteNotification; //## We check if the user is in our database Cache = db.PerUserCacheList.FirstOrDefault(c => c.WebUserUniqueId == User); //## If that is the case we keep it in memory //## We decrypt the token this.Deserialize((Cache == null) ? null : Cache.CacheBits!=null?Decrypt(Cache.CacheBits):null); } /// <summary> /// Method to clean the database /// </summary> public override void Clear() { base.Clear(); foreach (var cacheEntry in db.PerUserCacheList) db.PerUserCacheList.Remove(cacheEntry); db.SaveChanges(); } /// <summary> /// ADAL raise a notification before acces to the cache. /// Notification raised before ADAL accesses the cache. /// This is your chance to update the in-memory copy from the DB, /// if the in-memory version is stale. The token is decrypted. /// </summary> /// <param name="args"></param> void BeforeAccessNotification(TokenCacheNotificationArgs args) { if (Cache == null) { // first time access Cache = db.PerUserCacheList.FirstOrDefault(c => c.WebUserUniqueId == User); } else { // retrieve last write from the DB var status = from e in db.PerUserCacheList where (e.WebUserUniqueId == User) select new { LastWrite = e.LastWrite }; // if the in-memory copy is older than the persistent copy if (status.First().LastWrite > Cache.LastWrite) //// read from from storage, update in-memory copy { Cache = db.PerUserCacheList.FirstOrDefault(c => c.WebUserUniqueId == User); } } this.Deserialize((Cache == null) ? null : Cache.CacheBits!=null?Decrypt(Cache.CacheBits):null); } /// <summary> ///Notification raised after ADAL accessed the cache. ///If the HasStateChanged flag is set, ADAL changed the content of the cache, ///At this time we encrypt the token and save it. /// </summary> /// <param name="args"></param> void AfterAccessNotification(TokenCacheNotificationArgs args) { // if state changed if (this.HasStateChanged) { Cache = new PerUserWebCache { WebUserUniqueId = User, CacheBits = Encrypt(this.Serialize()), LastWrite = DateTime.Now }; //// update the DB and the lastwrite db.Entry(Cache).State = Cache.EntryId == 0 ? EntityState.Added : EntityState.Modified; db.SaveChanges(); this.HasStateChanged = false; } } void BeforeWriteNotification(TokenCacheNotificationArgs args) { // if you want to ensure that no concurrent write take place, use this notification to place a lock on the entry } /// <summary> /// Encription of the token. /// </summary> /// <param name="DataToEncrypt">Data to be encrypted</param> /// <returns>Data encrypted.</returns> private byte[] Encrypt(byte[] DataToEncrypt) { PasswordDeriveBytes passwordDeriveBytes = new PasswordDeriveBytes(Key, new byte[] { 0x43, 0x87, 0x23, 0x72 }); MemoryStream memoryStream = new MemoryStream(); Aes aes = new AesManaged(); aes.Key = passwordDeriveBytes.GetBytes(aes.KeySize / 8); aes.IV = passwordDeriveBytes.GetBytes(aes.BlockSize / 8); CryptoStream cryptoStream = new CryptoStream(memoryStream,aes.CreateEncryptor(), CryptoStreamMode.Write); cryptoStream.Write(DataToEncrypt, 0, DataToEncrypt.Length); cryptoStream.Close(); return memoryStream.ToArray(); } /// <summary> /// Decryption of the token. /// </summary> /// <param name="DataToDecrypt">Data to be decrypted</param> /// <returns>Data decrypted</returns> private byte[] Decrypt(byte[] DataToDecrypt) { PasswordDeriveBytes passwordDeriveBytes = new PasswordDeriveBytes(Key, new byte[] { 0x43, 0x87, 0x23, 0x72 }); MemoryStream memoryStream = new MemoryStream(); Aes aes = new AesManaged(); aes.Key = passwordDeriveBytes.GetBytes(aes.KeySize / 8); aes.IV = passwordDeriveBytes.GetBytes(aes.BlockSize / 8); CryptoStream cryptoStream = new CryptoStream(memoryStream, aes.CreateDecryptor(), CryptoStreamMode.Write); cryptoStream.Write(DataToDecrypt, 0, DataToDecrypt.Length); cryptoStream.Close(); return memoryStream.ToArray(); } }

This is the class where we have our DBContext


using System;using System.Collections.Generic;using System.ComponentModel.DataAnnotations;using System.Data.Entity;using System.Data.Entity.ModelConfiguration.Conventions;using System.Linq;using System.Text;using System.Threading.Tasks; public class TokenCacheDataContext : DbContext { public TokenCacheDataContext() : base("TokenCacheDataContext") { } public DbSet<PerUserWebCache> PerUserCacheList { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); } }


Initializer…

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks; public class TokenCacheInitializer : System.Data.Entity.DropCreateDatabaseIfModelChanges<TokenCacheDataContext> { }

Well, I hope you enjoy, any questions let me know.