Monday, June 19, 2017

Procedure to restore SharePoint 2013 access apps in the same farm from database without impacting other apps

In previous blog, I’ve provided the procedure to restore SharePoint 2013 access apps after deleted in the same farm from database backups. The approach is to overwrite all the four databases including site content, access app, app management service, and secure store services. The issue for that process is it will overwrite all the whole app management and secure store services database. As a result, any new or updated app might be impacted. For example, the newly added access will not be recover after this process.

In this article, I’ll provide a different way to restore SharePoint 2013 site with access apps. However, sicne this involves database insertion, this might not be supported by Microsoft SharePoint support contract. Please contact your Microsoft support before using the approach!!!


Before we explain the procedure to restore SharePoint 2013 site with access apps in the same farm, let’s create a team site with an access app. The site has the following url “http://spsbx15/sites/APP-DR” and the Access App is named “Harry-APP-Testing” as out of box Customers table. Before we delete the access app “Harry-APP-Testing” and start the restore, let's complete the preparation steps. We will need all this information during the restore.

1. Preparation step #1, we will need to get the access apps App Ids from the site collection. You could use the following Powershell.

         $appInstances = Get-SPappinstance -web $siteUrl

        if($appInstances -ne $null)
        { 
                foreach ($eachAppInstance in $appInstances)
                {        
                    $title = $eachAppInstance.Title
                    $version = $eachAppInstance.App.VersionString
                    $AppPrincipalId = $eachAppInstance.AppPrincipalId
                    $Id = $eachAppInstance.Id
                    $Status = $eachAppInstance.Status
                    $AppWebFullUrl = $eachAppInstance.AppWebFullUrl

                    Write-Output "$title; $version; $Id; $AppPrincipalId; $Status; $AppWebFullUrl"| Out-File $reportName -append 
                    Write-Output $eachAppInstance
    
                }
        } 

The result is listed below and please record the App Id.
  • Site Url                 http://spsbx15/sites/APP-DR
  • App Name            Harry-APP-Testing
  • App Id                  ddbe8814-5cdf-48a4-9322-a53cad392c17
  • App Type             Access App

2. Preparation step #2, we will need to get the access apps ReferenceIds, AppInstallationId from the site collection. You could use the following SQL query on the site content DB.

SELECT TOP 1000 [AppInstallationId]
      ,[DatabaseName]
      ,[ReferenceId]
      ,[TargetAppId]
      ,[AppSource]
      ,[SiteId]
  FROM [WSS_Content_APP-DR].[dbo].[AppDatabaseMetadata]

The result is listed below and please record the App ReferenceId. The AppInstallationId,  DatabaseName, and TargetAppId will also be used in other restore steps.
  • AppInstallationId  DDBE8814-5CDF-48A4-9322-A53CAD392C17
  • DatabaseName      db_ddbe8814_5cdf_48a4_9322_a53cad392c17
  • ReferenceId           0C904934-D29E-48A2-893E-C37472CB07AD
  • TargetAppId          AppDBCredentials_ddbe8814_5cdf_48a4_9322_a53cad392c17
  • AppSource            4
  • SiteId                        A44B0A1A-0FF0-4470-9D43-40DB0C6891CE

3. Preparation step #3, we will need to get the access apps secure store entries from the secure store service DB. You could use the following SQL query on the secure store service DB.

SELECT TOP 1000 [ApplicationId]
      ,[PartitionId]
      ,[ApplicationName]
      ,[FriendlyName]
      ,[ApplicationType]
      ,[TicketTimeout]
      ,[ContactEmail]
      ,[CredentialManagementUrl]
FROM [SVC_SecureStore].[dbo].[SSSApplication]
Where PartitionId = '0C904934-D29E-48A2-893E-C37472CB07AD'  

Please note the PartitionId is the ReferenceId form step #2. The result is listed below.

ApplicationId                                 C5FD28F7-41A9-4980-8F94-4EC1D4E478BF
PartitionId                                      0C37852B-34D0-418E-91C6-2AC25AF4BE5B
ApplicationName                           AppDBCredentials_ddbe8814_5cdf_48a4_9322_a53cad392c17
FriendlyName                                Credentials for App instance 'ddbe8814-5cdf-48a4-9322-a53cad392c17'
ApplicationType                             5
TicketTimeout                                NULL
ContactEmail                                  admin@admin.com
CredentialManagementUrl             NULL

4. Preparation step #4, we will need to get the access apps different entries from the app management store service DB. You could use the following SQL query on the secure store service DB.

4.1 Get AM_AppPrincipalAppInstances entries using the following SQL query.

SELECT TOP 1000 [CompositePartitionKey]
      ,[AppInstanceId]
      ,[ProductId]
      ,[AssetId]
      ,[ContentMarket]
      ,[AppSource]
 FROM [SVC_APPS].[dbo].[AM_AppPrincipalAppInstances]
 WHERE AppInstanceId ='DDBE8814-5CDF-48A4-9322-A53CAD392C17'

The AppInstanceId is from the step#2. The result is listed below.

CompositePartitionKey 0x2B85370CD0348E4191C62AC25AF4BE5B0049003A00300049002E0054007C004D0053002E00530050002E0049004E0054007C00370032003700370041003900410032002D0034003000420041002D0034003000450038002D0042003500420033002D004300450038004500360046003900350039003700320042004000390038004500390042004100380039002D0045003100410031002D0034004500330038002D0039003000300037002D00380042004400410042004300320035004400450031004400
AppInstanceId               DDBE8814-5CDF-48A4-9322-A53CAD392C17
ProductId                       C181CBB8-0474-41C3-8C3C-6C86962E497D
AssetId                          NULL
ContentMarket              NULL
AppSource                    4

4.2 Get AM_AppPrincipals entries using the following SQL query.

SELECT TOP 1000 [CompositePartitionKey]
      ,[Title]
      ,[RedirectUrl]
      ,[Realm]
      ,[Flag]
      ,[AppInstanceId]
      ,[DeploymentData]
      ,[DelegateAppPartitionKey]
  FROM [SVC_APPS].[dbo].[AM_AppPrincipals]
 WHERE Title = 'Harry-APP-Testing'

Please note the Title is the "App Name" from step #1. Be aware the same app names in the farm. In this case, you need to compare the CompositePartitionKey with the value from step 4.1. The result is listed below.

CompositePartitionKey 0x2B85370CD0348E4191C62AC25AF4BE5B0049003A00300049002E0054007C004D0053002E00530050002E0049004E0054007C00370032003700370041003900410032002D0034003000420041002D0034003000450038002D0042003500420033002D004300450038004500360046003900350039003700320042004000390038004500390042004100380039002D0045003100410031002D0034004500330038002D0039003000300037002D00380042004400410042004300320035004400450031004400
Title                                             Harry-APP-Testing
RedirectUrl                                 access:AuthRequestComplete
Realm                                          NULL
Flag                                              0
AppInstanceId                           NULL
DeploymentData                      NULL
DelegateAppPartitionKey       NULL


4.3 Get AM_ProductOAuthRegistration entries using the following SQL query.

SELECT TOP 1000 [CompositePartitionKey]
      ,[AppId]
      ,[AppInstanceId]
FROM [SVC_APPS].[dbo].[AM_ProductOAuthRegistration]
WHERE AppInstanceId = 'DDBE8814-5CDF-48A4-9322-A53CAD392C17'

Please note the AppInstanceId is the value from step #2. The result is listed below.

CompositePartitionKey  0x2B85370CD0348E4191C62AC25AF4BE5B01B8CB81C17404C3418C3C6C86962E497D
AppId                      i:0i.t|ms.sp.int|7277a9a2-40ba-40e8-b5b3-ce8e6f95972b@98e9ba89-e1a1-4e38-9007-8bdabc25de1d
AppInstanceId         DDBE8814-5CDF-48A4-9322-A53CAD392C17

Now, we can delete the access app and start to restore the access app along with the site collection. Some steps are similar to we discussed in previous article.

1. Restore the access app logins - see previous blog.
2. Restore the access database
3. Restore the site collection content DB
4. Insert the entry from step #3 to secure store service database
5. Insert multiple entries from step #4 to three app management service database

This way, you should have the access app restored along with site collection in the same farm. At meantime, since we are not overwriting the whole secure store or app management services, instead  inserting entries related to the specific access app, this approach will restore only the access app deleted without impacting other apps!

Since we are query SharePoint databases and insert data into both secure store and app management databases, this might violate Microsoft SharePoint support contract. Be aware NOT to sue approach before consulting with your Microsoft support team.



Thursday, June 15, 2017

Procedure to restore SharePoint 2013 site with access apps in the same farm from database backups

In March 2017, Microsoft announced that they will no longer recommend Access Services for new apps and web databases. When Access Services in SharePoint is first introduced in SharePoint 2013, the mission was to enable both information workers and developers to quickly create data eccentric web applications with little or no programming. Over the last several years it has become clear that the needs of our customers have grown beyond the scope of what Access Services can offer. One of the major issue we are facing is one of our  Access Service App is bigger that could not be packaged as app package. We are not be able to make any changes that could be saved or packaged. The worst case is there is no disaster recover procedure we could  recover the Access Service App along with the site collection.


Although Microsoft is recommending Microsoft PowerApps as alternative that offers a comprehensive set of application building tools, connection to custom web APIs, and a wide array of database options including SharePoint lists, SQL Azure databases, Common Data Service and third-party data sources, there is no clear way to convert existing Access Service App. While we are migrating existing Access Service Apps, we still need to support the current Access Service Apps in production. In this article, I’ll describe the way how you could restore the Access Service Apps from database backups along with the site collections using Microsoft way. You could use app package as access app backup and restore if the app is small enough to be saved as .app package. In different article, I’ll also provide a way that might not be supported by Microsoft but for your reference.

Before we explain the procedure to restore SharePoint 2013 site with access apps in the same farm, let’s create a team site with an access app. The site has the following url “http://spsbx15/sites/APP-DR” and the Access App is named “Harry-APP-Testing” as out of box Customers table. The disaster recover methods are different different scenarios of the site with access app restore.

Here is the summery of the site collection and farm information needed for restore. I'll explain the details how to get this information in the following sessions.

  • Site collection  URL                  http://spsbx15/sites/APP-DR
  • Site collection DB                  WSS_Content_APP-DR
  • Access App                            Harry-APP-Testing
  • Access App DB                      db_ddbe8814_5cdf_48a4_9322_a53cad392c17
  • App manager service DB        SVC_APPS
  • Security Store service DB       SVC_SecureStore
  • Access App logins                    db_ddbe8814_5cdf_48a4_9322_a53cad392c17_dbo 
                                                         db_ddbe8814_5cdf_48a4_9322_a53cad392c17_custom
                                                         db_ddbe8814_5cdf_48a4_9322_a53cad392c17_ExternalWriter

All the SharePoint components related to access app for the site collection and the relationships are illustrated in the below diagram.



1. The first scenario is the site collection content corrupted or deleted, we want to recover the site along with Access App. 

In order to test this scenario, we delete the site collection “http://spsbx15/sites/APP-DR”. Here is the way to restore.
  • Get the site content database WSS_Content_APP-DR from backup
  • Restore the content database to SharePoint SQL database
  • Mount the database using the Powershell

         Mount-SPContentDatabase WSS_Content_APP-DR -DatabaseServer spsbxsql15 -WebApplication        
         http://spsbx15

If the site collection had been just deleted within few hours and the SharePoint daily graduate site deletion timer job has not started (~6AM), you can quickly restore the site using the following steps.

        # Get the site GUID using Powershell. Record the site GUID
        Get-spdeletedsite -webapplication http://spsbx15

        # Restore the site using Powershell by passing the site GUID
        Restore-SPDeletedSite -Identity 610857cb-8414-4a89-8bf3-ad3628f6c86c


2. The second scenario Access App content corrupted, we want to restore the Access App to the same site. Here are the steps.

         Get the Access App database from backup. Please note the naming conversion to the Access App DB
         Restore the Access App database like “db_ddbe8814_5cdf_48a4_9322_a53cad392c17”


3. The third scenario is Access App deleted, we want to restore the Access App to the same site. Here are the steps before and after the Access App deletion.

As daily SharePoint back up process, please back up the following databases and logins.
  • Back up the Access App logins daily using the script provided by Microsoft.
  • Back up the site collection databases
  • Back up the access app databases
  • Back up the app manager service database
  • Back up security store service database
Whence we need to restore the site collection with access app, here is the procedure.
  • Restore the access logins using the script provided by Microsoft. The logins will be recreated with same SID and passwords. The logins are prefixed as "db_" and then access app ID. db_ddbe8814_5cdf_48a4_9322_a53cad392c17_dbo, db_ddbe8814_5cdf_48a4_9322_a53cad392c17_custom, db_ddbe8814_5cdf_48a4_9322_a53cad392c17_ExternalWrite
  • Restore the access app database db_ddbe8814_5cdf_48a4_9322_a53cad392c17
  • Restore the app manager service database SVC_APPS. This can be done when SharePoint is running.
  • Restore the security store database SVC_SecureStore. You need to stop IIS  by IISRESET /stop before the database restore.
  • Restore the site collection database WSS_Content_APP-DR and mount the site again
The last step to restore the site collection is tricky since the database cannot be restored if the current database is still be used. Here is the way to do that.

  • Delete the site collection from CA
  • Remove the deleted site from pool using Powershell
           get-spdeletedsite -webapplication http://spsbx15 | Remove-SPDeletedSite 

  • Run “Gradual Site Deletion” immediately to delete the sites that were marked for deletion 
  • Close any browser hitting the site, close all SQL query using the database
  • Conduct a IISRESET
  • Delete the site collection content database from SQL - You may still need to try few time until all connections dropped to the database
  • Restore the previous site collection content database WSS_Content_APP-DR 
  • Mount the database to SharePoint using Powershell
       Mount-SPContentDatabase WSS_Content_APP-DR -DatabaseServer spsbxsql15 
       -WebApplication http://spsbx15

Now you have the site collection along with working access app from previous back up!

Please note there are potential issues for the third scenario. The restore will overwrite the entire app manager service and security store service!  What will be impacted? Here are the potential risks you need to manage.

  1. If new access apps have been added to some site during the time, these will NOT be recovered. These access app will be orphan on the sites!
  2. If new security store entry has been added or existing security entry has been modified, these will NOT be recovered. You will have previous values!

Since we will disable access app creation, we can eliminate the risk #1. We control the security store entry update and have Powershell script to retrieve the entries, we can eliminate the risk #2. However, if you like my access restore procedure, please be aware the risks.

At this time, you might ask, is there anyway we could recover the site along with access without overwrite the entire app management service and security store service?  The answer is YES! I'll provide the details in another blog. However, that approach will involve SQL database insert to both app management service and security store service databases. This seems to be unsupported by Microsoft.

I'm working with Microsoft to see if there is anyway we can restore app and site without overwrite the app management service and security store service.