Deploying an Azure Website using PowerShell


Every developer learns that F5 is their deployment friend, but when it comes to deploying to live/production environments it is not an option. So how can you website code be deployed into Azure?

Let’s start of by creating a website in Visual Studio.

  • Open Visual Studio and Click New Project… from the welcome window.
  • From the new project dialog, select ASP.NET web Application and Click OK.

  • On the New ASP.NET Project dialog, select the template you wish to use. I’m using an MVC template, with No Authentication.

  • At this point it will ask you to configure your Microsoft Azure Website. Fill in the details and click OK. (I know this creates the site for you in Azure, we will delete this later.)

Once created you will have a Website, just underneath the solution we have PowerShell files that Visual Studio uses to deploy the website to Azure. It is these PowerShell files and configuration that we will use ourselves.

First we need to package up the website. You can do this by right clicking on the project in Visual Studio and click Publish.

The Publish web dialog that appears will be set up for direct publishing to Azure, we need to change the Publish method to Web Deploy Package, and then give a Package Location.

Click Next > and on the next page of the wizard, ensure you Configuration is set to Release. Note: if there is a web job related to this, then do not click Exclude files from the App_Data folder as this is where the webjobs get compiled to.

Click Next > then Publish.

If you open the folder where you published your website files to you will find a collection of files. The only file you need from here is the zip file, so delete the rest, they are for IIS deployment.

From your Visual Studio project copy over your configuration, Publish-WebApplicationWebsite.ps1 and AzureWebSitePublishModule.psm1 file. These are all the files required to give to your administrator to deploy to Azure, with the next set of instructions with the heading “Deploying to Azure”.

Just before we continue to the next step, go to you azure tenant and delete the website that Visual Studio created, that way you will be doing everything via PowerShell.

Deploying to Azure.

To deploy to Azure you need to ensure you have Azure PowerShell installed on your machine – see my blog Installing Azure PowerShell if you need instructions how to. You will also need to know how to connect to you Azure Subscription via PowerShell. The steps below will show the basic commands but if you have multiple subscriptions you should read my blog Handling Azure PowerShell with multiple Azure Subscription first to ensure you don’t deploy to the wrong subscription.

  • Open the Configurations folder and edit the .json file.
  • Change the website Name and Location to match where you want this deployed and the name you wish to give it.

{

    "environmentSettings": {

        "webSite": {

            "name": "CFWebSiteDemo-Dev",

            "location": "West Europe"

        },

        "databases": [

            {

                "connectionStringName": "",

                "databaseName": "",

                "serverName": "",

                "user": "",

                "password": "",

                "edition": "",

                "size": "",

                "collation": ""

            }

        ]

    }

}

  • As you can see from the script above, I’ve named my CFWebSiteDemo-Dev. Personally I find it useful to copy this file once for each environment (Dev, test, uat, prod), then when I’m deploying I just need to call the right configuration file.

  • Open up an Azure PowerShell Window.
  • Connect using your account. Add-AzureAccount press enter. You will be asked to sign into your Azure account.
  • Type Get-AzureSubscription to see all the subscriptions linked to your account(s). You need to ensure that your subscription you want to use is your current subscription.
  • Type Select-AzureSubscription –SubscriptionId [SubscriptionID]. This should now make your subscription the current subscription. Call Get-AzureSubscription to make sure. Read Handling Azure PowerShell with multiple Azure Subscription if you are still having issues up to this point.
  • Now navigate to your directory in the Powershell window. Mine is at c:\deploy. Cd deploy
  • Now type ./publish-webApplicationWebSite.ps1 –Configuration [Location of correct environment.json file] –WebDeployPackage [Location of zip file]
  • This will create the website in Azure, and then install the files. You will get a screen very similar to below.


NOTE: If you encounter an error when the website is trying to be created, then it will not upload the files. I have had this a few times before. Just check that the Azure website exists in your Azure Tenant and seems to be looking OK, then call the .\Publish-WebApplicationWebSite.ps1 command again. (You might need to try a new Azure PowerShell window.) Other reason why it fails could be due to how your company locks down your network. If you are having no success, try on a network (Starbuck wireless) that doesn’t have a network policy. If it then seems to work on that network, then you have something preventing the upload in your network, and will need to work through the problem with your network administrators.

  • As you can see in my tenant I now have a web app called CFWebSiteDemo-Dev.

  • My Website is up and running.

 

Upgrading Azure Website.

Upgrading the Azure website is very easy, make your changes and then create a new publish zip file.

Use the original PowerShell files and configuration files for Deploying Azure follow these steps.

  • Open up the Azure Windows PowerShell as Administrator.
  • Ensure you have added the account and subscription to your PowerShell profile if you haven’t done the previous steps.
    • Get-AzureAccount –Checks if account is there.
    • Get-AzureSubscription – Checks if Subscription is there.
    • Select-AzureSubscription –SubscriptionName [subscriptionName] –Selects the Subscription to deploy to.
  • Deploying files to Azure
  • Type ‘./Publish-WebApplicationWebsite.ps1 –Configuration [Location of correct environment .json file] –WebDeployPackage [Location of new zip file]
  • Your updated website should now be up and running.

SQL Azure – Connecting to SQL Azure server and database using the browser


In my last post I showed you how to connect to your SQL Azure using SQL Management studio. This post is showing you how to manage your SQL Azure Server and Database within the browser, but please note, I’m not sure how long this feature will be around due to the fact that if you create a server using the V12 (Latest SQL Database), you will not be able to view your database in the browser. Also that the page uses Silverlight to render, and that was killed off in 2012.

To connect through the browser you have two choices:
1. You can log into your Azure Portal, and navigate to your database. At the bottom of the Quick Start page for your database there is a link “Design your SQL database” this will open up another page where you can log into your SQL azure.

2. The other way of access the login page for SQL Azure in the browser is by navigating to the following URL, replacing servername with the name of your server. https://[servername].database.windows.net you will be presented with a login screen.

Using your SQL admin account you can log in. (The login doesn’t have to be the SQL admin, it can be any SQL user account that has already been created)

Once you have logged in, you can then navigate to your database, and click the pencil icon to design.

Once in design mode you could create a new table, view, stored procedure. As I’m not a true SQL developer, this design view is what I’m used to within SQL Management studio. But when connecting to SQL Azure with SQL management studio this functionality is missing.

If you are a true SQL Developer, there is nothing stopping you clicking New Query in the menu bar and writing T-SQL Statements to create your tables, columns, stored procedures etc.

SQL Azure – Creating SQL Azure Server and Database using PowerShell


In the past two blog for SQL Azure, I have shown you how to use the Azure Management portal to create a SQL Azure Server and Database and then update the firewall rules. This blog post is going to show you how you can do the exact same thing via PowerShell.

All the different PowerShell Cmdlets for managing SQL Azure can be found at the MSDN link https://msdn.microsoft.com/en-us/library/azure/dn546726.aspx.

  • Connect to Azure
Add-AzureAccount
  • This will pop up a Microsoft sign in dialog.
  • Sign in with your Azure username and Password.
  • If you know your subscription name you can do the following, otherwise you might need to call Get-AzureSubscription to list all subscriptions you have to find the name, and ID.
$subscriptionName = 'Windows Azure MSDN – Visual Studio Ultimate'

Select-AzureSubscription –SubscriptionName $subscriptionName

#Below is if you have PowerShell Azure version greater than 0.8.14 (get-module azure).version

#subscriptionID = "a222bcff-ac30-554d-67a5-1d6664f1a555"
#Select-AzureSubscription –SubscriptionID $subscriptionID
  • Next step is to create the Azure SQL Database Server. Remember you don’t get to assign a server name.
$location = 'West Europe'
$adminLogin = 'SQLAdmin'
$adminPassword = 'MyPa55w0rd'
$sqlDB = 'DemoDatabase'
 
$sqlServer = New-AzureSqlDatabaseServer –AdministratorLogin $adminLogin –AdministratorLoginPassword $adminpassword –Location $location

  • The above screen shot appears after the SQL server has successfully been created. To view all your SQL Servers type
Get-AzureSqlDatabaseServer
  • If you now try to connect to SQL Azure, you will encounter a firewall warning.
#Either get credentials for SQL authentication by prompting
$cred = Get-Credential
$sqlctx = New-AzureSqlDatabaseServerContext –ServerName $sqlServer.Name –Credential $cred
 
#Or create a Credential object that includes your login information.
$securePassword = ConvertTo-SecureString 'MyPa55w0rd' –AsPlainText -Force
$manualCredential = new-object System.Management.Automation.PSCredential('SQLAdmin',$securepassword)
$sqlctx = New-AzureSqlDatabaseServerContext –ServerName $sqlServer.ServerName –Credential $manualCredential

  • Therefore we need to create a Firewall rule to allow connections to the database server, the IP address is shown in the message above, I’ve hidden mine. The start and end IP address can be the same, or you can put a range in.
New-AzureSqlDatabaseServerFirewallRule –ServerName $sqlServer.ServerName –RuleName 'myOffice' –StartIPAddress '111.111.111.111' –EndIPAddress '222.222.222.222'

  • The above screen shot appears after the SQL server firewall entry has successfully been created. To view all your firewall rules for this server type
Get-AzureSqlDatabaseServerFirewallRule –ServerName $sqlServer.ServerName
  • Now if we retry the step to connect you don’t get the error message. This allows us now to use the context to create a new database. Ensure you include the Edition otherwise the retired “business” edition will be created for you.
New-AzureSqlDatabase –DatabaseName $sqlDB –ConnectionContext $sqlctx –Edition Standard

  • As you can see from above the MaxSizeGB is 1. Not very big. I’m therefore going to increase this to 10GB. (As in my screenshot above I forgot to add –Edition as Standard, you can also use the Set-AzureSqlDatabase cmdlet to change Database Edition.
Set-AzureSqlDatabase –ConnectionContext $sqlctx –DatabaseName $sqlDB –MaxSizeGB 10

 

By using SQL Management studio and connecting to my server I can see that my database has been created.

If I log into the Azure Management Portal I can see:

  • SQL Database and Server

  • Firewall rules

Lastly if you wish to clean up and remove database and Server, just run the following PowerShell, you will be prompted for a confirmation for both commands.

# Delete the database
Remove-AzureSqlDatabase –ConnectionContext $sqlCtx –DatabaseName $sqlDB
 
# Delete the Server
Remove-AzureSqlDatabaseServer $sqlServer.ServerName

 

SQL Azure – Configuring SQL Azure so you can connect from Local SQL Management Studio


In my second post of my SQL Azure series, I’m going to show you how to connect to you SQL Azure server database from SQL Management Studio. You can only connect to SQL Azure from somewhere that is not a Windows Azure service by defining IP Firewall rules.

 

Configuring SQL Azure Firewall rules.

  • Open up the Management Azure Portal and log in using your username and password.
  • Navigate to the SQL databases area.
  • Then for your database, click on the Server Name.

  • Click on the Configure Tab.
  • Find out your external IP address(s) that you will be connecting from, the screen will tell you your current IP address at the top of the screen.
  • In the Rule area below, Put in a Rule Name and then fill out either a range (if using dynamic/multiple IP locations), or the given IP address(es) you will be connecting from.
  • Click Save.

Connecting from a Local SQL Management Studio

You will need to use SQL Server 2012 or above to connect to SQL Azure. Alternatively you can download SQL Server 2014 express for free and download the MgmtStudio Download.

  • Once you have opened the Management SQL Studio, put in the Server name with .database.windows.net at the end. (E.g., Server Name is ctwsc5d11a, then the Server name you put in is ctwsc5d11a.database.windows.net
  • Change the authentication to SQL Server Authentication.
  • Login using the UserName and Password you created when setting up the SQL Azure Server and Database.
  • Click Connect.
  • Once connected you can create Tables, Store Procedures etc. using point and click (which creates valid T-SQL templates) or T-SQL Statements*

(*Please note, not all T-SQL statements that work in Standard SQL works in Azure. For example SELECT INTO doesn’t work unless you predefine the Table and columns first, also there is no designer mode when creating Azure SQL Tables in SQL Management Studio, all you can do is get the T-SQL template to create the table)

SQL Azure – Creating SQL Azure Server and Database in Azure Management


As I’ve recently started using SQL Azure recently at work, and although the steps are basic really to create a database and get up and running, I thought I would post a couple of “simple 101″ blogs just showing you how. This first post of my SQL Azure series will show you the steps to create a SQL Azure Server and database using the good old “point and click” method.

  • Open up the Management Azure Portal and log in using your username and password.
  • Click on New > Data Services > SQL Database > Custom Create.
  • On the dialog window, fill in the boxes.

  • Give the database a name. This is the Database name not the server name. Azure will automatically assign the server name.
  • At the bottom of the page, change the Server tab to New SQL database server, as soon as you do this a second page to the Wizard will appear.
  • Click the next arrow.
  • On the second page fill in the Database Server settings. You need to provide a Login name, password and region. The Login name can be anything you want, however think of this as your SA username and password. (E.g, SQLAdmin)


  • At the bottom of Page 2 wizard is two check boxes:
    • Allow Windows Azure Services to Access the Server – With this ticked it allows you to connect to SQL Azure database from other Azure services (With the username and password). This means any Azure services including Azure services from a different tenant.
    • Enable Latest SQL Database Update – This will give you the latest and greatest version of SQL Azure, sometimes this will be a preview version. At the time of writing this post, V12 was the latest update and it had better T-SQL compatibility. For example I know using V12 allows you to create a table that has no clustered index. This feature is especially helpful for its support of the T-SQL SELECT..INTO statement which creates a table from a query result.
  • Click the tick.
  • Once created you will be given a server name. (I’ve hidden mine for security reasons)


Impersonation with Yammer and C#


Over the past couple of weeks I’ve been investigating and learning how to impersonate a user in Yammer. Although there information out there, there was nothing showing from beginning to end how to make impersonation work. So hopefully this will be people’s goto post. J

First of all from the Yammer Office 365 Network, I would like to thank Chad Cooper and Greg Kiel who helped point me in the right direction, and Chris O’Brien for allowing me to use his test Office 365 with Yammer Enterprise network.

Rules for Impersonation

To be able to impersonate within Yammer:

  • The Yammer network needs to be an Enterprise network – which means you need to pay for it, or you have an E3 365 license with a domain name.
  • You require a Yammer App.
  • You need to be a verified admin to create a Yammer App. This is different from just being an Admin of the network. If you are using Office 365 and you are a global administrator, then in your related Enterprise Yammer, you will be a verified admin. In the SharePoint 365 Admin section you need to ensure that the settings are set to use Yammer for social, and not for SP2013 social. If you have users that are added to your Yammer network, not via Office 365, a verified admin can make other people verified admin, by going to the Network Admin settings, then clicking Admins under the Network section on the navigation menu.
  • Not a rule, but a recommendation to use a Service account that’s a verified admin, (i.e,. an account not assigned to a real person), this will ensure you app continues to work if you or the app creator leaves the company.
  • In the External network the verified admin account that creates and authenticates the app, needs to be a user in the External network.
  • The External network must say it’s parent network is your home network. You cannot impersonate people in external networks that the person or network isn’t related to your default home network.041515_2040_impersonati2

Creating the Yammer App.

To create the app in your network, as stated above, you need to be a Verified Admin.

  • Go to the URL https://www.yammer.com/client_applications
  • One the left hand side, click Register New App
  • This will open up a Register New App dialog. Fill out the information.
    • App Name – The app name which will appear in the Yammer’s activity stream
    • Organization – The name of the organization affiliated with your app
    • Support e-mail – Add which users of your app can contact for support
    • WebSite – Your Organization’s website.
    • Redirect URI – Where Yammer will redirect to after the authentication flow is complete. (In my case I used my SharePoint site)
  • Tick the Terms and Conditions and then click Continue.
  • This will then show you your Client ID, Client secret and Expected redirect URL.
  • Next step is to Implement Authentication the app. Ensure you are still signed in as a verified admin Go to https://www.yammer.com/dialog/oauth?client_id= [ :client_id ] &redirect_uri [ :redirect_uri ] replacing the tokens [:client_id] and [:redirect_uri] with values from the last step.
  • Click Allow, and then the site you are redirected to, at the end of the URL you will find ?code=[:code] save this code somewhere for the time being.
  • Using Chrome – Go to https://www.yammer.com/oauth2/access_token.json?client_id= [ :client_id ] &client_secret= [ :client_secret ] &code= [ :code ] replace the tokens [:client_id], [:client_secret] and [:code] with the values from previous steps. The reason to use chrome is because the response is displayed in the browser. Grab the token value. This value is what you will need when you write code to access Yammer. Do not share it with anyone, it is basically the access right to be a verified admin on your Yammer network.

C# code to impersonate a user.

The demo code below will show you how to get a user ID by using their email address, then impersonate their token, so that you can add them to a group. The comments in the code explains what is happening.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OfficeDevPnP.Core.Utilities;
using System.Net;
using System.IO;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
 
namespace YammerTesting
{
    class Program
    {
        static String GlobalAccessToken = "**************" //Put your token value here, best to store in app config settings.
        static String ClientId = "*************" Put your clientID key of the app here, best to store in app config settings.
 
        static void Main(string[] args)
        {
            AddUserToHomeNetworkGroup("users@emaildomain.com", "5605000");
        }

         //Pass in email address and Group ID, and it will add the user to the group. An action you can only do if you are the actual user.
        private static void AddUserToHomeNetworkGroup(string EmailAddress, string GroupId)
        {
           //Gets the User's ID from Yammer, current running in the App context. If this returns a 404, it means the user email doesn't exist.
            string TargetUserId = MakeYammerRequest(string.Format("https://www.yammer.com/api/v1/users/by_email.json?email={0}", EmailAddress), null, GlobalAccessToken, "id");

          //Passing in the ClientID of the App, the user ID you wish to impersonate and the GlobalAccessToken you will get an impersonation token.
            string impersonationtoken = MakeYammerRequest(string.Format("https://www.yammer.com/api/v1/oauth/tokens.json?consumer_key={0}&user_id={1}", ClientId, TargetUserId), null, GlobalAccessToken, "token");

         //Add User to group with GroupID, this call is made as the User.
         MakeYammerRequest(string.Format("https://www.yammer.com/api/v1/group_memberships.json?group_id={0}", GroupId), "", impersonationtoken, null);
        }
 
       //A method written by <a href="https://twitter.com/stephaneeyskens">@stephaneeyskens</a>;
       //If no data is passed it will perform a GET request, with data it will create a POST request. The key is the value to return within the JSON result.
        private static string MakeYammerRequest(string url, string data, string token, string key)
        {
            HttpWebRequest YammerRequest = HttpWebRequest.Create(url) as HttpWebRequest;
            YammerRequest.Method = "GET";
            YammerRequest.ContentType = "application/json; odata=verbose";
            YammerRequest.Accept = "application/json; odata=verbose";
            YammerRequest.Headers.Add("Authorization", string.Concat("Bearer ", token));
            if (!(data == null))
            {
                YammerRequest.Method = "POST";
                byte[] ByteData = UTF8Encoding.UTF8.GetBytes(data);
                YammerRequest.ContentLength = ByteData.Length;
                Stream YammerRequestStream = YammerRequest.GetRequestStream();
                YammerRequestStream.Write(ByteData, 0, ByteData.Length);
            }

            HttpWebResponse YammerResponse = YammerRequest.GetResponse() as HttpWebResponse;

           //returns a single jArray row
            dynamic resp = JsonConvert.DeserializeObject(
                new StreamReader(YammerRequest.GetResponse().GetResponseStream()).ReadToEnd());

           //Returns the value where the key is…
            return (key != null) ? resp[0][key] : null;
        }
    }
}

External Yammer networks and Impersonation of home users.

With Yammer, you have your default network – let us call that your home network, and you can also create external networks. External networks allow you to invite external users to your Yammer Network, you can also invite all your users from your home network into your external network. However it seems that you cannot impersonate an external user, or impersonate a user in an external network where the parent network of the external network isn’t your home network. I’m happy for someone to correct me, but I don’t think it’s possible, and in the next section after I’ve shown you how to impersonate a home user in an External Yammer network, I will explain why.

The comments in the code explains what is happening.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OfficeDevPnP.Core.Utilities;
using System.Net;
using System.IO;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace YammerTesting
{
    class Program
    {
        static String GlobalAccessToken = "**************"; //Put your token value here, best to store in app config settings.
        static String ClientId = "*************"; Put your clientID key of the app here, best to store in app config settings.
 
        static void Main(string[] args)
        {
            AddHomeUserToExternalNetworkGroup("users@emaildomain.com", "my external network name", "5605010");
        }        

       //Pass in email address, Group ID and the External network name to add user to the group. An action you can only do if you are the actual user.
        private static void AddHomeUserToExternalNetworkGroup(string EmailAddress, string ExternalNetworkName, string GroupId)
        {
           //Gets the User by email. This will grab the user from the home network, current running in the App context. If this returns a 404, it means the user email doesn't exist.

           string TargetUserId = MakeYammerRequest(string.Format("https://www.yammer.com/api/v1/users/by_email.json?email={0}", EmailAddress), null, GlobalAccessToken, "id");

          //Impersonate the User in the home network.
          string impersonatetoken = MakeYammerRequest(string.Format("https://www.yammer.com/api/v1/oauth/tokens.json?consumer_key={0}&user_id={1}", ClientId, TargetUserId), null, GlobalAccessToken, "token");

            //***Extra Step*****    This call will get all the different accessTokens the impersonated user have, by passing in the ExternalNetworkName, we can return just the token for that network.
             string AccessToken = MakeYammerRequestToGetExternalNetworkToken(impersonatetoken, ExternalNetworkName);
 
           //Now we have the AccessToken for the user in the External Network, we can add them to the group.
            MakeYammerRequest(string.Format("https://www.yammer.com/api/v1/group_memberships.json?group_id={0}", GroupId), "", AccessToken, null);
        }

        //A get request to call /api/v1/oauth/tokens.json and return the given network token.
        private static string MakeYammerRequestToGetExternalNetworkToken(string token, string networkName)
        {
            if (networkName == null)
            {
              throw new ArgumentException("Missing networkName.");
            }

            HttpWebRequest YammerRequest = HttpWebRequest.Create("https://www.yammer.com/api/v1/oauth/tokens.json") as HttpWebRequest;
            YammerRequest.Method = "GET";
            YammerRequest.ContentType = "application/json; odata=verbose";
            YammerRequest.Accept = "application/json; odata=verbose";
            YammerRequest.Headers.Add("Authorization", string.Concat("Bearer ", token));
            HttpWebResponse YammerResponse = YammerRequest.GetResponse() as HttpWebResponse;
            //returns multiple jArray rows, one for each network the user is associated with
            JArray resp = (JArray)JsonConvert.DeserializeObject(new StreamReader(YammerRequest.GetResponse().GetResponseStream()).ReadToEnd());

           //Return the row where it contains the external network name.
            var result = resp.FirstOrDefault(x => x["network_name"].ToString().ToLower() == networkName.ToLower());

            if(result != null)
               return result["Token"].ToString();
 
           return null;
        }

       //A method written by &amp;lt;a href="https://twitter.com/stephaneeyskens"&amp;gt;@stephaneeyskens&amp;lt;/a&amp;gt;
      //If no data is passed it will perform a GET request, with data it will create a POST request. The key is the value to return within the JSON result.
        private static string MakeYammerRequest(string url, string data, string token, string key)
        {
            HttpWebRequest YammerRequest = HttpWebRequest.Create(url) as HttpWebRequest;
            YammerRequest.Method = "GET";
            YammerRequest.ContentType = "application/json; odata=verbose";
            YammerRequest.Accept = "application/json; odata=verbose";
            YammerRequest.Headers.Add("Authorization", string.Concat("Bearer ", token));
            if (!(data == null))
            {
                YammerRequest.Method = "POST";
                byte[] ByteData = UTF8Encoding.UTF8.GetBytes(data);
                YammerRequest.ContentLength = ByteData.Length;
                Stream YammerRequestStream = YammerRequest.GetRequestStream();
                YammerRequestStream.Write(ByteData, 0, ByteData.Length);
            }

            HttpWebResponse YammerResponse = YammerRequest.GetResponse() as HttpWebResponse;
           //returns a single jArray row
            dynamic resp = JsonConvert.DeserializeObject(
                new StreamReader(YammerRequest.GetResponse().GetResponseStream()).ReadToEnd());

           //Returns the value where the key is…
           return (key != null) ? resp[0][key] : null;
        }
    }
}

Why you cannot impersonate an External User in an External Yammer Network

Now this was the reason why I started all this work, and it turns out that I don’t think it is possible.

You can get the UserID from the External Network, by calling the following two calls.

//This will get the access token to make a call in the External Network, it uses the App context to get the token.
string AccessToken = MakeYammerRequestToGetExternalNetworkToken(GlobalAccessToken, ExternalNetworkName);

//Get the UserID in that network, using the access token.
string TargetUserId = MakeYammerRequest(string.Format("https://www.yammer.com/api/v1/users/by_email.json?email={0}", EmailAddress), null, AccessToken, "id");

However your next step, you would think, would be to call the following line of code. However your external user is not part of your home network, therefore you will get a 400 bad request error.

string impertoken = MakeYammerRequest(string.Format("https://www.yammer.com/api/v1/oauth/tokens.json?consumer_key={0}&user_id={1}", ClientId, TargetUserId),
               null,
               GlobalAccessToken,
              "token");

Even if you try and use the AccessToken for the ExternalNetwork you get a 401 unauthorised error, which I think is because the access token isn’t acting on behalf of a verified admin, or the App not running the external network.

I believe the only place you can do this, is in the home network of the user. which if they are an external user to you, the likelihood that you have access to their home yammer network is slim. Even slimmer chance is that you are a verified network admin there, and can create an app, as it’s that’s app token you need to use, and then my original method AddHomeUserToExternalNetworkGroup() to get it to work.

Update: I have had more chance to play about with 2 yammer networks that I’m Verified admin in both and I have found out these rules.

  • You can impersonate a user in your home network.
  • You can impersonate a home user in an external network, only if that external network parent network is your home network.
  • You cannot impersonate an external user in your external network where the parent network is your home network.
  • You cannot impersonate by inviting an external user (who is a verified admin and has the app authorized in their network), to your network and making them a verified admin in your network. It doesn’t matter which app token you use, you will not be able to impersonate external users in external networks, you can only do it from the home network.

References:

http://www.silver-it.com/node/174

https://samlman.wordpress.com/2015/03/02/using-impersonation-with-the-yammer-apis/

https://developer.yammer.com/v1.0/docs/impersonation

Handling Azure PowerShell with multiple Azure Subscriptions


The other day I was trying to create an Azure WebSite for a client, I ran the commands, everything was successful. However when I went to the client Azure tenant, there was no sign of the web site! But I could hit the URL, which proved the site existed. I was dreading creating a Microsoft Support call, but as it was near the end of the day I went home. Deal with it in the morning. That evening, I was doing some work at home, and logged into my own personal Azure Tenant, and there was the Website I created for the client.

It turns out,

It doesn’t matter if you are logged into your Azure Website.

It doesn’t matter if you’ve just added the new account to Azure PowerShell.

It doesn’t matter if you’ve not used your old Azure Tenant in a while.

It Does matter what Azure PowerShell has as your Default, or Current Subscription at the time of calling your Azure cmdlets.

What do I mean?

Well before I explain Current/Default Subscription, let’s get those who have never used PowerShell Azure with their Azure account set up.

  1. Open your Azure PowerShell window
  2. Type
    Add-AzureAccount

    press enter.

  3. You will be asked to sign into your Azure account.

  1. Once done, PowerShell window will display your Id, Type of account, Subscriptions, Tenants.

If you now type

Get-AzureSubscription

it will state that your Subscription is the Default and Current. Default means every time you open your PowerShell window, it will already have this subscription loaded. Current means, if you have multiple subscriptions the one marked as current is the one you are performing your cmdlets against.

Selecting the Azure Subscription to work against.

So what to do? I’ve added a second, free trial azure subscription to powershell azure by calling the

Add-AzureAccout


cmdlet again. I’ve then called

Get-AzureSubscription


again to list all subscriptions. (Please note, you might have one account that have several subscriptions, it’s not a one to one relationship, just happens to be for me).

As you can see from the above image, the Subscription Name “Windows Azure MSDN – Visual Studio Ultimate” is both the default and the current subscription.

I can make the Subscription Name “Free Trial” my current subscription by calling (Note: Subscription name is case sensitive)

Select-AzureSubscription –SubscriptionName "Free Trial"

NOTE: (Just learnt this myself!!) If you have version 0.8.14 of PowerShell Azure you can call by Subscription ID instead. This will help for people with Multiple Subscriptions with the same name. Not sure which version this was implemented but in 0.8.3 it wasn’t there. Find out your version by typing (get-module azure).version

Select-AzureSubscription –SubscriptionId [SubscriptionID]

Now if you type

Get-AzureSubscription

you can see that my Free Trial is now Current.

To make the Free Trial default, all I need to do is add –Default to the Select-AzureSubscription cmdlet

Select-AzureSubscription  -SubscriptionName "Free Trial" –Default

Hopefully now you won’t end up making changes to the wrong Azure instance like I did originally.