Creating a virtual network inside of Azure, you will be required to come up with your subnet and address ranges you want to have in that subnet. I cannot easily come up with all the address range I want to have in a subnet and so I came across subnet calculator. For networking people this stuff is very basic. They can just spit out IP address like popcorn popping out. But I can’t and hence I use subnet calculator. Play around and check for yourself if you are new to this.
Tuesday, November 28, 2017
Thursday, August 24, 2017
Setup Integrated Terminal in VS Code to use Anaconda Python command prompt
I recently discovered about Anaconda for doing Python development. Anaconda simplifies setting up data science development environment. It installs all the packages for Python, installs Python, installs R etc. It just works. I have tried developing on Python before and it was rough. Anaconda is great.
I like VS Code as an editor and I want to do Python development using it. VS Code has Integrated Terminal into it for launching Python scripts. You can have PowerShell or cmd.exe configured. I want to replace it with Anaconda command prompt which is nothing but cmd.exe with some arguments.
Inside VS Code, open user settings page and navigate to Integrated Terminal section
Click on Replace in Settings and User Settings window will open up. There you will add cmd.exe and arguments settings for Anaconda command prompt.
"terminal.integrated.shell.windows": "C:\\Windows\\System32\\cmd.exe"
Regarding arguments. Well how do we find the arguments for Anaconda command prompt. Right click on the command prompt for Anaconda icon and then click properties.
As shown in the screen shot above everything after cmd.exe is arguments. Take those and put it inside [] as shown below.
"terminal.integrated.shellArgs.windows": [
"/K","C:\\Users\\myusername\\AppData\\Local\\Continuum\\Anaconda3\\Scripts\\activate.bat C:\\Users\\myusername\\AppData\\Local\\Continuum\\Anaconda3"
],
VS Code also allows you to do debugging with Python, provided you install Python and Python for VS Code extensions. After you install you can start debugging your Python script. But hold on, if your python path doesn’t exist inside environment variable then VS Code will error out asking you to modify launch.json file and modify the pythonPath. Inside your user settings file. Add the following line regarding your Anaconda3 location where python.exe is located as shown below.
"python.pythonPath": "C:\\Users\\myusername\\AppData\\Local\\Continuum\\Anaconda3"
After doing this you will be able to do debugging with VS Code with Python using Anaconda. If you are getting started with Python then I highly recommend using Anaconda for your environment setup. Enjoy!
Thursday, December 15, 2016
Easily add authorization rules to your Azure App
In the last post we saw how you can configure Authentication for your Azure App using Google. You can configure Authentication using other providers too like Facebook, Twitter or Microsoft Azure Active Directory. And the good thing is that you can do this without modifying your deployed application.
In this post I want to show you a new Azure App service feature called Authorization which you can easily configure by just adding authorization.json file to your application root directory. Let’s take a look at this authorization.json file. For my simple example I have created as follows:
{
"routes": [
{
"path_prefix": "/",
"policies": { "unauthenticated_action": "AllowAnonymous" }
},
{
"path_prefix": "/Admin",
"policies": { "unauthenticated_action": "RedirectToLoginPage" }
}
]
}
First you have a routes property which a collection of url authorization rules. There are different properties for each rule. In the above example, the first rule has path_prefix property set as ‘/’ and policy set as “unauthenticated_action” to “AllowAnoymous”. This means when I visit the home page allow anonymous access. But here is a caveat, this is only going to work if you have “Action to take when request is not authenticated” option set in the azure portal to “Allow Anonymous requests (no action)”. It was a bit confusing to me because I had this option set to “Login with Google” and it would not allow anonymous access with .json file. Check out my screenshot of my settings.
The next authorization rule in the above json says that when I navigate to /Admin page then redirect me to Login page and in my example it will be navigated to Google’s login page.
The basic schema of this .json file is as follows as shown in this msdn article.
{
"routes": [
{
"http_methods": [ "GET", "POST", "PUT", ... ],
"path_prefix": "/some/url/prefix",
"policies": {
"unauthenticated_action": "AllowAnonymous|RedirectToLoginPage|RejectWith401|RejectWith404"
}
},
...
]
}
You might be interested in knowing what does “http_methods” property does. It says that if a request is “GET” or “PUT” or “POST” then only this rule will be taken into effect for this url. If you want to restrict access to a particular page only if it is accessed via a “GET” request then you can just specifiy “GET”.
In path prefix you can have wildcards too which is very important if the url can have variable segments. For example, /product/1/edit then you can have path_prefix as /product/*/edit. For simple web applications this feature works great and I like how turn key solution this is.
Once again for this feature to work the authorization.json file has to be at the root of the application folder.
Tuesday, November 29, 2016
Troubleshooting TF14098 permission denied while deleting a branch
Recently I encountered the error TF14098: Access Denied: User DOMAIN\user needs Checkin permission(s) for $/teamproject/folder/* while delete a TFS branch. In this post, I want to share experience troubleshooting this issue. I am using TFS 2015 that is hosted on permises with latest update. I am also a TFS admin with project collection administrator rights.
When I first saw this error, I was felt that I knew why this happened. We had two branches DEV and TEST. TEST was branched from DEV. DEV had folder called Binaries and in it there was a particular .dll which had explicit DENY checkin permissions set for [Project]\Contributors, [Project]Project Administrators, [Collection]\Project Collection Administrators. I thought that since TEST was branched from DEV all those permissions would have been in effect in TEST. I right clicked on the TEST/Binaries/our.dll from within TFS source control explorer, then click on Advanced and then on Security.
After that I made sure that those three permission were set to Allow and nothing was deny. I was confident that this would work but it did not worked. Again the same error. Access Denied.
Next I opened visual studio developer command prompt in administrator mode and then navigated to the actual workspace folder locally and then ran the command tf permission or tf vc permission as follows:
>tf vc permission $/project/test /recursive | clip
This will copy all the permissions on files in your workspace recursively and copy it to your clipboard which you then can paste inside notepad and do search on deny. I found the Groups that had Deny permission set for that particular file. I double checked that file’s permission inside TFS source control explorer thinking something might have gone wrong. I tried deleting the branch again. Same error. Then I deleted just that file to get rid of the permission error. This time I was super confident that this would fix the issue since there is no file locally or on the server. I tried again. Same error. Then I read that in this msdn forum that permissions can even exists on a path even if no file exists on the server. Which makes sense if you think about it that on the server path could still exists even if there are no file in a branch since a branch only has pointers to the contents in it. I used the following command to set allow on that file as follows:
>tf vc permission $/project/test/binaries/our.dll /allow:* /group:”[Project]\Contributors”,”[Project]\Project Administrators”
I tried deleting the branch again inside visual studio and then tried checking in again and finally it worked this time. I hope this helps.
Thursday, November 24, 2016
Adding Google authentication to Azure App Service web app
In this post, I want to show you how quickly you can enable Authentication using Google to web app hosted in azure app service. You can configure other authentication providers also if you wish. The documentation for this feature can be found here.
First of all create a blank asp.net web app and publish it to azure. It can be any web application. For demonstration purposes I have created a .net core web app and hosted on Azure App Service. Open the App Services blade and open your website blade then click on settings. Under settings you will see Authentication and Authorization option. Turn on authentication feature as shown below.
After you turn on authentication, for “Action to take when request is not authenticate” select “Log in with Google”
You can see different authentication providers in the list above. Click on Google. On the next screen it will ask you Google Authentication Settings i.e. a Client ID and Client Secret.
Let’s head over to developer.console.google.com. You should on the dashboard page and click on Enable API. Then Click on the Google+ API to enable that api. Your screen should have Google+ API like the screenshot below.
After you have enabled Google+API, go the Credentails page and Click on Credentials button and click on OAuth Client ID.
On Create Client ID page, select Web application.
As soon as you click on Create you will be asked to provide following information. Let’s go over these in detail.
1. Name (provide any name you wish, I used the name of the web app)
2. Under Restrictions – Authorized JavaScript origins, you have to provide different urls that you want to be protected so when someone hits that url they will be presented with Google’s login dialog. You cannot provide wildcards in the url. My url is http://[webappname].azurewebsites.net
3. Under Restrictions – Authorized redirect URIs, you have to provide a redirect url. What is a redirect url? So after you are successfully authenticated Google doesn’t know where it should redirect you, so you will have to provide a redirect url for your website. Now you cannot provide any url. It has to be https://[webappname].azurewebsite.net/.auth/login/google/callback.
After you save you will be provided with a Client ID and Client Secret. Copy them and paste them in the Azure Portal and save.
Navigate to your website and you will be provided with Google login option. After your are successfully logged in, you will be redirect to your website’s home page. I think it is very easy to setup but real world apps need more than just one size fits all approach. For example, what if I wanted anonymous access to home page but authenticated access to the entire application.
You might have questions like,”How do I prevent anybody with a Google account from accessing my app?” Then that piece is upon you to configure in your application. “How do I know the email of the user and which login provider they used?” These are provided to you as HTTP header attributes as follows:
X-MS-CLIENT-PRINCIPAL-NAME : youremail@gmail.com
X-MS-CLIENT-PRINCIPAL-IDP: google
In Asp.Net Core you can access them as follows
public IActionResult Index()
{
var user = Request.Headers["X-MS-CLIENT-PRINCIPAL-NAME"].ToString();
if (user == "youremail@gmail.com")
{
return View("Index"); //Authorized View
}
else
{
return View("Error"); //UnAuthorized View
}
}
If you want to see more information returned from Google you can access your sites but typing the following url
https://[webappname].azurewebsites.net/.auth/me
This will return a json object with all the information.
Inside Asp.Net 4.6 application you can access this information via Claims already populated.
Friday, November 18, 2016
How to read Google SpreadSheet using Sheets API v4, .Net and a Service Account
In this post, I want to show how to read google spreadsheet data using google sheets v4 apis in .net via a service account. First of all you need an active google account and then next head to google developer console and create a project. I created a project called My Project. Next on the dashboard screen click on Enable API.
On the following screen click on Google Sheets API link and Sheets API will be Enabled. Next go to Credentials page and then Click on Create Credentials.
Click on the third option Service account key to create a service account.
On the Create service account key click on New Service Account. Provide a service account name, select a role for your project. I am choosing owner here. Select Key type to be JSON. Finally click on create and the file will be downloaded on your machine. Know where this file is downloaded we will need this in a later step.
On the credentials page, under service account keys you will be able to see the account you created in earlier step.
Create a spreadsheet called Employees with one row and two columns and keep a note of the spreadsheet ID.
The spreadsheetId can be found from the url of the google spreadsheet as shown below. In the url below the id in the {} bracket. Keep a note of this spreadsheet id we will need this in a later step.
https://docs.google.com/spreadsheets/d/{your-spreadsheet-id}/edit#gid=0
Finally all setup is done. Lets head over to Visual Studio and create a new Console Project. Install nuget package Google.Sheets.Api.v4 from the nuget package manager. Next create three .cs classes and paste the following code as shown below. Fix all the references.
1. GoogleService.cs. This class is responsible for creating a sheetsservice using googlecredential.
public class GoogleService
{
private readonly string _googleSecretJsonFilePath;
private readonly string _applicationName;
private readonly string[] _scopes;
public GoogleService(string googleSecretJsonFilePath, string applicationName, string[] scopes)
{
_googleSecretJsonFilePath = googleSecretJsonFilePath;
_applicationName = applicationName;
_scopes = scopes;
}
public GoogleCredential GetGoogleCredential()
{
GoogleCredential credential;
using (var stream =
new FileStream(_googleSecretJsonFilePath, FileMode.Open, FileAccess.Read))
{
credential = GoogleCredential.FromStream(stream).CreateScoped(_scopes);
}
return credential;
}
public SheetsService GetSheetsService()
{
var credential = GetGoogleCredential();
var sheetsService = new SheetsService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = _applicationName,
});
return sheetsService;
}
}
2. SpreadSheet.cs. I created a spreadsheet class to store values that we read from the spreadsheet. There is a headerrow and there is rows. Each spreadsheetrow can have multiple rows. For demo purposes I created 2 columns. We need only two
public class SpreadSheet
{
public SpreadSheetRow HeaderRow { get; set; }
public List<SpreadSheetRow> Rows { get; set; }
}
public class SpreadSheetRow
{
private readonly IList<Object> _values;
public SpreadSheetRow(IList<Object> values)
{
_values = values;
}
public string Value0 => _getValue(0);
public string Value1 => _getValue(1);
private string _getValue(int columnIndex)
{
try
{
var s = _values[columnIndex].ToString();
return s;
}
catch (Exception ex)
{
return String.Empty;
}
}
}
3. GoogleSpreadSheetReader.cs. This class relies on GoogleService class from step1. The GetSpreadSheet method accepts parameter spreadSheetId and a range parameter. I have a spreadsheet in which the first row was header row. If you wanted to read all the rows then you will have to modify this method.
public class GoogleSpreadSheetReader
{
private readonly SheetsService _sheetService;
public GoogleSpreadSheetReader(GoogleService googleService)
{
_sheetService = googleService.GetSheetsService();
}
public SpreadSheet GetSpreadSheet(string spreadSheetId,string range)
{
SpreadsheetsResource.ValuesResource.GetRequest request = _sheetService.Spreadsheets.Values.Get(spreadSheetId, range);
ValueRange response = request.Execute();
IList<IList<Object>> values = response.Values;
var rows = new List<SpreadSheetRow>();
for (int i = 1; i < values.Count; i++)
{
var row = new SpreadSheetRow(values[i]);
rows.Add(row);
}
var headerRow = new SpreadSheetRow(values[0]);
var spreadSheet = new SpreadSheet();
spreadSheet.HeaderRow = headerRow;
spreadSheet.Rows = new List<SpreadSheetRow>();
spreadSheet.Rows.AddRange(rows);
return spreadSheet;
}
}
4. Remember the JSON file we downloaded from Google put that file inside a folder called GoogleSecret inside your solution as shown below. Right click on the the file and hit F4 to view properties and change Copy to Output Directory to Copy Always.
5. Putting it all together inside Program.cs together to finally read data from Google SpreadSheet.
class Program
{
static void Main(string[] args)
{
Console.WriteLine(System.AppDomain.CurrentDomain.BaseDirectory.ToString());
var googleSecretJsonFilePath = $"{System.AppDomain.CurrentDomain.BaseDirectory}\\GoogleSecret\\GoogleSecret.json";
var applicationName = "My Project";
string[] scopes = { SheetsService.Scope.SpreadsheetsReadonly };
var googleService = new GoogleService(googleSecretJsonFilePath, applicationName, scopes);
var spreadSheetId = "your-spreadsheet-id";
var range = "A:B";
var reader = new GoogleSpreadSheetReader(googleService);
var spreadSheet = reader.GetSpreadSheet(spreadSheetId, range);
Console.WriteLine(JsonConvert.SerializeObject(spreadSheet.Rows));
Console.Read();
}
}
Explanation of the above code. First we get hold of the JSON file path from the Bin directory then provide the name of your application, I called mine “My Project”. Using scopes, we mention what level of access we have eg. SpreadsheetsReadonly. We create a new instance of GoogleService then pass googleservice into GoogleSpreadSheetReader. In the Employees spreadsheet we are using only two columns so we provide a range as A : B. The range option is very interesting and you can get crazy with these ranges. Finally you get a spreadsheet by calling reader.GetSpreadSheet(spreadSheetId, range); Run the application by pressing F5 and you will see the output as JSON string.
If you have any questions then please let me know in the comments below.
Monday, November 7, 2016
Compare TFS 2015 Build definition changes
Today I discovered a feature that I felt was quite useful. I always wanted to know what changes were made to build definition. If someone made a change to build defnition then you would want to know what changed. If you are using TFS 2015 or on Visual Studio Team Services then go to Build> Right click on Build definition and click on edit build definition. Under History, click on a build definition to see the diff button highlighted.
Once you click on that, you will see all the changes that were made to this build definition from the last time it was changed. Enjoy.