diff --git a/templates/AzureFunction/build/build.config.psd1 b/templates/AzureFunction/build/build.config.psd1 index 21bbff1..09b7621 100644 --- a/templates/AzureFunction/build/build.config.psd1 +++ b/templates/AzureFunction/build/build.config.psd1 @@ -1,16 +1,16 @@ @{ - TimerTrigger = @{ - # Default Schedule for timed executions - Schedule = '0 5 * * * *' + TimerTrigger = @{ + # Default Schedule for timed executions + Schedule = '0 5 * * * *' - # Different Schedules for specific timed endpoints - ScheduleOverrides = @{ - # 'Update-Whatever' = '0 5 12 * * *' - } - } + # Different Schedules for specific timed endpoints + ScheduleOverrides = @{ + # 'Update-Whatever' = '0 5 12 * * *' + } + } - HttpTrigger = @{ - <# + HttpTrigger = @{ + <# AuthLevels: https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-http-webhook-trigger?tabs=python-v2%2Cisolated-process%2Cnodejs-v4%2Cfunctionsv2&pivots=programming-language-csharp#http-auth @@ -18,13 +18,32 @@ function: (default) Require a function-endpoint-specific token with the request admin: Require a Function-App-global admin token (master key) for the request #> - AuthLevel = 'function' - AuthLevelOverrides = @{ - # 'Set-Foo' = 'anonymous' - } - Methods = @('get', 'post') - MethodOverrides = @{ - # 'Set-Foo' = 'delete' - } - } + AuthLevel = 'function' + AuthLevelOverrides = @{ + # 'Set-Foo' = 'anonymous' + } + Methods = @('get', 'post') + MethodOverrides = @{ + # 'Set-Foo' = 'delete' + } + } + + EventGridTrigger = @{ + <# + AuthLevels: + https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-http-webhook-trigger?tabs=python-v2%2Cisolated-process%2Cnodejs-v4%2Cfunctionsv2&pivots=programming-language-csharp#http-auth + + anonymous: No Token needed (combine with Identity Provider for Entra ID auth without also needing a token) + function: (default) Require a function-endpoint-specific token with the request + admin: Require a Function-App-global admin token (master key) for the request + #> + AuthLevel = 'function' + AuthLevelOverrides = @{ + # 'Set-Foo' = 'anonymous' + } + Methods = @('get', 'post') + MethodOverrides = @{ + # 'Set-Foo' = 'delete' + } + } } \ No newline at end of file diff --git a/templates/AzureFunction/build/build.ps1 b/templates/AzureFunction/build/build.ps1 index 753908c..9da6b53 100644 --- a/templates/AzureFunction/build/build.ps1 +++ b/templates/AzureFunction/build/build.ps1 @@ -44,6 +44,24 @@ foreach ($command in Get-ChildItem -Path "$workingDirectory\þnameþ\functions\h $httpConfig -replace '%AUTHLEVEL%', $authLevel -replace '%METHODS%', ($methods -join '", "') | Set-Content -Path "$($endpointFolder.FullName)\function.json" } + +# Generate Event Grid Trigger +$eventGridCode = Get-Content -Path "$PSScriptRoot\functionEventGrid\run.ps1" | Join-String -Separator "`n" +$eventGridConfig = Get-Content -Path "$PSScriptRoot\functionEventGrid\function.json" | Join-String -Separator "`n" +foreach ($command in Get-ChildItem -Path "$workingDirectory\þnameþ\functions\eventGridTrigger" -Recurse -File -Filter *.ps1) { + $authLevel = $config.EventGridTrigger.AuthLevel + if ($config.EventGridTrigger.AuthLevelOverrides.$($command.BaseName)) { + $authLevel = $config.EventGridTrigger.AuthLevelOverrides.$($command.BaseName) + } + $methods = $config.EventGridTrigger.Methods + if ($config.EventGridTrigger.MethodOverrides.$($command.BaseName)) { + $methods = $config.EventGridTrFigger.MethodOverrides.$($command.BaseName) + } + $endpointFolder = New-Item -Path $buildFolder.FullName -Name $command.BaseName -ItemType Directory + $eventGridCode -replace '%COMMAND%',$command.BaseName | Set-Content -Path "$($endpointFolder.FullName)\run.ps1" + $eventGridConfig -replace '%AUTHLEVEL%', $authLevel -replace '%METHODS%', ($methods -join '", "') | Set-Content -Path "$($endpointFolder.FullName)\function.json" +} + # Generate Timer Trigger $timerCode = Get-Content -Path "$PSScriptRoot\functionTimer\run.ps1" | Join-String -Separator "`n" $timerConfig = Get-Content -Path "$PSScriptRoot\functionTimer\function.json" | Join-String -Separator "`n" diff --git a/templates/AzureFunction/build/functionEventGrid/function.json b/templates/AzureFunction/build/functionEventGrid/function.json new file mode 100644 index 0000000..88b67cd --- /dev/null +++ b/templates/AzureFunction/build/functionEventGrid/function.json @@ -0,0 +1,19 @@ +{ + "bindings": [ + { + "authLevel": "%AUTHLEVEL%", + "type": "eventGridTrigger", + "direction": "in", + "name": "EventGridEvent", + "methods": [ + "%METHODS%" + ] + }, + { + "type": "http", + "direction": "out", + "name": "Response" + } + ], + "disabled": false +} \ No newline at end of file diff --git a/templates/AzureFunction/build/functionEventGrid/run.ps1 b/templates/AzureFunction/build/functionEventGrid/run.ps1 new file mode 100644 index 0000000..1b2de5a --- /dev/null +++ b/templates/AzureFunction/build/functionEventGrid/run.ps1 @@ -0,0 +1,24 @@ +param ( + $EventGridEvent, + + $TriggerMetadata +) + + +Write-Host "Trigger: %COMMAND% has been invoked" + +$parameters = Get-RestParameter -Request $Request -Command %COMMAND% + +try { + $results = %COMMAND% @parameters -ErrorAction Stop +} +catch { + $_ | Out-String | ForEach-Object { + foreach ($line in ($_ -split "`n")) { + Write-Warning $line + } + } + Write-FunctionResult -Status InternalServerError -Body "$_" + return +} +Write-FunctionResult -Status OK -Body $results \ No newline at end of file diff --git a/templates/AzureFunctionEventGrid/PSMDInvoke.ps1 b/templates/AzureFunctionEventGrid/PSMDInvoke.ps1 new file mode 100644 index 0000000..c7d416e --- /dev/null +++ b/templates/AzureFunctionEventGrid/PSMDInvoke.ps1 @@ -0,0 +1,4 @@ +param ( + $Path +) +New-PSMDTemplate -ReferencePath "$PSScriptRoot" -OutPath $Path diff --git a/templates/AzureFunctionEventGrid/PSMDTemplate.ps1 b/templates/AzureFunctionEventGrid/PSMDTemplate.ps1 new file mode 100644 index 0000000..2fc96ef --- /dev/null +++ b/templates/AzureFunctionEventGrid/PSMDTemplate.ps1 @@ -0,0 +1,10 @@ +@{ + TemplateName = 'AzureFunctionEventGrid' + Version = "1.0.0.0" + AutoIncrementVersion = $true + Tags = 'azure', 'function', 'eventgrid' + Author = 'Jan-Hendrik Peters' + Description = 'Event Grid trigger endpoint for the basic Azure Function Template' + Exclusions = @("PSMDInvoke.ps1", ".PSMDDependency") # Contains list of files - relative path to root - to ignore when building the template + Scripts = @{ } +} diff --git a/templates/AzureFunctionEventGrid/function.json b/templates/AzureFunctionEventGrid/function.json new file mode 100644 index 0000000..79b0fc2 --- /dev/null +++ b/templates/AzureFunctionEventGrid/function.json @@ -0,0 +1,15 @@ +{ + "bindings": [ + { + "type": "eventGridTrigger", + "name": "EventGridEvent", + "direction": "in" + }, + { + "type": "http", + "direction": "out", + "name": "Response" + } + ], + "disabled": false +} diff --git a/templates/AzureFunctionEventGrid/run.ps1 b/templates/AzureFunctionEventGrid/run.ps1 new file mode 100644 index 0000000..107d992 --- /dev/null +++ b/templates/AzureFunctionEventGrid/run.ps1 @@ -0,0 +1,23 @@ +param ( + $EventGridEvent, + + $TriggerMetadata +) + +Write-Host "Trigger: %COMMAND% has been invoked" + +$parameters = Get-RestParameter -Request $EventGridEvent -Command %COMMAND% + +try { + $results = %COMMAND% @parameters -ErrorAction Stop +} +catch { + $_ | Out-String | ForEach-Object { + foreach ($line in ($_ -split "`n")) { + Write-Warning $line + } + } + Write-FunctionResult -Status InternalServerError -Body "$_" + return +} +Write-FunctionResult -Status OK -Body $results