Tuesday, December 1, 2020

App.config vs App service configuration settings for storing app settings for Azure web jobs

As you probably know when you upload zip package with exe application to Azure App service > Web jobs (to run it as Azure web job by scheduler) – you may override app settings in App service > Configuration > Application settings section. In this case settings defined in Azure will have priority over settings defined in app.config which is deployed as part of zip package:

However it is important to note that even if you will use app settings from Azure – it is still necessary to include app.config to zip package. Otherwise if you will exclude app.config from zip package – then ConfigurationManager.AppSettings will return empty collection. So good practice is to add app.config with empty values to zip package and then manage app settings in Azure. Don’t forget to remove values from app.config – otherwise sensitive information (client secrets, passwords, keys, etc) may be accidentally leaked with zip package of web job.

Tuesday, November 24, 2020

Enable ReSharper unit tests runner with TypeMock isolator

If you use TypeMock isolator for writing unit tests (which is great library for mocking from my point of view) and ReSharper to make user experience in Visual Studio better (which is another great tool :) ) then you may face with the following problem when try to run unit tests in ReSharper test runner: tests will fail with the following error

TypeMock.TypeMockException :
*** Typemock Isolator is currently disabled. Enable using the following:

* Within Visual Studio:
    - Use Typemock Smart Runner 
    - For other runners, Choose Typemock Menu and click "Integrate with Other Runners"
 
  * To run Typemock Isolator as part of an automated process you can:
     - run tests via TMockRunner.exe command line tool
     - use 'TypeMockStart' tasks for MSBuild or NAnt
 
For more information consult the documentation (see 'Running Unit Tests in an Automated Build')
    at TypeMock.InterceptorsWrapper.VerifyInterceptorsIsLoaded()

This error will be still there even if “Integrate with other runners” option will be checked in Typemock menu:

In order to fix this problem do the following:

1. Go to TypeMock installation folder (C:\Program Files (x86)\Typemock\Isolator\x.x) and create or edit knownRunners.dat file there

2. In this file add process name of ReSharper unit tests runner on separate line: for ReSharper 2020 it will be “ReSharperTestRunner64c.exe”.
In order to know process name of the runner - run unit tests with it, find it in Process Explorer (if runner was ran from Visual Studio it will be shown under Visual Studio process tree) > right click > Properties > copy exe file name.

After that run unit tests with TypeMock in ReSharper test runner – they should work now.

Monday, November 16, 2020

Remote debugging of Azure functions in Visual Studio

When developing for Azure you should definitely take a look on Visual Studio’s Cloud Explorer (Views > Cloud Explorer) as it has features which are missing in basic Azure portal. E.g. when working with Notification hubs it allows to manage existing subscriptions for push notifications (view and delete if needed). There is one more useful feature if you develop Azure functions which I explored recently: remote debugging. It allows you to attach debugger to remote process of your Azure function app running in Azure and debug it in your Visual Studio.

In order to do that open Cloud explorer > choose subscription > App services > right click on Azure function app > Attach debugger:

If it will show error:

System.Runtime.InteropServices.COMException (0x89710023): Unable to connect to the Microsoft Visual Studio Remote Debugger named '{tenant}.azurewebsites.net'.  The Visual Studio 2017 Remote Debugger (MSVSMON.EXE) does not appear to be running on the remote computer. This may be because a firewall is preventing communication to the remote computer. Please see Help for assistance on configuring remote debugging.

ensure that port 4022 which is used by remote debugger is opened in firewall. After that you should be able to debug remote Azure functions running on Azure.

Friday, November 13, 2020

Create new Team UX when use sensitive labels

In this article I will show how different sensitive labels affect UX on the standard Create new Team form. For testing I created 6 different sensitive labels with different Privacy and external sharing settings:

Name

Privacy

External user access

1

Private

Private

No

2

Public

Public

No

3

Private or public

None

No

4

Private with external users

Private

Yes

5

Public with external users

Public

Yes

6

Private or public with external users

None

Yes

Let’s see how teams creation form looks like for each sensitivity label from table above.

1. Private

2. Public

3. Private or public

4. Private with external users

5. Public with external users

3. Private or public with external users

Thursday, November 12, 2020

Applying O365 sensitivity labels for different containers

In my previous post I showed how to enable sensitivity labels for different containers (SPO sites, Teams, O365 groups) in the tenant . Let’s see in more details how exactly applying of sensitivity labels looks like and to which exact containers it can be applied.

First of all let’s go to Sharepoint Online and try to create new site there. We will see that sensitivity labels are available for Modern Sharepoint Online sites: both Modern Team site

and Modern Communication sites

But if we will try to create Classic site (e.g. using Publishing Portal site template) we will see that sensitivity labels are not available:

So for Classic Sharepoint sites sensitivity labels are not available.

Next let’s go to Teams and try to create new Team there: we will see that Sensitivity field appeared on the Teams creation form:

Finally if we will go to Azure portal and will try to create new O365/M365 group we will also see that Sensitivity field will be available:

In the future posts we will check other details of sensitivity labels functionality in O365.

Monday, November 9, 2020

Enable sensitivity labels for Sharepoint sites, Teams and O365 groups

Sensitivity labels help to maintain content in your organization. In opposite to classification labels which are more like additional metadata for O365 groups/SP sites where custom policies have to be enforced by internal tools or custom PowerShell scripts (i.e. don’t have O365 policies assigned to them) sensitivity labels have policies behind and allow to use O365 infrastructure to maintain sensitive data in your organization.

Sensitivity labels may be enabled from several places:

By default they can be used for files in emails but in order to enable them for “container” (SP online sites, Teams and O365 groups) several additional steps should be done:

1. First of all enable sensitivity labels from PowerShell using the following script:

Import-Module AzureADPreview
Connect-AzureAD
$Setting = Get-AzureADDirectorySetting -Id (Get-AzureADDirectorySetting | where -Property DisplayName -Value "Group.Unified" -EQ).id
$Setting["EnableMIPLabels"] = "True"
Set-AzureADDirectorySetting -Id $Setting.Id -DirectorySetting $Setting

2. After that we need to sync them to AzureAD using the following script:

Install-Module -Name ExchangeOnlineManagement
Import-Module ExchangeOnlineManagement
$UserCredential = Get-Credential
Connect-IPPSSession -Credential $UserCredential
Execute-AzureADLabelSync
Disconnect-ExchangeOnline

If you will have error "It is about Unable to resolve package source https://www.powershellgallery.com/api/v2” then start new PowerShell session as administrator and run the following command as 1st command in the session:

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

and then run above script again.

After these steps you will be able to create sensitivity labels for SP sites, Teams and O365 groups. Let’s see how it looks like in Security and compliance center > Classification > Sensitivity labels. Pay attention that there is now the following note:

You can now create sensitivity labels with privacy and access control settings for Teams, SharePoint sites, and Microsoft 365 Groups.

Click Create a label – after that New label wizard will be opened. On the first step we need tp specify name and description and on 2nd step it will be possible to choose both Files & emails and Groups & sites:

Here we are interested in Groups and sites so let’s keep only this option checked. Skip next step for Files and emails and open next step “Define protection settings for groups and sites”. On this step we may set “Privacy and external user access settings” and “Device access and external sharing settings”:

E.g. if we will check “Privacy and external user access settings” then on the next step we will be able to set privacy and external users settings for sites/teams/groups for which this label will be applied:

On the final step we will need to publish our new label (this will open own wizard).

After label has been published it will take up to 10 minutes before it will appear in O365 UI:

This is how you may enable sensitive labels for SP sites, Teams and O365 groups. Hope this information will help someone.

Thursday, November 5, 2020

Call WebExtensions.WebExistsFullUrl method from OfficeDevPnP library for different site collection

Few years ago I wrote about one problem in OfficeDevPnP method WebExtensions.WebExistsFullUrl: shortly when it was called with url which belongs to non-existent site collection from different managed path it returned true. Full description of the problem is available here: How to check does site collection exist by absolute url using CSOM in Sharepoint. Also I posted issue to PnP-Sites-Core in github: WebExtensions.WebExistsFullUrl returns true for non-existent sites from different managed path in Sharepoint 2013 on-premise. I checked this issue with the latest PnP version (which is 3.26.2010 at the moment of writing of this article) and found that this problem is fixed now by MS. I.e. code of WebExtensions.WebExistsFullUrl method is still the same:

public static bool WebExistsFullUrl(ClientRuntimeContext context, string webFullUrl)
{
    bool exists = false;
    try
    {
        using (ClientContext testContext = context.Clone(webFullUrl))
        {
            testContext.Load(testContext.Web, w => w.Title);
            testContext.ExecuteQueryRetry();
            exists = true;
        }
    }
    catch (Exception ex)
    {
        if (IsUnableToAccessSiteException(ex) || IsCannotGetSiteException(ex))
        {
            // Site exists, but you don't have access .. not sure if this is really valid
            // (I guess if checking if URL is already taken, e.g. want to create a new site
            // then this makes sense).
            exists = true;
        }
    }
    return exists;
}

but now when we try to clone ClientContext in this line:

ClientContext testContext = context.Clone(webFullUrl))

and webFullUrl corresponds to non-existent site collection from another managed path (e.g. if context was created from the root site collection http://example.com and we pass webFullUrl = http://example.com/sites/som-non-existent-url) it throws System.Exception (System.Net.WebException) now:

The remote server returned an error: (404) Not Found

while in earlier CSOM version it created ClientContext for the root site in this case. And as result WebExtensions.WebExistsFullUrl returns false as expected. So fortunately issue was fixed and we can call this method for checking existence of different site collections.