Publish Lambda Function in AWS - powershell

I am attempting to publish a new Lambda function if it doesn't already exist. The Update seems to be working great, and I can update it at will. However when I try to do the Publish command I keep getting the error Member must not be null
$zipFilePath = "E:\ProductName-Dev\release.zip"
$zipFileItem = Get-Item -Path $zipFilePath
$fileStream = $zipFileItem.OpenRead()
$memoryStream = New-Object System.IO.MemoryStream
$fileStream.CopyTo($memoryStream)
$cmdOutput = Get-LMFunction -FunctionName new-extract;
try{
if($?) {
"lambda function already in AWS"
Update-LMFunctionCode -FunctionName new-extract -ZipFile $memoryStream -Publish 1
} else {
"need to publish new lambda function"
Publish-LMFunction -FunctionName new-extract -FunctionZip $zipFilePath -Handler exports.handler -Role arn:aws:iam::0000000:role/my-extract -Region us-east-1
}
}
finally {
$fileStream.Close()
}
If I run the Publish-LMFunction without all of the parameters and enter things manually I still get the error. Is there something obvious I'm messing? I believe I have all 4 required fields added to my Publish function. I can also create these within the webconsole, so I don't think it's a credentials issue.

I was simply missing the Runtime parameter
Publish-LMFunction -FunctionName $FunctionName -FunctionZip $zipFilePath -Handler exports.handler -Role arn:aws:iam:$AccountNumber:role/$RoleName -Region $Region -Runtime nodejs4.3
Their documentation shows it as required but when you are writing in the Powershell ISE it does not put an asterisk by the field.

Related

PowerShell connect & append data to GoogleSheet

**Problem I am trying to solve: **
We want to be notified whenever one of our kiosk machines restart due to a Windows Update, so we can remotely connect right away and reset them to the desired state.
After trying different options (i.e. send email via SMTP triggered by an event via Task Scheduler, which proved unreliable due to script taking too long before restart occurs), this is the next attempted solution (perhaps it occurs faster?).
**Current solution attempted: **
Write data to a GoogleSheet via PowerShell script (below), triggered via Task Scheduler when a specific event occurs (i.e. Event Id: 1074). From there, GoogleSheet can easily send us the notification we want using Apps Script (details not relevant for this post).
Import-Module UMN-Google
# Set security protocol to TLS 1.2 to avoid TLS errors
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
# Google API Authozation
$scope = "https://www.googleapis.com/auth/spreadsheets https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/drive.file"
$certPath = "C:/Scripts/GoogleService/my-cert-path.p12"
$iss = 'name#projectname.iam.gserviceaccount.com'
$certPswd = 'mypassword'
try {
$accessToken = Get-GOAuthTokenService -scope $scope -certPath $certPath -certPswd $certPswd -iss $iss
} catch {
$err = $_.Exception
$err | Select-Object -Property *
"Response: "
$err.Response
}
$accessToken
# Define the GoogleSheet and the target Sheet
$spreadSheetID = 'google-sheet-id-i-omitted-from-this-sample'
$sheetName = 'MachineActivityData'
$EventId = 1074
$A = Get-WinEvent -MaxEvents 1 -FilterHashTable #{Logname = "System" ; ID = $EventId }
$Message = $A.Message
$EventID = $A.Id
$MachineName = $A.MachineName
$Source = $A.ProviderName
# Set the arrayValues
$arrayValues = #($MachineName, $Source, $EventId)
$appendValue = 'Append'
# Write to GoogleSheet (appending data)
Set-GSheetData -accessToken $accessToken -append $appendValue -sheetName $sheetName -spreadSheetID $spreadSheetID -values $arrayValues
Issue encontered:
When running the above script, I get the following error:
Set-GSheetData : A positional parameter cannot be found that accepts argument 'Append'.
At C:\Scripts\script_GoogleSheetConnection.ps1:40 char:1
+ Set-GSheetData -accessToken $accessToken -append $appendValue -sheetN ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Set-GSheetData], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Set-GSheetData
As you can see, I am using UMN-Google. This documentation helps, but I couldn't find much more than this to help with this error.
This error has something to do with the -append value not being correct.
Per the linked documentation, it appears to be a string (as in the example, and function definition). But I tried other options as well (i.e. bool...).
Any idea why the function Set-GSheetData is not accepting this parameter?
Quick note, I am fairly new to using PowerShell. I appreciate any suggestions.
Thank you kindly,
I tried the above script, and expected data to be appended to the specified GoogleSheet. However, the function Set-GSheetData returned an error, as a parameter is invalid. Per documentation, the parameter I entered is correct.

Create azure dynamic group from azure functions powershell

I am trying to create an azure function that has to create azure dynamic group when i execute the function from MS flow. I am using below code for this purpose.
$groupName = $Request.Query.Name
$groupDesc = $Request.Query.Desc
$domainnames = $Request.Query.DomainName
$dynamicrule = ""
Foreach($domainname in $domainnames.Split(";"))
{
$dynamicrule = $dynamicrule + "(user.userPrincipalName -contains ""_$domainname"") or";
}
$dynamicrule = $dynamicrule -replace ".{2}$"
$dynamicrule = $dynamicrule + "and (user.objectId -ne null)";
New-AzureADMSGroup -DisplayName $groupName -Description $groupDesc -MailEnabled $False -MailNickName "group" -SecurityEnabled $True -GroupTypes "DynamicMembership" -MembershipRule $dynamicrule -MembershipRuleProcessingState "On"
When i execute the above command, i am getting below error messgae.
ERROR: The term 'New-AzureADMSGroup' is not recognized as the name of a cmdlet, function, script file, or operable program.Check the spelling of the name, or if a path was included, verify that the path is correct and try again.Exception :Type : System.Management.Automation.CommandNotFoundExceptionErrorRecord
Can sombody please help me on how can i create dynamic groups using azure function app.
Thanks,
Venu
From the error message, you did not install AzureAD powershell module in your function app. And if you want to create a dynamic group, you need to use the -MembershipRule parameter, it is just available in the preview version i.e. AzureADPreview module. Though the doc looks like the parameter is available in AzureAD, but per my test, it is not available.
Actually it is easy to solve the issue, but if you want to create a dynamic group with New-AzureADMSGroup, there will be a few follow-up issues, you could follow the steps below.
1.Navigate to the function app in the portal -> Identity -> enable the system-assigned identity(MSI) for your app.
2.Navigate to App files -> host.json -> make sure the managedDependency is Enabled.
{
"version": "2.0",
"managedDependency": {
"Enabled": true
},
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[1.*, 2.0.0)"
}
}
In the requirements.psd1, add the AzureADPreview like below, then it will install the AzureADPreview module for you automatically.
#{
'Az' = '5.*'
'AzureADPreview' = '2.0.2.129'
}
In the profile.ps1, remove all the things and add the lines below, this is used to solve the issue related to AzureAD powershell in function, without it, you will get an error, details here.
$64bitPowerShellPath = Get-ChildItem -Path $Env:Windir\WinSxS -Filter PowerShell.exe -Recurse -ErrorAction SilentlyContinue | Where-Object {$_.FullName -match "amd64"}
$env:64bitPowerShellPath=$64bitPowerShellPath.VersionInfo.FileName
3.If you want to use New-AzureADMSGroup to create group in Azure AD, you need the permission in Microsoft Graph, in this case, we use MSI to auth, so use the commands below to give the permission to your MSI.
Run the commands below in local with the Global admin user account, replace <functionapp-name>:
Connect-AzureAD
$MSI = (Get-AzureADServicePrincipal -Filter "displayName eq '<functionapp-name>'")
$MSGraphAppId = "00000003-0000-0000-c000-000000000000"
$GraphServicePrincipal = Get-AzureADServicePrincipal -Filter "appId eq '$MSGraphAppId'"
$PermissionName = "Group.ReadWrite.All"
$AppRole = $GraphServicePrincipal.AppRoles | Where-Object {$_.Value -eq $PermissionName -and $_.AllowedMemberTypes -contains "Application"}
New-AzureADServiceAppRoleAssignment -ObjectId $MSI.ObjectId -PrincipalId $MSI.ObjectId -ResourceId $GraphServicePrincipal.ObjectId -Id $AppRole.Id
4.After step 2, navigate to the kudu(in the Advanced Tools blade of the function app) -> data -> ManagedDependencies -> click the file with the format like 201208083153165.r(choose the newest one via the Modified time) -> check if the AzureADPreview module was installed successfully like below.
5.After the module was installed, in your function code, use the lines below, in my sample, I use this sample to test directly, you could change the code depends on your requirements, remember to replace 201208083153165.r with yours in step 4, it works fine on my side.
using namespace System.Net
# Input bindings are passed in via param block.
param($Request, $TriggerMetadata)
# Write to the Azure Functions log stream.
Write-Host "PowerShell HTTP trigger function processed a request."
# Interact with query parameters or the body of the request.
$name = $Request.Query.Name
if (-not $name) {
$name = $Request.Body.Name
}
$body = "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."
if ($name) {
$body = "Hello, $name. This HTTP triggered function executed successfully."
}
$script = {
if ($env:MSI_SECRET) {
Disable-AzContextAutosave -Scope Process | Out-Null
Connect-AzAccount -Identity
}
$context = Get-AzContext
$graphtoken = (Get-AzAccessToken -ResourceUrl "https://graph.microsoft.com").Token
$aadtoken = (Get-AzAccessToken -ResourceUrl "https://graph.windows.net").Token
Import-Module D:\home\data\ManagedDependencies\201208083153165.r\AzureADPreview
Connect-AzureAD -AccountId $context.Account -TenantId $context.Tenant -MsAccessToken $graphtoken -AadAccessToken $aadtoken
New-AzureADMSGroup -DisplayName "joyd1" -Description "Dynamic group created from PS" -MailEnabled $False -MailNickName "group" -SecurityEnabled $True -GroupTypes "DynamicMembership" -MembershipRule "(user.department -contains ""Marketing"")" -MembershipRuleProcessingState "On"
}
&$env:64bitPowerShellPath -WindowStyle Hidden -NonInteractive -Command $Script
# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]#{
StatusCode = [HttpStatusCode]::OK
Body = $body
})
Check the group in the portal:

Error when executing PowerShell script for SharePoint Online

So, i'm trying to run this SPO PowerShell script that microsoft provides in this link:
https://learn.microsoft.com/en-us/powershell/module/sharepoint-online/export-spouserinfo?view=sharepoint-ps on the "example 2". However, when i try to run the script on PowerShell ISE, i get the following error: "Parameter missing for 'Output Folder' argument. Specify a 'System.String' type parameter and try again." I tried to change the arguments, input my site collection, creating a .csv file on the folder, but nothing changes this error message, what am i doing wrong?
Here is the code i'm using:
$sites = Get-SPOSite -IncludePersonalSite $true
$user = "xxxxxx#domain.com"
foreach ($site in $sites)
{
Export-SPOUserInfo -LoginName $user -site $site.Url -OutputFolder
"D:"
}
Thanks in advance!
Writing to the root of a drive is really not a best practice. Always use a folder of the root, unless there is a very valid reason to put a file there. Yet, that is not your use case as presented.
$sites = Get-SPOSite -IncludePersonalSite $true
$user = "xxxxxx#domain.com"
foreach ($site in $sites)
{
Export-SPOUserInfo -LoginName $user -site $($site.Url) -OutputFolder 'D:\SPOSiteData'
}
Your string must be all on one line if not properly terminated for multi-line. For example, using PowerShell Splatting
about_Splatting - PowerShell | Microsoft Docs
$ExportSPOUserInfoSplat = #{
LoginName = $user
site = $($site.Url)
OutputFolder = 'D:\SPOSiteData'
}
Export-SPOUserInfo #ExportSPOUserInfoSplat
Te line wrapping, which it seems you copied and pasted, is that way because of page space not a code requirement.

Calling Script Remotely Does Not Work

I can run this script perfectly on my SharePoint server, and the user's profile picture gets updated:
[Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")
[Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Server")
$siteurl = "http://SHAREPOINTSITE/"
try {
$site = New-Object Microsoft.SharePoint.SPSite($siteurl)
} catch {
New-Item -ItemType File -Path C:\Users\admin\Desktop -Name ERROR1.txt -Value $_.Exception.Message -Force
}
try {
$context = [Microsoft.Office.Server.ServerContext]::GetContext($site)
} catch {
New-Item -ItemType File -Path C:\Users\admin\Desktop -Name ERROR2.txt -Value $_.Exception.Message -Force
}
#This gets the User Profile Manager which is what we want to get hold of the users
$upm = New-Object Microsoft.Office.Server.UserProfiles.UserProfileManager($context)
$user = "DOMAIN\user.name"
#Put it in a loop for iterating for all users
if ($upm.UserExists($user)) {
try {
$profile = $upm.GetUserProfile($user)
$profile["PictureURL"].Value = "\\Sharepoint\C$\Users\admin\Desktop\1.jpg";
$profile.Commit();
} catch {
New-Item -ItemType File -Path C:\Users\admin\Desktop -Name ERROR3.txt -Value $_.Exception.Message -Force
}
}
New-Item -ItemType File -Path C:\Users\admin\Desktop -Name HELLO.txt -Force
$site.Dispose()
But when I run it from a remote PowerShell session, I am getting some weird errors:
ERROR1.txt
Exception calling ".ctor" with "1" argument(s): "The Web application at http://SHAREPOINTSITE/ could not be found. Verify that you have typed the URL correctly. If the URL should be serving existing content, the system administrator may need to add a new request URL mapping to the intended application."
ERROR2.txt
Multiple ambiguous overloads found for "GetContext" and the argument count: "1".
I have checked all of the possibilities here, but still seeing this issue.
This is how I call the above script from the remote machine:
$spfarm = "DOMAIN\admin.username"
$spfarmpw = ConvertTo-SecureString "password123" -AsPlainText -Force
$cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $spfarm,$spfarmpw
$session = New-PSSession SharePoint -Authentication Default -Credential $cred
Invoke-Command -Session $session -FilePath "\\SharePoint\C$\Users\admin\Desktop\testremote.ps1"
I have tried calling this in a few different ways (e.g. hosting the script on my machine or hosting it on the SharePoint server, as well as using relative paths to call the script), but I always see these errors.
Can anyone please help me understand why this doesn't work when calling it from a remote PC? The script is clearly being called (HELLO.txt always gets created), but the SharePoint profile picture never gets updated - even though that script definitely should work.
Any help or guidance is much appreciated
nslookup
nslookup SHAREPOINTSITE
Output
Server: dc1.domain.co.uk
Address: xx.xx.x.xx
Name: sharepoint.domain.co.uk
Address: yy.yy.y.yy
Aliases: SHAREPOINTSITE.domain.co.uk
Where yy.yy.y.yy is the correct IP (it's the same address I see when executing ping SHAREPOINTSITE)
Try changing the Authentication method to CredSSP. This is required by the remote PowerShell so that it can pass the credentials on.

PublicKey.Key.Encrypt error You cannot call a method on a null-valued expression

I keep getting the null-valued error on this script:
$key = $cert.PrivateKey.Decrypt($object.Key, $true)
It's taken from the powershell examples so I have no idea why it's not working. Any clue? The certificate is found correctly by using it's thumb-print, and the secret key is in it.
This is running on Windows 2012 R2 with powershell v4
try
{
$object = Import-Clixml -Path c:\temp\encryptionTest.xml
$thumbprint = '58E3080C84336ECFBBF9EFFCFF98788880F0BA5F'
$cert = Get-Item -Path Cert:\LocalMachine\My\$thumbprint -ErrorAction Stop
$key = $cert.PrivateKey.Decrypt($object.Key, $true)
$cert.PrivateKey
$secureString = $object.Payload | ConvertTo-SecureString -Key $key
$secureString
}
finally
{
if ($null -ne $key) { [array]::Clear($key, 0, $key.Length) }
}
UPDATE: I contacted the script author and he mentionned that the problem is that .NET does not play nicely out of the box with CNG (Crypto Next Generation)certificates which are identified as version 3(which is exactly the version we use) He supplied a new function that work with those.
I had the same issue but instead of picking up the cert from Cert:\LocalMachine\My, I changed it to
$cert = Get-Item -Path Cert:\CurrentUser\My\$thumbprint -ErrorAction Stop
and it works fine.
I contacted the script author and he mentionned that the problem is that .NET does not play nicely out of the box with CNG (Crypto Next Generation)certificates which are identified as version 3(which is exactly the version we use) He supplied a new function that work with those.
https://github.com/dlwyatt/ProtectedData