Applying PnP Provisioning template with Azure Functions/Powershell - azure

I'm currently trying to develop a Flow which creates a SharePoint site and then utilizes an Azure Function to provision said site with a selection of libraries and such.
The Flow itself is pretty straight forward, but the bit I'm struggling with is the Azure Function itself, particularly the authentication; It uses a Connect-PnPOnline cmdlet, and with our tenant using MFA I've had a bit of difficulty getting around it - I've created a Service Principal User which at the very least has enabled me to connect to the site, but I still can't actually use Apply-PnPProvisioningTemplate, nor any other PnP commands really - when I try and do so, I get:
"The remote server returned an error: (403) Forbidden."
My Service Principal user has Contribute permissions, and a scope of Sites.FullControl.All, so I'm not sure where I'm going wrong.
See below the Powershell code - I don't think the issue is really arising from there but it can't hurt to show:
$requestBody = Get-Content $req -Raw | ConvertFrom-Json
"destination": "SharePointSiteURL"
$destination = $requestBody.destination
$secpasswd = ConvertTo-SecureString $env:pass -AsPlainText -Force
$mycreds = New-Object System.Management.Automation.PSCredential ($env:user, $secpasswd)
Connect-PnPOnline -url $destination -AppID $env:user -AppSecret $env:pass
Apply-PnPProvisioningTemplate -path "D:\home\site\wwwroot\template.xml"
Out-File -Encoding Ascii -FilePath $res -inputObject "Done $destination"
I should note that this is actually my first time using Azure Functions so forgive me if the solution here is quite simple! Any help would be appreciated.

Referring to MSDN Thread
https://social.msdn.microsoft.com/Forums/en-US/53629265-47da-41f7-b780-35eaba999f73/applying-pnp-provisioning-template-with-azure-functionspowershell?forum=AzureFunctions
This post work https://www.sharepointfire.com/2018/04/sharepoint-online-pnp-site-provisioning-using-flow-and-azure-function/

Related

how do I retrieve the password from the MicrosoftGraphPasswordCredential object

I have to update a Script which should create an application in Azure and subsequently use it to traverse resources.
Among the commands to update is to create a credential for the application created.
$AppSPN = New-AzADServicePrincipal -DisplayName "Move_Validation_SPN"
subsequently I need to use a credential to traverse the resources, according to the same Microsoft documentation, it can be created like this:
$creds = New-Object `
-TypeName "Microsoft.Azure.PowerShell.Cmdlets.Resources.MSGraph.Models.ApiV10.MicrosoftGraphPasswordCredential" `
-Property #{ 'DisplayName' = $name; 'StartDateTime' = $startDate; 'EndDateTime' = $endDate }
New-AzADAppCredential -ApplicationId $AppSPN.appId -PasswordCredentials #creds
Here comes the question, when I create a Token, how do I retrieve the password from the MicrosoftGraphPasswordCredential object? which is: $creds
$Token = Get-Token -TenantId $TenantId -SubscriptionID $SourceSub.Id -ApplicationID $AppSPN.appID -ApplicationKey $creds
From version 6.6.0, there are breaking changes in this cmdlet New-AzADAppCredential.
As mentioned in this MS Doc, Az PowerShell cmdlets module moved from Azure AD Graph to Microsoft Graph. So, it is better to use the cmdlet of New-AzureADApplicationPasswordCredential.
Workaround:
As mentioned here, there should be a mistake in the official doc, in the example, it uses the New, not Get.If you try New, it appears like the doc.
Source: New-AzureADApplicationPasswordCredential

How to revert to classic authentication for Azure Function App

I've been following various tutorials on Azure B2C authentication and none of them are updated to use the new "authentication experience" within the function app settings. As someone just trying to set up a basic test, this has proven very frustrating as it's not clear what to fill in since some of the terminology and settings the tutorials say to use don't exist (or possibly have a different name) in the new authentication experience. Anyway, just for the sake of diagnosing some authentication issues I'm having, I wanted to try using the classic auth experience. However I don't seem to be able to do that. I tried deleting my identity provider in the new auth experience as well as setting allow unauthenticated access for auth settings, but I still don't seem to be able to revert back to the classic setttings.
Is there a way to delete my new auth experience and revert back to classic? I just want to diagnose where I'm going wrong with my test and this is the only area where I wasn't able to follow the tutorial 1 to 1. Thanks.
Please follow the below steps:-
Connect-AzAccount
$tenantId = (Get-AzContext).Tenant.Id
Password based authentication
$sp = New-AzADServicePrincipal -DisplayName ServicePrincipalName
$sp.secret | ConvertFrom-SecureString -AsPlainText
$pscredential = Get-Credential -UserName $sp.ApplicationId
Connect-AzAccount -ServicePrincipal -Credential $pscredential -Tenant $tenantId
For automation scenarios, you need to create credentials from a service principal's applicationId and secret:
$pscredential = New-Object -TypeName System.Management.Automation.PSCredential($sp.ApplicationId, $sp.Secret)
Connect-AzAccount -ServicePrincipal -Credential $pscredential -Tenant $tenantId

unable to connect azure automation and exchange online

I'm receiving this error when attempting to connect to Exchange online when using a service account from my automation account. I think the problem may also be that my $credential variable is not passing into my $session variable, but I can't think of any reason why that would be happening.
Error :
New-PSSession : [outlook.office365.com] Connecting to remote server outlook.office365.com failed with the following
error message : Access is denied. For more information, see the about_Remote_Troubleshooting Help topic.
At line:5 char:12
$session = New-PSSession -ConfigurationName Microsoft.Exchange -Conne ...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CategoryInfo : OpenError: (System.Manageme....RemoteRunspace:RemoteRunspace) [New-PSSession],
PSRemotingTransportException
FullyQualifiedErrorId : AccessDenied,PSSessionOpenFailed
Import-PSSession : Cannot validate argument on parameter 'Session'. The argument is null. Provide a valid value for the
argument, and then try running the command again.
At line:6 char:42
Import-Module (Import-PSSession -Session $session -DisableNameCheckin ...
~~~~~~~~
Script :
Param (
[string] $Employee = ""
)
$credential = Get-AutomationPSCredential -Name 'admin#crafthub.onmicrosoft.com'
$session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri 'https://outlook.office365.com/powershell-liveid/' -Credential $credential -Authentication Basic -AllowRedirection
Import-Module (Import-PSSession -Session $session -DisableNameChecking -AllowClobber) -Global
$mailbox = Get-Mailbox -Identity $Employee
Write-Output $mailbox
Help will be highly appreciated
Yes, it looks like $credential variable is not passing into $session variable.
In your code you have given Azure Automation credential name as "admin#crafthub.onmicrosoft.com" so double check if you have created Azure Automation credential with the exact name "admin#crafthub.onmicrosoft.com" or not.
You may already be aware but just letting you know that you have to provide Office 365 service account's credentials when you create an Azure Automation credential. To create Azure Automation credential, goto Azure Portal -> Your Azure Automation Account -> 'Credentials' tile -> Click on '+ Add a credential' -> Provide a name for Azure Automation credential under 'Name', provide Office 365 service account's name under 'User name', provide Office 365 service account's password under 'Password' and 'Confirm password' -> Click on 'Create'.
Then, provide the name of that Azure Automation credential in your code's Get-AutomationPSCredential command line i.e., $credential = Get-AutomationPSCredential -Name '<Above_Provided_Azure_Automation_Credential_Name>'
If you have already done all this without any issues then I would recommend you to try latest "Exchange Online PowerShell V2" way i.e., import "ExchangeOnlineManagement" Azure Automation module as shown below and then to connect, use Connect-ExchangeOnline cmdlet instead of New-PSSession cmdlet. Later, as you are trying to get mailbox details so use Get-EXOMailbox cmdlet instead of Get-Mailbox cmdlet. For more information w.r.t it, refer this document.

Azure Powershell Function App Reading Content From Data Lake Gen 1

I would be very grateful for any assistance with this problem.
All I am trying to do is use a simple Azure function app using Powershell to read a file ("/input/specimen.json") in from my data lake, work with it, then eventually write it back out to the lake. I'm stuck already.
Here is the relevant code from the function app:
# The below line is at the very top of the function app run.ps1
using namespace System.Management.Automation.PSCredential
# The lines below are in the main area of the function app which are called.
$path = "/input/specimen.json"
$account = "mydatalake"
$tenant = "<my-tenant-id>"
$user = "<application/client id>"
$pass = "<client secret>"
$password = ConvertTo-SecureString $pass -AsPlainText -Force
$cred = New-Object -TypeName System.Management.Automation.PSCredential -argumentlist $user,$password
connect-azaccount -credential $cred -tenant $tenant -ServicePrincipal
$data = Get-AzDataLakeStoreItemContent -accountname $account -path $path
write-host $data
$body = $data | out-string
disconnect-azaccount
The output from the function app is:
2020-06-04T19:49:09Z [Error] ERROR: Get-AzDataLakeStoreItemContent
: Error opening a Read Stream for file /stan/interests.json.
Operation: GETFILESTATUS failed with HttpStatus:Forbidden
RemoteException: AccessControlException GETFILESTATUS failed with
error 0x83090aa2 (Forbidden. ACL verification failed. Either the
resource does not exist or the user is not authorized to perform the
requested operation.). [a6cfab98-149a-46eb-8cb6-bd0a40a11796] failed
with error 0x83090aa2 (Forbidden. ACL verification failed. Either the
resource does not exist or the user is not authorized to perform the
requested operation.).
[a6cfab98-149a-46eb-8cb6-bd0a40a11796][2020-06-04T12:49:08.1314705-07:00]
JavaClassName: org.apache.hadoop.security.AccessControlException.
The error reeks of ACLS and permissions, but I have set up a Service Principal to use for the 'connect-azaccount' and have made that SP both a Contributor and Owner of the data lake, but still get the same errors. I'm reasonably certain that the SP I am using IS being used to authenticate because the Function App logs show the created session being echoed out to the host with the correct tenant and client id.
This is beginning to drive me crazy. What else do I need to get this to work? Could there be other roles or permissions needed? Is there a better way to do this?
Any and all assistance would be greatly appreciated - thanks in advance.
If you want to use the service principal to access Azure data lake gen1 file, we need to configure ACL fro the sp. For more details, please refer to the document.
The ACL for Azure data lake gen1 has three permissions. There are Read, Write, and Execute. For more details, please refer to the docuemnt.
For example, we want to read file /Oregon/Portland/Data.txt, we need to configure ACL as below
Regarding how to configure it, we can do that on Azure Portal

Running New-AzureRmResourceGroupDeployment from within a Function App

I need to wire up a stateless worker ad-hoc to perform a long running job based off a user action that self destructs when its done. I am trying to run New-AzureRmResourceGroupDeployment from within a PoSh Function App and cannot figure out how to authenticate to Azure from within the PoSh script.
I tried this:
$accountName = "myID#mydomain.com"
$pwd = ConvertTo-SecureString "password" -AsPlainText -Force
$cred = new-object PSCredential($accountName, $pwd)
Add-AzureRmAccount -Credential $cred
New-AzureResourceGroupDeployment -ResourceGroupName yadda yadda
And I get an error message that I need to use an Organization ID (which I am, our Azure AD is federated and we use AD Sync (and SiteMinder w/o WS-* if that matters)):
Add-AzureRmAccount : -Credential parameter can only be used with Organization ID credentials. For more information, please refer to http://go.microsoft.com/fwlink/?linkid=331007&clcid=0x409 for more information about the difference between an organizational account and a Microsoft account.
I tried "Login-AzureRMAccount -Credential $cred" with similar results.
If I do the Add- or Login- cmdlets from a PoSh window on my local machine (which is member joined to AD) with the -Credential flag I get a similar error. If I run the cmdlets without the credential I am prompted for credentials through an interactive ID/PW window (I do not have to enter my password once I type in my ID).
Does anyone know how I can do the authentication? I would be okay with authenticating like above, some sort of pass through credential from our web layer, or even an Option C I don't know about.
You will need to use service principal for authentication. A sample with instructions can be found here.
Azure Function role like permissions to Stop Azure Virtual Machines
For that you would need to use Service Principal auth. I don't think there is any sense of copypasting Azure Doc's to this answer, just consult this document:
https://learn.microsoft.com/en-us/azure/azure-resource-manager/resource-group-authenticate-service-principal

Resources