Using Azure Cognitive Services from Logic Apps

Azure’s Cognitive Services are very easy to use from within your own applications or more “code-less” solutions such as Azure Logic Apps. In this post, I will show a simple example of a Logic App that does sentiment analysis on incoming tweets. When the sentiment score is very high, an SMS is sent.

To perform sentiment analysis, use the Text Analytics API from Cognitive Services. First, in the Azure Portal, create a Cognitive Services account of type Text Analytics. After that account has been created, you will need the following information to be used in Logic Apps:

  • Endpoint: https://westus.api.cognitive.microsoft.com/text/analytics/v2.0
  • Key: use one of the two secret keys to access the API

If you create a Cognitive Services account in the free tier, you can make 5000 calls per 30 days.

Now create a Logic App in the Azure Portal and go to Triggers and Actions to enter the designer. I will not provide step-by-step details as working with triggers and actions in the graphical designer is very easy. To obtain the results we want, we will have to switch to Code View though.

First, from the Microsoft Managed APIs, add a Twitter trigger. Provide your credentials to Twitter and provide a search term.

Now click the + icon to add an action. To call the Sentiment Analysis API, use the HTTP action and provide the following information (Note: forgetting to specify the specific API to call is a common error; for the URI below also add /sentiment to perform sentiment analysis!!!):

2016-04-22 15_48_34-Logic Apps Designer - Microsoft Azure

Naturally, replace your key with one of the keys obtained from your Cognitive Services account. The body of your HTTP POST can be an array of documents, with each document having an id and the text you want to analyze. In our case, we want to analyze the Tweet text so we use the graphical designer to insert it. In Code View, this will be:

2016-04-22 15_52_59-Logic Apps Designer - Microsoft Azure

Now we want to send an SMS when the sentiment of the Tweet is very positive. The sentiment is expressed as a value between 0 and 1 where 1 is a really, really, really positive tweet.

To send an SMS when the sentiment is above 0.95, first click the + icon and add a condition. The value to evaluate is part of the HTTP body of the previous action. So add that and select greater than or equals and enter 0.95 in the value. Then switch to advanced view to see the expression you built. It will look like:

@greaterOrEquals(body(‘Http’), 0.95)

The above is not going to cut it though since the response body is JSON and the sentiment score needs to be extracted from it. Change the expression to the following:

@greaterOrEquals(float(json(string(body(‘Http’))).documents[0].score), 0.95)

Since the response body is an array of documents and we only have one document, just obtain the score from the first document.

2016-04-22 16_03_05-Logic Apps Designer - Microsoft Azure

Now we can click Add an action in the If yes section to send an SMS. You can use the Twilio Send Message Managed API to do so but you will need an account at Twilio for this to work. Alternatively, you can send an e-mail or just post a result to http://requestb.in. For Twilio, you will end up with something like below. Phone numbers have been blurred to protect the innocent.

2016-04-22 16_08_08-Logic Apps Designer - Microsoft Azure

In the above, we only want to show the score for the Tweet and not the whole body. This can be done in Code View:

In the Send_Message action, change the following:

@{body(‘Http’)} for @{triggerBody()[‘TweetText’]}

to:

@{json(string(body(‘Http’))).documents[0].score} for @{triggerBody()[‘TweetText’]}

Note that changes like the above can make the UI designer unavailable.

When you save this Logic App, incoming tweets containing Azure should be analyzed and you should get SMSs when tweets are very positive. Hey, it’s Azure, why shouldn’t they be? 🙂

You can check if the Logic App is executing correctly from the Operations tile:

2016-04-22 16_23_11-Logic Apps Designer - Microsoft Azure

For a search term like Azure, I recommend to turn off the Logic App if you don’t want to exhaust your 5000 free tier API calls.

Azure Resource Manager REST API from Node

In our video about Fault Domains in Azure IaaSv2, we mentioned Azure Resource Manager and the use of templates to deploy IaaSv2 resources such as virtual machines in a fault domain, a load balancer, a public IP address and more. Azure Resource Manager also has a REST API that can be used from any language. This post discusses the use of the REST API from node.js, including obtaining a token from Azure Active Directory using adal-node.

Before obtaining the token, you need to decide which account to use. In this case I created a service principal in Azure AD to be used as a service account. The process to create a service principal is well documented here and here. I created the service principal using the procedure in the first link, by creating a dummy application in Azure Active Directory. When you create such a dummy application you will obtain two of several things you need to obtain the token:

  • The client ID (a GUID) which basically serves as the user name
  • A generated key with a validity of 1 or 2 years that servers as the password

Other information you will need is the tenant ID (also a GUID) which is used to construct the authorization URL. To actually obtain the token using ADAL (Active Directory Authentication Library) for node.js with adal-node, take a look at adal-node on npm, in the server to server with client credentials sample. There are some issues with that sample code, so I modified it as follows:

var adal=require('adal-node');
var AuthenticationContext= adal.AuthenticationContext;
var tenantID="TenantIDGUID";
var clientID="ClientIDGUID";
var resource="https://management.azure.com/";
var authURL="https://login.windows.net/" + tenantID;
var secret="ClientSecret";
var context=new AuthenticationContext(authURL);
context.acquireTokenWithClientCredentials(resource, clientID, secret, function(err,tokenResponse) { }

Some things to note:

Once you obtain the token, you will get a tokenResponse in the callback function. The tokenResponse contains:

{ tokenType: 'Bearer',
expiresIn: 3600,
expiresOn: Fri Jun 05 2015 10:46:48 GMT+0200 (Romance Daylight Time),
resource: 'https://management.azure.com/',
accessToken: 'long, long token',
isMRRT: true,
_clientId: 'clientID',
_authority: 'https://login.windows.net/tenantID' }

So basically, you are getting an OAuth bearer token you can use in a call to a Web API that expects such a token. The Azure Resource Manager REST APIs will be called with this token.

To actually make the API request, I do the following:

  • Use the restler module: see https://www.npmjs.com/package/restler
  • Get the access token from the token response above: the token is obtained with tokenResponse[‘accessToken’]
  • Build the request URL, in this case to list all resources in my subscription. To interactively find out the kind of requests you can make, use Resource Explorer
  • Make the REST call with restler, passing the accessToken

The code looks like this where you replace {yourSubID} with your Azure subscription ID:

var rest=require('restler');
authHeader = tokenResponse['accessToken'];
requestURL="https://management.azure.com/subscriptions/{yourSubID}/resources?api-version=2015-01-01";
rest.get(requestURL, {accessToken:authHeader}).on('complete',function(result) {
console.log(result); });

If you go to https://github.com/gbaeke/armnode you will find the full samples to get you started. Hope this is helpful. Leave a comment if you have further questions.

Fault Domains in Azure IaaSv2

With the availability of IaaSv2 in Microsoft Azure, several new features are available that dramatically change the way resources are deployed and maintained. One profound change is the introduction of three fault domains for IaaSv2 virtual machines as opposed to two fault domains for IaaSv1 virtual machines. In the case of Azure, a fault domain is basically a rack of servers. A power failure at the rack level will impact all servers in the rack or fault domain. To make sure your application can survive a fault domain failure, you will need to spread your application’s components, for instance front-end web servers, across fault domains. The way to do this in Azure is to assign virtual machines to an availability set. Upon deployment but also during service healing, Azure’s fabric controller will spread the virtual machines that belong to the same availability set across the fault domains automatically. As an administrator, you cannot control this assignment.

If you deploy virtual machines in cloud services (IaaSv1 style), the maximum amount of fault domains is two which can present a problem. For instance, when you deploy a majority node set cluster with three nodes across two fault domains, it is entirely possible that the fault domain that hosts two of the three nodes fails. When that happens, the surviving node does not have majority and will go offline as well. For such deployments, three fault domains are a requirement to survive a failure in one fault domain.

Now that you understand what a fault domain is and the requirement for three fault domains, how do you get three fault domains in Azure? Well, you will need to deploy virtual machines using the IaaSv2 model. This model is based on Azure Resource Manager which also enables rich template based deployment of virtual machines, network interfaces, IP addresses, load balancers, web sites and more. Many Microsoft and community templates can be found at http://azure.microsoft.com/en-us/documentation/templates/

To get a feel for how such a deployment works and to check if your resources are spread across three fault domains, take a look at our Cloud Chat video:

Windows Azure Point-to-Site Networking

If you are having trouble with the point-to-site VPN configuration in Windows Azure, here are some tips about the procedure:

  • Follow the procedure located at http://msdn.microsoft.com/en-us/library/windowsazure/dn133792.aspx for creating the virtual network and the gateway.
  • When configuring the certificates for the VPN connection, first create the self-signed root certificate with the following command:  

    makecert -sky exchange -r -n "CN=RootCertificateName" –pe -a sha1 -len 2048 -ss My

  • The above command creates a self-signed root certificate and stores it in your certificate store (Certificates – Current User\Personal\Certificates). Next, export that certificate to a .cer file and upload it to Azure from the dashboard of the virtual network using the Upload client certificate link (the name of that link will probably be changed in the future Smile) I also stored the root certificate in my Trusted Roots.
  • Now create a client certificate with the self-signed root certificate as the issuer. The command I used is different from the one in the documentation because it did not work for me. I used:

    makecert -n "CN=ClientCertificateName" -pe -sky exchange -m 96 -ss
    my -a sha1 -is my -in "RootCertificateName"

  • The above command creates the client certificate in the same store as the root certificate and uses the root certificate previously generated as the issuer. Be sure to check that the issuer is the root certificate you uploaded to Azure.

In the dashboard of the virtual network, download the x64 or x86 client VPN package and install it. There will be an extra network connection that uses SSTP to connect to your Azure gateway:

image

 

In Azure the dashboard should show connected clients:

image

Office 365 Identity Management with DirSync without Exchange Server On-Premises

This post describes how users, groups and contact are provisioned in Office 365 from the on-premises Active Directory. By using DirSync, these objects are created in and synchronized to Office 365. Without an Exchange Server and Exchange Management tools in place, it is not always obvious how these objects should be created.

The following sections describe the procedures you can follow without Exchange or the Exchange management tools in place.

IMPORTANT NOTE
The sections below only specify the basic actions you need to perform in Active Directory to have the object appear in the right place in Office 365 (user, security group, mailbox, distribution group, contact). Note that almost all properties of these objects need to be set in Active Directory. If you want to hide a distribution group from the address book or you want to configure moderation for a distribution group, you have to know the property in Active Directory that’s responsible for the setting, set the value and perform directory synchronization. You will also need to upgrade the Active Directory schema with Exchange Server 2010 schema updates. You cannot use the Exchange Server 2010 System Manager without having at least one Exchange Server 2010 role installed on-premises.

Create a user account

Create a regular user account in Active Directory. This user account will be replicated by DirSync and it will appear in the Users list in the portal (https://portal.microsoftonline.com).

Important: set the user logon name to a value with a suffix that matches the suffix used for logging on to Office 365. For instance, if you logon with first.last@xylos.com in Office 365, set the UPN to that value:
clip_image002

User accounts without a mailbox (or any other license) can be used in Office 365 to grant permissions such as Billing Administrator or Global Administrator. A user account like this is typically used to create a DirSync service account.

Create a user account for a user that needs a mailbox

Create a user account as above. Set the user’s primary e-mail address in the email attribute or you will get an onmicrosoft.com address only:

clip_image004

When this user is synchronized and an Exchange Online license is added in the portal, a mailbox will be created that has the E-mail address in the E-mail field as primary SMTP address. Automatically, a secondary SMTP address is created with prefix@tenantid.onmicrosoft.com:

clip_image006

What if the user needs extra SMTP addresses?

  • You cannot set extra SMTP addresses in Exchange Control Panel (or Remote PowerShell) because the object is synchronized with DirSync.
  • In the on-premises Active Directory you need to populate the proxyAddresses attribute of the user object. You can set the values in this field with ADSIEdit or Active Directory Users and Computers (Windows Server 2008 ADUC and higher with Advanced Features turned on)
  • In the proxyAddresses field, make sure that you also list the primary SMTP address with SMTP: (in uppercase) in front of the address. Secondary addresses need smtp: (in lowercase) in front of the address.
    clip_image008

Note: instead of editing the proxyAddresses field directly, you can use a free (but at this point in time beta) product: http://www.messageops.com/software/office-365-tools-and-utilities/office-365-active-directory-addin. The tool adds the following tabs to Active Directory Users and Computers:

  • O365 Exchange General: set display name, Email address, additional Email addresses and even a Target Email Address (for mail redirection)
  • O365 Custom Attributes: set custom attributes in AD for replication to Office 365
  • O365 Delivery Restrictions: accept messages from, reject messages from
  • O365 Photo: this photo will appear on the user’s profile and will be used by Lync Online as well
  • O365 Delegates: to set the publicDelegates property

When a user is created in AD, you can use the additional tabs this tool provides to set all needed properties at once.

To summarize the actions for a mailbox:

  • Create a user in ADUC with the user logon name (UPN) and e-mail address to the primary e-mail address of the user (UPN and e-mail address do not have to match but it’s the most common case)
  • Make sure the user has a display name (done automatically for users if you specify first, last and full name in the AD wizard)
  • Set proxyAddresses manually or with the MessageOps add-in to specify additional e-mail addresses (with smtp: in the front) and make sure you also specify the primary e-mail address with SMTP: in the front.
  • Let DirSync create and sync the user to Office 365
  • Assign an Exchange Online license to the user. A mailbox will be created with the correct e-mail addresses.

Create a security group

Create a security group in Active Directory. The group will be synchronized by DirSync and appear in the Security Groups in the portal. The group will not appear in the Distribution Groups in Exchange Online (obviously).

Create a distribution group

Create a distribution group in Active Directory. In the properties of the group set the primary e-mail address in the E-mail address field:

clip_image010

In addition to the e-mail address, the group object also needs a display name (displayname attribute). If the distribution group in AD has an e-mail address and a display name, the group will appear in the Distribution Groups list in Exchange Online after synchronization.

Note that specifying members and alternate e-mail addresses has to be done in the local Active Directory as well. If you have installed the MessageOps add-in, you can set easily set those properties.

Create a mail-enabled distribution group

You can add a display name and e-mail address to a standard security group to mail-enable the group. After stamping those two properties, the group will appear in the list of Distribution Groups in Exchange Online. When you list groups with the Get-Group cmdlet, you will see the following:

clip_image012

You can stamp the properties manually or use the MessageOps add-in to set these properties easily.

Create a contact

Create a contact object in Active Directory. In the properties of the created object, fill in the E-mail field in the General tab.

Conclusion

Although DirSync makes it easy to create directory objects in Office 365, without an Exchange Server and the Exchange management tools it is not always obvious how to set the needed properties in order to correctly synch these objects. If you find it too much of a hassle to set the required properties on your local Active Directory objects, there are basically two things you can do:

  • Turn off Directory Synchronization and start mastering directory objects in the cloud
  • Install at least one Exchange Server 2010 SP1 so that you can use the Exchange management tools

Issue with meeting invites during Office 365 staged migration

During a recent migration project, we migrated several mailboxes to Office 365 using the staged migration approach. Naturally, during the migration, users that had been migrated still sent meeting invites to on-premises users and meeting rooms. The problem was that meeting invites were actually received as clear text and stripped of the necessary attributes that make it a meeting request. The on-premises server was Exchange Server 2003 SP2.

As you might know, during a staged migration, DirSync creates MEUs (mail-enabled users) in the cloud. These MEUs actually represent on-premises users that have not been migrated yet and they make sure that the global address list in Office 365 matches the on-premises global address list.

When a user with a cloud mailbox sends a meeting invite to an on-premises user, he actually sends the invite to the MEU. The MEU has a TargetAddress that points back to the on-premises user. The MEU also has settings that control how mail should be formatted when sent to the actual on-premises user. The solution to the problem was to change the UseMapiRichTextFormat  to a value of Never using the following PowerShell command:

set-MailUser MEUname -UseMapiRichTextFormat Never

For all MailUser objects, use:

get-mailuser | set-MailUser -UseMapiRichTextFormat Never

After running this command, cloud users could successfully send meeting requests to on-premises users. Hope it helps!

A quick look at Windows Azure IaaS

I played around a bit with Windows Azure IaaS to see how it stacks up against Amazon EC2. We use Amazon EC2 internally for some test and demo setups that don’t always have to be running.

As a practical test, I wanted to install a Windows Server 2012 domain controller in a subnet of my choice. It turns out that getting started is pretty simple. The rest of this post presumes that you have a Windows Azure account with the Virtual Machines Preview activated (go to http://www.windowsazure.com to get started).

You can manage virtual machines from the new management interface at https://manage.windowsazure.com or with Windows Azure PowerShell (https://www.windowsazure.com/en-us/manage/downloads/). This post will not use Powershell. Sorry! Smile

The first thing I did was to create a new virtual network which also lets you create an affinity group. Affinity groups allow you to have some control over the location of components like storage in order to reduce latency for instance. To learn more about affinity groups, take a look at http://social.technet.microsoft.com/wiki/contents/articles/7916.importance-of-windows-azure-affinity-groups.aspx. Note that there are other ways to create affinity groups, but it’s easy to do when you create your virtual networks. I will not bother you with the details of creating the virtual network and just show the end result. I created a virtual network with two subnets: prod and dev.

image

The details for the subnets can be seen when clicking Configure:

image

Note that there is more you can configure here. You can specify DNS servers that will then be handed out to your VMs using DHCP. In addition, you can configure a connection to your on-premises network using a site-to-site VPN solution.

After the networks are configured (including the affinity group), it’s time to create a storage account. Storage accounts are not new in Azure and are traditionally used to store BLOBs, tables and queues. The virtual machine disks you create (or that will be created automatically as an OS disk) will actually be stored in BLOB storage. I created the following storage account:

image

During the creation of the account, you will be asked for the affinity group. You see that reflected above in the location property. Note that you can actually take a look inside the storage account with a tool like Azure Storage Explorer (http://azurestorageexplorer.codeplex.com/). After adding your storage account using the name and the key (you can get that from the old portal), you will see:

image

Above, you see the boot disk of a virtual machine of 30GB. Files in BLOB storage have a maximum size of 1TB so VHDs are also limited to 1TB. Depending on the VM size, you can add additional disks of 1TB to a VM. The maximum amount of disks you can add today is 16 and you can stripe these inside the VM to a 16TB volume if required.

Now we have our network and storage defined, we can create a virtual machine. It’s important to note that you should create the virtual machine with the From Gallery option to be able to specify all the necessary settings such as the network:

image

When you click From Gallery, you will get a wizard with the following questions:

  • OS selection: Windows Server 2008 R2, Windows Server 2012, CentOS, Ubuntu, …
  • VM config: name, administrator password, size (from Extra Small to Extra Large)
  • VM mode: here’s where you select the storage account and the network
  • VM options: here you can select the virtual network subnets that this virtual machine should belong to

The virtual machine will then be provisioned and shown in the list:

image

Connecting to the virtual machine is easy with Remote Desktop and the Connect option at the bottom of the screen (with the virtual machine highlighted). The connection will not be made to the standard RDP port. Behind the scenes, every VM (or multiple VMs) live in a cloud service and each cloud service has an associated public IPv4 address. Each VM in the cloud service has an external port mapped to its RDP port. The external port is generated randomly but you can change it in the configuration of the virtual machine:

image

The cloud service’s IP address is automatically mapped to servicename.cloudapp.net so in the above example you would connect to servicename.cloudapp.net:50248 to connect to the virtual machine.

When you create your first virtual machine, you will not see the associated cloud service in the user interface. When you create another virtual machine and select to connect to an existing virtual machine in the VM options page, the cloud service will be shown in the UI:

image

The cloud service provides a view on the group of servers in the service. You can see the total amount of cores in the service, aggregated CPU utilization and more.

Now we have a virtual machine running, what about its IP address? Virtual machines are automatically assigned an IP from the range that was specified in the virtual network assigned to the virtual machine. If you specified your own DNS servers, these will be supplied as well. If not, Azure DNS servers will be assigned. It’s important to know that IPs should only be assigned through DHCP. Do not configure static IP addresses, not even one that matches the IP that was assigned. You should be aware that if your virtual machine were to fail (e.g. because of host failure), the same IP will be assigned although the MAC address will change.

Now that this is all sorted out, is there something we have to think of regarding the deployment of a domain controller? The answer is: absolutely! In short:

  • Although you have always learnt to assign a static IP to a DC, forget about that now. Use the DHCP assigned address as stated earlier.
  • Do not place the Active Directory DIT, logs and SYSVOL on the operating system disk but on an attached data disk. Data disks do not use “write-behind” caching it seems.
  • Windows Azure today does not use Hyper-V 3 so the new VMgenerationID stuff in Windows Server 2012 is not supported.

Now how does Windows Azure IaaS stack up against EC2? I have not played around with it enough to know all the details and differences but this is what I found so far:

  • Connecting to virtual machines using RDP and the concept of the cloud service and port mapping makes it easier to connect to virtual machines in a private virtual network. In EC2 you have to set this up yourself or use a Terminal Services gateway.
  • Virtual machines seem to have the ability to connect to the Internet by default. In EC2 you need to assign an elastic IP or use some gateway solution inside the virtual private container.
  • It is relatively easy to get started. The EC2 learning curve is a bit higher but there are more options as well so that evens it out.

Enabling and disabling DirSync in BPOS and Office 365

If you have some experience with BPOS or the Office 365 Beta, you know there’s a tool called DirSync that allows you to synchronize your Active Directory with Microsoft’s Online Services. During a course last week, I was asked if you can use DirSync temporarily to sync users, contacts and groups and, after migration, turn it off.

In BPOS, you can certainly do the above and essentially use DirSync as just a migration tool. It is in fact the easiest way to load users, contacts and groups into BPOS if you don’t mind setting up the software. When you turn off DirSync in the BPOS Administration website, all synchronized users become normal users which means their properties become editable. Turning off DirSync is done from the Migration / Directory Synchronization tab:

image

In Office 365, it’s a totally different story because DirSync is intended as a tool for permanent coexistence. As a result, you will not find a Disable button in the UI and there’s also no PowerShell cmdlet to turn it off. If you just want to migrate your users, contacts and distribution groups to Office 365 you should use other means such as CSV, PowerShell, etc…

Office 365 and Identity

imageMicrosoft has provided more details about Office 365 and the different identity options in a service description document (link at the bottom of this post).

There are two types of identities:

  • Cloud Identity: credentials are separate from your corporate credentials
  • Federated Identity: users can sign in with their corporate Active Directory credentials

With BPOS, there was only one type: cloud identity. Users had to logon using a Sign-In Assistant that stored the cloud credentials (name and password) and used those credentials to sign in in the background. For larger organizations, the Sign-In Assistant was a pain to install and manage so it’s a good thing it is going away.

With the new identity solution, as stated above, the Sign-In Assistant goes away and the logon experience is determined by the type of identity and how you access the service. The table below summarizes the sign-in experience:

image

1 The password can be saved to avoid continuous prompting
2 During the beta, with Federated IDs, you will be prompted when first accessing the services
3 Outlook 2007 will be updated to give the same experience as Outlook 2010

Note that it is required to install some components and updates on user’s workstations if rich clients are used to access Office 365. Although you can manually install these updates, the Office 365 Desktop Setup package does all that is needed. Office 365 Desktop Setup was formerly called the Microsoft Online Services Connector. Office 365 Desktop Setup supports Windows XP (SP2) and higher.

A couple of other things that are good to know:

  • Office 365 supports two-factor authentication if you implement SSO with Active Directory Federation Services 2.0. There are two options to enforce two-factor auth: on the ADFS 2.0 proxy logon page or at the ForeFront UAG SP1 level.
  • Active Directory synchronization is supported with the Microsoft Online Services Directory Synchronization tool. The tool is basically the same as with BPOS although there are some changes to support new features: security group replication, write back (which also enables some extra features), etc…
  • Note that the synchronization tool still does not support multiple forests.
  • The synchronization tool is required in migration scenarios like rich coexistence, simple coexistence and staged migration with simple coexistence.

The full details can be downloaded from the Microsoft website. If you are involved in Office 365 projects, this is considered required reading!

Office 365 SharePoint Online Storage

imageMicrosoft has recently published updated Office 365 Service Descriptions at http://www.microsoft.com/downloads/en/details.aspx?FamilyID=6c6ecc6c-64f5-490a-bca3-8835c9a4a2ea.

The SharePoint Online service description contains some interesting information, some of which I did not know yet. We typically receive a lot of questions about SharePoint online and storage. The list below summarizes the storage related features:

  • The storage pool starts at 10GB with 500MB of extra storage per user account (talking about enterprise user accounts here).
  • Maximum amount of storage is 5TB.
  • File upload limit is 250MB.
  • Storage can be allocated to a maximum of 300 site collections. The maximum amount of storage for a site collection is 100GB.
  • My Sites are available and each My Site is set at 500MB (this is not the 500MB noted above, in essence this is extra storage for each user’s personal data).
  • A My Site is not counted as a site collection. In other words, you can have 300 normal site collections and many more My Sites.
  • Extra storage can be purchased (as before) at $2,5USD/GB per month.

When it comes to external users (for extranet scenarios), the document states that final cost information is not available yet. It is the intention of Microsoft to sell these licenses in packs.

Check out the SharePoint Online service description for full details.

%d bloggers like this: