How I Blog – Updated 2018

Over 8 years ago (wow that feels like a long time writing that) I was fairly new to blogging and wrote a post about “How I Blog”.  A coworker recently asked me about how I blogged so I quickly read through the old article and realized that much of the technology that I leverage has changed, but the process is fairly similar.  In light of that I’m writing an updated blog post to reflect the current technology and other changes since 8 years ago.

 

Tools

  • Open Live Writer – Windows Live Writer is no longer supported so I’ve switched over to the open source version which was released a few years ago.  Not everything is 100% the same but the UI and general authoring experience has remained.  I typically draft up posts in Open Live Writer, push the draft to WordPress, and then finalize on WordPress due to minor issues with formatting code and such.
  • Twitter – Live Writer had a nice plug-in called Twitter Notify that allowed you to link your Twitter account to Live Writer.  These days I have WordPress automatically tweet out new blog posts.  I use this (and RSS feed) as my primary method to notify others when I have new content posted.
  • OneDrive – OneDrive allows you to sync content across multiple computers and offers a couple GBs of free storage (specific number has gone up and down over the years).  I pay for an Office 365 Home subscription which includes 1TB of OneDrive storage so I shouldn’t run out of space anytime soon.  I really can’t say enough about how much time OneDrive saves me when it comes to blogging.  I use this to sync screenshots, Open Live Writer files (drafts and posts), and code snippets between my multiple devices.  As an added bonus I also get all these files backed up into the glorious “interwebs cloud” should I ever have an issue with my personal backups.
  • Paint.Net – Paint.Net is a free tool that gives you basic PhotoShop-like image editing.  I use this for cropping screenshots, pixelating images with sensitive information, and many other minor tasks.  I find the software very easy to use and it’s hard to beat free.  Please support the tool providers with a donation if you end up using and liking it.

Hosting/Online Services

  • WordPress – Originally I hosted with GeeksWithBlogs.net but after issues with the RSS feed I looked at a number of options including Orchard and WordPress.  Eventually I landed on hosted WordPress (self-hosting had its own issues).  You can read more about the transition process on this My Blog Has Moved post.  Overall I am much happier paying a small fee for WordPress to host my content, integrate my custom domain, and offer a number of native integrations.
  • WordPress Statistics – What good is blogging if you can’t track statistics like number of visitors or which of your posts are the most popular?  The “Personal” WordPress plan includes the pertinent statistics that I’m interested in and plenty of charts or filters to find the data.
  • RSS Feed – WordPress has native functionality to publish an RSS feed of posts.  This has removed the need to use FeedBurner or other 3rd party tools.  RSS feeds may not hold the same weight that they did years ago but personally that is how I consume a number of blogs and other services.  I welcome any input on alternatives for notifying “subscribers” that a new post is available or similar functionality.
  • GoDaddy – Since the beginning of my blog I have registered my briantjackett.com domain with GoDaddy.  There are numerous other options out there but I see no need to switch as things “just work.”

Tips for Starting Out

So, if you’ve read this far and you yourself don’t have a blog but are interested in starting one here are a few tips.

  • Know your content – What is it that you want to blog about?  Will your blog contains posts about cool robotics work that you are doing, video game reviews, or perhaps your super cute cat Mr. Mittens?  Decide on an area or related group of topics and focus on those.
  • Know your audience – Relating to the above, who are you writing your content for?  Are you writing posts for personal reference in the future (this is part of why I write), for internal company coworkers, or for the community at large.  This will shape what, how, and why you write.
  • Set goals – Define some goals for yourself about how often you plan to publish content, how many visitors/subscribers you are aiming for, or some other means of measuring how you are doing with your blogging.  As stated in my previous post I’ve set some blogging goals for myself and have done fairly well sticking to them. This not only helps motivate you to keep writing but also offers some level of consistency for your audience.  Nothing is worse than starting out great publishing 10 posts in one month and then going silent for a year, don’t be that person.
  • Write when it’s right – You like that play on words?  I bet you chuckled for brief second before shaking your head.  I have never been great at writing, literature, and all those book type things.  For me it’s very rare that I can sit down and just let my thoughts flow onto paper (or monitor/screen as it were.)  When I do get those moments of clarity I shut out distractions, turn on some music, and capitalize on the moment.  Don’t force your writing, but when a good idea comes to mind start to write it out or at least jot it down for future use.
  • Read other blogs – Seems obvious, but really go out there and start reading some blogs that interest you.  Perhaps they are written by coworkers, people you’ve met at user groups, or some super awesome person in your field of work that everyone talks about.  This can help you find your footing for style, content, and many other things.
  • Get feedback – This one is huge.  Find some trusted friends, coworkers, or even your family to read over your posts and give you feedback on what they like/dislike about your posts.  Just like giving a presentation to a practice audience, having others review and comment on your writing can be very helpful to making you a stronger writer.
  • Conclusion

    So there you have it, my current blogging tools, a little about my process, and some tips for starting out.  If you’d like to share anything about your own blogging experience or have some feedback of your own feel free to comment below.  Thanks to everyone who has been reading my blog over the past 8+ years now and giving me encouragement to keep writing.  I find it very fulfilling and hopefully you do as well.

     

    -Frog Out

How I Do A Personal Monthly Retrospective

In this post I’ll walk through the process that I’m currently using (going on 5 months in a row now) to do a personal retrospective.  Each month this shouldn’t take more than 10-20 minutes but the benefits have been tangible for me thus far.  I’ll describe the process next but provide some  additional context in the conclusion.

Guidelines

A few guidelines first.

  • Consistent day – Pick a set day of each month to do your retrospective (ex. 1st day of the month, 1st Saturday, 3rd Wed, whatever works best.)  For me the last Friday of the month is my day.
  • Remind yourself – Schedule a reminder, a recurring meeting invite, or some other way to track the day for your retrospective.  I use a recurring meeting scheduled in my work calendar.
  • Timing – Spend no more than 20 minutes on the retrospective.  This keeps things succinct and easy to  complete each month.

Monthly Retrospective Process

  1. What to record
    • What is going well?
    • What are blockers / is not going well?
    • What would you like to accomplish going forward? (To-Do)
    • Why are you here? (see section below, we’ll come back to this)
  2. Write simple phrases or sentences for anything relating to personal life, work, career, family, etc.  Nothing is off limits.

 

At the next month use the following process to review the previous month and then write for the new month.

  • Review last month’s “To-Dos” and mark if completed
  • If an item is in “what are blockers / not going well” for 2 months in a row but no improvement or action taken then make a To-Do for it
  • If an item is in “To-Do” for 2 months in a row but not worked on then drop it off as it is not a high enough priority for you
  • Review last month “what is / is not going well” and see if anything points to future goals or direction (Why are you here)

 

Why are you here?

The “Why are you here?” question takes a little bit of a different approach.  The goal here is to find long term direction in your life.  This could take many forms including “what motivates you the most?”, “what do you see yourself doing when you retire?”, or “if time and money were of no concern, what would you be doing?”  The way to start with this question is to ask yourself the question 5 times in row until you get to the same answer multiple times in a row.  This may not happen in the first few months or even years, but over time you should be able to sharpen your answers until you get closer to your true answer.

Example

(Month 1) Why are you here?

  1. I want to have a good job… why?
  2. I want to make good money… why?
  3. I want to provide for my family… why?
  4. I want to spend more time with the people that I love… why?
  5. I want to bring joy to others because it makes me feel fulfilled…

[Now that you’ve arrived at wanting to bring joy to others, start at that point and continue forward the next month]

(Month 2) Why are you here?

  1. I want to bring joy to other people because it makes me feel fulfilled… why?
  2. I’m good at making other people feel included and that is the best way that I can make other people happy… why?
  3. Someone once helped me to feel included and I realized that I had a natural ability to make others feel included and I feel compelled to help other people and pass along that gift… why?
  4. Someone once helped me to feel included and I realized that I had a natural ability to make others feel included and I feel compelled to help other people and pass along that gift… why?

 

Notice 2 things here.  1st is that we’ve repeated ourselves so we’re getting closer to a true answer.  2nd is that as you continue answering usually you start to add more details and clarity to your responses.  In this example we went from 7 words up to 34 words with much greater detail and intentionality.  These answers aren’t set in stone and you may find that things change over the months / years.  What once was important may be replaced by something else that takes on greater priority.  The important part is that you ask the question and be honest with your answers.

Conclusion

Earlier this year I was speaking with my mentor (if you don’t have at least 1 mentor I highly encourage you to find one as soon as possible, they don’t even have to work at the same company as you) trying to answer the question “Why am I here?”  The question was posed to me at a technical leadership training event that I had attended.  I didn’t have a very good answer for the near or long term in my life.  In order to find some direction I used the simple questions in the retrospective above (you may recognize some of these from an agile retrospective meeting).  The benefits from this process have been very real for me.  I’ve found things that I’ve not enjoyed doing in my life and stopped doing them or found ways to transition that work to others who do enjoy it.  Conversely I’ve also found things that I do enjoy in my life and worked to position myself to have more opportunities in those spaces.

If you try out this process I’d love to hear how it works for you, even a follow up after you’ve been through it a few months.  Good luck and keep searching until you find your Why.

 

-Frog Out

Start Using Visual Studio Live Share

Before getting into this post, do yourself a favor and download the extension for Visual Studio Live Share.  There is a version for Visual Studio 2017 (15.6 or higher, but recommend 15.7 which just released this week) or Visual Studio Code (1.22 or higher).

Background

Back in November 2017 the Visual Studio team announced a new feature called Live Share (blog post) that allows a team to collaborate on the same codebase using the same development tools, settings, or environment.  When I first heard about this I thought to myself “no thanks, I’m fine with screen-sharing through Skype / Sococo / Google Hangouts / etc. for real-time collaboration on code projects.”

A few weeks later I listened to Scott Hanselman’s Hanselminutes podcast on “Revolutionizing remote pair programming with Live Share” and realized what I was missing.  Screen sharing works when both users have a copy of the same codebase (re: checked-in to source control, shared permissions, etc.) but what happens when you want to collaborate with someone who doesn’t have access to the codebase?  Or the codebase is rather large to download?  Or the bandwidth needed to screen-share a 4k monitor display is causing poor performance on the screen-share session?  And on and on with limitations.

Problems Solved

Visual Studio Live Share solves a number of these issues:

  • Allows you to share with anyone simply by giving them a link
  • Files that are interacted with from the source projects are temporarily cached on the target machine in real-time (i.e. doesn’t download the entire project at start)
  • Doesn’t require the person sharing with to have the same extensions, developer tools, etc. installed
  • Allows real-time 2-way collaboration and debugging (the latter is a huge deal)
  • Reduces network bandwidth used by only sends minimal data like cursor position and typed characters (i.e. doesn’t push 1080p or 4k monitor worth of pixels across the network)
  • And much more…

Walkthrough

You can watch the videos the Live Share team has put together but I’m also sharing a couple quick screenshots from my testing with my peer Ken Kilty yesterday.  I’ll be showing Visual Studio 2017 but Visual Studio Code is also available.

Note: ensure that you follow the instructions for allowing Live Share to work through the firewall if you have one enabled on your device.

Open a project / folder.  Click the Share button in upper right corner.

VSLiveShare3

After sending the link to the person(s) you want to collaborate with they will see a screen similar to the following.  Clicking the link they can choose which application to launch.

VSLiveShare1

You can share with multiple people and even cross collaborate on different IDEs with one user using Visual Studio 2017 while the other is using Visual Studio Code.

VSLiveShare2

Conclusion

I’m still exploring the capabilities of Visual Studio Live Share such as “follow me”, shared terminal, remote debugging, shared servers, and more.  You can read up on the documentation as well.  Live Share is currently in preview but I already see a number of scenario where this will be extremely useful for working with peers, customers, and beyond.  Give it a try today and let me know in the comments if you have any feedback or questions.

 

-Frog Out

Calling Azure AD Secured Azure Function Externally From JavaScript

My customer recently had a need to securely call an HTTP trigger on an Azure Function remotely from an arbitrary client web application.  In this scenario securely meant ensuring that the user has logged into Azure Active Directory (AAD), but any number of authentication providers could be used.  The SharePoint Patterns and Practices (PnP) team had posted a video (SharePoint PnP Webcast – Calling external APIs securely from SharePoint Framework) that used the SharePoint Framework but my team needed to do this from vanilla JavaScript.  Many thanks to the PnP team and my peer Srinivas Varukala for their inspiration and code samples.

Overview

The key components to this solution involve the following:

  • Azure AD app registration (used to enforce authentication on Azure Function)
  • Azure Function configured to enforce Azure AD authentication
  • Client web application with JavaScript code to call the Azure Function

Azure Function

In the Azure Portal create a new Azure Function.  Choose an HTTP Trigger and use the language of choice (I’m using C# script in this example).  The Azure Function will validate if a claims principal exists on the incoming request and then output to the logs the name of the user if authenticated.

<Update 2018-05-02>

Note: the Azure portal currently does not support the headers required for CORS (cross-origin resource sharing) requests that contain credentials.  Feedback (source) has been provided to the Azure App Service team to support this but was declined.  As such the manual processing of CORS  requests is not supported at this time.  You will need to determine if this workaround works for you or not.

</Update 2018-05-02>

using System.Net;
using System.Security.Claims;
using System.Threading;
public static HttpResponseMessage Run(HttpRequestMessage req, TraceWriter log)
{
  log.Info("C# HTTP trigger function processed a request.");
// check for authenticated user on incoming request
  if (!ClaimsPrincipal.Current.Identity.IsAuthenticated)
  {
    log.Info("Claims: Not authenticated");
  }
  else
  {
    log.Info("Claims: Authenticated as " + ClaimsPrincipal.Current.Identity.Name);
  }

  var resp = req.CreateResponse(HttpStatusCode.OK, "Hello there " + ClaimsPrincipal.Current.Identity.Name);

  // manually process CORS request
  if (req.Headers.Contains("Origin"))
  {
    var origin = req.Headers.GetValues("origin").FirstOrDefault();
    resp.Headers.Add("Access-Control-Allow-Credentials", "true");
    resp.Headers.Add("Access-Control-Allow-Origin", origin);
    resp.Headers.Add("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
    resp.Headers.Add("Access-Control-Allow-Headers", "Content-Type, Set-Cookie");
  }
  return resp;
}

Azure AD App

In order to enforce Azure AD authentication on the Azure Function an Azure AD app registration needs to be created.  Log into the Azure AD admin portal.  Under Azure Active Directory –> App Registrations create a new app registration.

SecureCallAFFromJS1

Take note of the Application ID (also known as client ID) for the application created.  This will be used later in the Azure App Service authentication / authorization configuration.

SecureCallAFFromJS2

The default permissions for the Azure AD app registration (delegated: sign in and read user profile) will be sufficient.

SecureCallAFFromJS3

SecureCallAFFromJS4

Enforce authentication

Return to the Azure Function and navigate to the Platform features –> Authentication / Authorization screen.  Turn App Service Authentication to On, set “Action to take…” to “Log in with Azure Active Directory”, then click the Azure Active Directory authentication provider to configure it as follows.

SecureCallAFFromJS5

Fill in the Application ID / Client ID from the previously created Azure AD app registration.  Specify the IssuerUrl of the Azure AD domain (typically https://login.microsoftonline.com/TENANT_NAME_GOES_HERE.onmicrosoft.com).

SecureCallAFFromJS6

Remove CORS configuration

As noted previously, the Azure portal currently (as of writing May 1, 2018) does not support Azure App Service processing CORS requests that contain credentials.  As such removing all domains from the CORS configuration in Azure Portal is unsupported.  Please validate if this workaround works for you or not.

SecureCallAFFromJS7

Client code

In this example I started with a .Net Framework MVC project from Visual Studio 2017 v15.6.7 but the code could be hosted on any page with HTML, JavaScript, and a logged in user to Azure AD.  Note that the MVC project allows enforcing Azure AD authentication which is what I was most interested in.

SecureCallAFFromJS8

SecureCallAFFromJS9
HTML snippet to include inside of an IFRAME element with source pointing to root of Azure Function.

SecureCallAFFromJS13

JavaScript snippet to call HTTP trigger of Azure Function.

Note that in a production scenario you would want to ensure that the IFRAME has loaded fully (and thus authentication cookie set) prior to the Azure Function being called.

  $(document).ready(function () {
    $("#btnExternalCall").click(function (e) {

      var serviceURL = "https://NAME_OF_AZURE_FUNCTION_GOES_HERE.azurewebsites.net/api/HttpTriggerCSharp1";

      $.ajax({
        url: serviceURL,
        type: "GET",
        xhrFields: {
          withCredentials: true
        },
        crossDomain: true,
        success: function (data) {
          alert("Success: " + data);
        },
        error: function (ex) {
          alert("Failure getting user token");
      }
    });
  });
});

Testing

When all has been configured you can test scenario.  If you enter F12 developer tools from your browser of choice you should see the authentication cookie for both the client web application as well as the Azure Function domains.

SecureCallAFFromJS10

After issuing the call to the HTTP Trigger on the Azure Function you should see that the call was indeed authenticated and the ClaimsPrincipal is returned.

SecureCallAFFromJS11SecureCallAFFromJS12

Conclusion

This is a very powerful capability being able to ensure that an HTTP trigger on an Azure Function only allows authenticated users to call the endpoint.  Hopefully this post helps others who have a similar need.  Please leave and questions or feedback in the comments below.

-Frog Out

Slides from SharePoint Cincy 2018 Conference

This post is a few days late as I’m catching up from being out of town for vacation and at the SharePoint Cincy 2018 Conference.  A big thank you to all who attended my session, the organizers (especially Sean McDonough), sponsors, other speakers, and anyone else who helped put on the conference.  Below are my slides from my session.  Feel free to reach out with any questions or comments.

Dipping Your Toe into Cloud Development with Azure Functions

Slides

      -Frog Out

Speaking at SharePoint Cincy 2018

I’m excited to be speaking at SharePoint Cincy 2018.  I believe this is the 5th year I’ve spoken there and it has always been a good conference to meet with attendees and hear other good content.  Below is an abstract for the session that I’ll be presenting on cloud development using Azure Functions (a recent area of big interest I’ve been working with a customer on).  There is still time to register.  Feel free to use my promo code Jackett2018 for a discount.  If you’re attending the conference feel free to stop by and say hi.

SpeakerBadgeSPCincy2018Jackett

SharePoint Cincy 2018

Website: http://www.sharepointcincy.com/

Registration: http://events.constantcontact.com/register/event?llr=vwg9epoab&oeidk=a07ef00osd9d81e26f2

Title: Dipping Your Toe into Cloud Development with Azure Functions

Abstract: Those on-prem custom solutions (ex. timer jobs, batch processes, etc.) need to be re-written for SharePoint Online. Where do you host them so that you don’t DoS the proxy? How do you properly secure public endpoints for Azure resources? What authentication will you use against SharePoint Online? In this session we will introduce Azure Functions and related services as an option for replacing on-prem solutions while keeping in mind security, architecture, authentication, scalability, and more. We’ll also walk through a real-world scenario calling Office 365 APIs using an authenticated Azure AD app. Prior experience with Azure is helpful but not required.

How To Reference Azure Managed Service Identity (MSI) During ARM Template Deployment

Despite the long title, sharing this information out to the broader community as I had this specific need for a customer scenario and found it in a reply on this StackOverflow thread.  I developed a full ARM template and tweaked the initial solution to better suit my customer’s needs.  You can either download the reference ARM template (no warranties, provided as-is) or implement the pieces that you need.

Scenario

As of the time of writing this, Azure has released into preview the Managed Service Identity (MSI) functionality into preview.  In essence this allows specific Azure resources (ex. app service, VM, etc.) to be granted a service principal in Azure AD which can then be granted permissions in role based access control (RBAC) type fashion.  For a customer they needed to deploy an Azure Function and associated Key Vault.  The MSI for the Azure Function needed to have read (get) access to the secrets within the key vault.  While this could be configured post-ARM template deployment it is easier and more reliable to do so at deployment time.

Solution

The reference ARM template can be downloaded in full from the following location.

https://github.com/BrianTJackett/Blog-Samples/blob/master/MSI-ARM-Template/azure-function-with-MSI-to-key-vault-template.json

In the “Microsoft.Web/sites” resource be sure to enabled the MSI by including the following element at the root of the resource:

"identity": {
         "type": "SystemAssigned"
       }

In order to add the access policy to the key vault, add the following elements as children of the “properties” element:

note: sites_name is the name of a parameter for my given ARM template.  Either hardcode this value or supply a value to this parameter.

"tenantId": "[subscription().tenantid]",

"accessPolicies": [
   {
     "tenantId": "[subscription().tenantid]",
     "objectId": "[reference(concat(resourceId('Microsoft.Web/sites', parameters('sites_name')), '/providers/Microsoft.ManagedIdentity/Identities/default'), '2015-08-31-PREVIEW').principalId]",
     "permissions": {
       "keys": [],
       "secrets": [
         "get"
       ],
       "certificates": []
     }
   }

]

The highlighted portion references the MSI (principalId) of the resource that is being looked up (the Azure Function).

Lastly be sure to establish a dependsOn relationship from the key vault to the Azure Function with the following:

"dependsOn": [
         "[resourceId('Microsoft.Web/sites', parameters('sites_name'))]"
       ]

Conclusion

This post was more of a mental reminder to myself about how to reference an Azure MSI within an ARM template, but if you have need of this same solution hopefully you found it useful.  Feel free to share and questions or feedback in the comments.

-Frog Out