├── .gitignore ├── .vscode └── settings.json ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── NOTICE ├── README.md ├── examples ├── demo-container-image-all-aws-sdk │ ├── Dockerfile │ ├── function │ │ └── examplehandler.ps1 │ ├── readme.md │ └── template.yml ├── demo-container-images-shared │ ├── Dockerfile │ ├── function │ │ └── examplehandler.ps1 │ ├── powershell-modules-aws-tools │ │ └── Dockerfile │ ├── powershell-runtime │ │ └── Dockerfile │ ├── readme.md │ └── template.yml ├── demo-runtime-layer-function │ ├── build-layers.ps1 │ ├── function │ │ ├── Makefile │ │ ├── examplehandler.ps1 │ │ ├── examplemodule │ │ │ ├── examplemodule.psd1 │ │ │ └── examplemodule.psm1 │ │ └── examplescript.ps1 │ ├── readme.md │ └── template.yml └── demo-s3-lambda-eventbridge │ ├── build-layers.ps1 │ ├── function │ ├── Makefile │ └── modules │ │ └── demo-s3-lambda-eventbridge │ │ ├── demo-s3-lambda-eventbridge.psd1 │ │ └── demo-s3-lambda-eventbridge.psm1 │ ├── readme.md │ ├── template.yml │ └── test.csv ├── img ├── aws-cli-publish-layer-version.png ├── aws-sam-layer-resources.png ├── aws-sam-resources.png ├── build-layers.png ├── build-modules-layer.png ├── cat-invoke-result.png ├── lambda-console-code.png ├── lambda-console-test.png ├── s3-demo-aws-sam-resources.png ├── s3-demo-sam-deploy-g.png ├── sam-build-layer.png ├── sam-build-parallel-use-container.png ├── sam-build-parallel.png ├── sam-deploy-g.png ├── sam-deploy-layer-g.png └── sam-local-invoke.png ├── powershell-modules ├── AWSToolsforPowerShell │ ├── AWS.Tools.All │ │ ├── build-AWSToolsLayer.ps1 │ │ ├── buildlayer │ │ │ └── Makefile │ │ └── template.yml │ ├── AWS.Tools.Common │ │ ├── build-AWSToolsLayer.ps1 │ │ ├── buildlayer │ │ │ └── Makefile │ │ └── template.yml │ ├── AWS.Tools.S3EventBridge │ │ ├── build-AWSToolsLayer.ps1 │ │ ├── buildlayer │ │ │ └── Makefile │ │ └── template.yml │ ├── Demo-AWS.Tools │ │ ├── build-AWSToolsLayer.ps1 │ │ ├── buildlayer │ │ │ └── Makefile │ │ ├── template.yml │ │ └── tests │ │ │ └── build-AWSToolsLayer.Tests.ps1 │ └── readme.md ├── VMwarePowerCLI │ ├── Makefile │ ├── build-PowerCLILayer.ps1 │ └── template.yml └── readme.md └── powershell-runtime ├── build-PwshRuntimeLayer.ps1 ├── readme.md ├── source ├── Makefile ├── PowerShellLambdaContext.cs ├── bootstrap └── modules │ ├── Private │ ├── Get-Handler.ps1 │ ├── Get-LambdaNextInvocation.ps1 │ ├── Invoke-FunctionHandler.ps1 │ ├── Send-FunctionHandlerError.ps1 │ ├── Send-FunctionHandlerResponse.ps1 │ ├── Set-HandlerEnvironmentVariables.ps1 │ ├── Set-LambdaContext.ps1 │ ├── Set-PSModulePath.ps1 │ └── _SendRuntimeApiPost.ps1 │ ├── pwsh-runtime.psd1 │ └── pwsh-runtime.psm1 └── template.yml /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.toptal.com/developers/gitignore/api/powershell,windows,linux,macos,visualstudiocode,git 3 | # Edit at https://www.toptal.com/developers/gitignore?templates=powershell,windows,linux,macos,visualstudiocode,git 4 | 5 | ### Git ### 6 | # Created by git for backups. To disable backups in Git: 7 | # $ git config --global mergetool.keepBackup false 8 | *.orig 9 | 10 | # Created by git when using merge tools for conflicts 11 | *.BACKUP.* 12 | *.BASE.* 13 | *.LOCAL.* 14 | *.REMOTE.* 15 | *_BACKUP_*.txt 16 | *_BASE_*.txt 17 | *_LOCAL_*.txt 18 | *_REMOTE_*.txt 19 | 20 | ### Linux ### 21 | *~ 22 | 23 | # temporary files which can be created if a process still has a handle open of a deleted file 24 | .fuse_hidden* 25 | 26 | # KDE directory preferences 27 | .directory 28 | 29 | # Linux trash folder which might appear on any partition or disk 30 | .Trash-* 31 | 32 | # .nfs files are created when an open file is removed but is still being accessed 33 | .nfs* 34 | 35 | ### macOS ### 36 | # General 37 | .DS_Store 38 | .AppleDouble 39 | .LSOverride 40 | 41 | # Icon must end with two \r 42 | Icon 43 | 44 | 45 | # Thumbnails 46 | ._* 47 | 48 | # Files that might appear in the root of a volume 49 | .DocumentRevisions-V100 50 | .fseventsd 51 | .Spotlight-V100 52 | .TemporaryItems 53 | .Trashes 54 | .VolumeIcon.icns 55 | .com.apple.timemachine.donotpresent 56 | 57 | # Directories potentially created on remote AFP share 58 | .AppleDB 59 | .AppleDesktop 60 | Network Trash Folder 61 | Temporary Items 62 | .apdisk 63 | 64 | ### PowerShell ### 65 | # Exclude packaged modules 66 | *.zip 67 | 68 | # Exclude .NET assemblies from source 69 | *.dll 70 | 71 | ### VisualStudioCode ### 72 | .vscode/* 73 | !.vscode/settings.json 74 | !.vscode/tasks.json 75 | !.vscode/launch.json 76 | !.vscode/extensions.json 77 | !.vscode/*.code-snippets 78 | 79 | # Local History for Visual Studio Code 80 | .history/ 81 | 82 | # Built Visual Studio Code Extensions 83 | *.vsix 84 | 85 | ### VisualStudioCode Patch ### 86 | # Ignore all local history of files 87 | .history 88 | .ionide 89 | 90 | # Support for Project snippet scope 91 | 92 | ### Windows ### 93 | # Windows thumbnail cache files 94 | Thumbs.db 95 | Thumbs.db:encryptable 96 | ehthumbs.db 97 | ehthumbs_vista.db 98 | 99 | # Dump file 100 | *.stackdump 101 | 102 | # Folder config file 103 | [Dd]esktop.ini 104 | 105 | # Recycle Bin used on file shares 106 | $RECYCLE.BIN/ 107 | 108 | # Windows Installer files 109 | *.cab 110 | *.msi 111 | *.msix 112 | *.msm 113 | *.msp 114 | 115 | # Windows shortcuts 116 | *.lnk 117 | 118 | ### AWS SAM ### 119 | samconfig.toml 120 | .aws-sam/ 121 | invoke-result 122 | # temporary files which can be created if a process still has a handle open of a deleted file 123 | 124 | 125 | # End of https://www.toptal.com/developers/gitignore/api/powershell,windows,linux,macos,visualstudiocode,git 126 | 127 | # PowerShell runtime binaries 128 | powershell-runtime/pwsh-runtime/powershell 129 | dev/ 130 | layers/ -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | // When enabled, will trim trailing whitespace when you save a file. 3 | "files.trimTrailingWhitespace": true, 4 | // Specifies the PowerShell coding style used in this project (https://github.com/PoshCode/PowerShellPracticeAndStyle/issues/81) 5 | "powershell.codeFormatting.preset": "Stroustrup" 6 | } 7 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | 10 | ## Reporting Bugs/Feature Requests 11 | 12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 13 | 14 | When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already 15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 16 | 17 | * A reproducible test case or series of steps 18 | * The version of our code being used 19 | * Any modifications you've made relevant to the bug 20 | * Anything unusual about your environment or deployment 21 | 22 | 23 | ## Contributing via Pull Requests 24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 25 | 26 | 1. You are working against the latest source on the *main* branch. 27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 29 | 30 | To send us a pull request, please: 31 | 32 | 1. Fork the repository. 33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 34 | 3. Ensure local tests pass. 35 | 4. Commit to your fork using clear commit messages. 36 | 5. Send us a pull request, answering any default questions in the pull request interface. 37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 38 | 39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 41 | 42 | 43 | ## Finding contributions to work on 44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start. 45 | 46 | 47 | ## Code of Conduct 48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 50 | opensource-codeofconduct@amazon.com with any additional questions or comments. 51 | 52 | 53 | ## Security issue notifications 54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 55 | 56 | 57 | ## Licensing 58 | 59 | See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 60 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PowerShell Runtime for AWS Lambda 2 | 3 | This new [PowerShell](https://docs.microsoft.com/en-us/powershell/scripting/overview) custom runtime for [AWS Lambda](https://aws.amazon.com/lambda/) makes it even easier to run Lambda functions written in PowerShell to process events. 4 | 5 | Your code runs in an Amazon Linux environment that includes AWS credentials from an [AWS Identity and Access Management (IAM)](https://aws.amazon.com/iam/) role that you manage. 6 | 7 | ## Overview 8 | 9 | Lambda has supported running PowerShell since 2018. However, the existing solution uses the .NET Core runtime [implementation for PowerShell](https://docs.aws.amazon.com/lambda/latest/dg/lambda-powershell.html). It uses the additional [AWSLambdaPSCore](https://www.powershellgallery.com/packages/AWSLambdaPSCore/3.0.1.0) modules for deployment and publishing, which require compiling the PowerShell code into C# binaries to run on .NET. This adds additional steps to the development process. 10 | 11 | This new runtime uses Lambda's [custom runtime](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-custom.html) functionality based on the `provided.al2023` runtime. 12 | 13 | ## PowerShell custom runtime benefits 14 | 15 | * **Native PowerShell.** This new runtime uses native PowerShell. 16 | * The function runtime environment matches a standard PowerShell session, which simplifies the development and testing process. 17 | * No compilation step required and no hosting on the .NET runtime. 18 | * Allows additional functionality, such as `Add-Type` to provide richer context information. 19 | 20 | * **Code visibility.** You can now also view and edit PowerShell code within the Lambda console's built-in [code editor](https://docs.aws.amazon.com/lambda/latest/dg/foundation-console.html#code-editor) which using .zip archive functions (not container images). You can embed PowerShell code within an [AWS CloudFormation](https://aws.amazon.com/cloudformation/) template, or other infrastructure as code tools. 21 | * **Output**. This custom runtime returns everything placed on the pipeline as the function output, including the output of `Write-Output`.This gives you more control over the function output, error messages, and logging. With the previous .NET runtime implementation, your function returns only the last output from the PowerShell pipeline. Unhandled exceptions are caught by the runtime, then they are logged to the log stream and a error result is returned to the caller. 22 | 23 | ## Building, deploying, and invoking PowerShell Lambda functions 24 | 25 | You can build the custom runtime using a number of tools, including the the [AWS Command Line Interface (AWS CLI)](https://aws.amazon.com/cli/), or with infrastructure as code tools such as [AWS CloudFormation](https://aws.amazon.com/cloudformation/), [AWS Serverless Application Model (AWS SAM)](https://aws.amazon.com/serverless/sam/), [Serverless Framework](https://serverless.com/framework/), and [AWS Cloud Development Kit (AWS CDK)](https://aws.amazon.com/cdk/). 26 | 27 | Deploy the example [demo-runtime-layer-function](examples/demo-runtime-layer-function/) to explore how the runtime and PowerShell function work. 28 | 29 | ### [PowerShell-runtime](powershell-runtime/) 30 | 31 | Contains the PowerShell custom runtime based on ````provided.al2023```` with a number of deployment methods. 32 | 33 | ### [PowerShell-modules](powershell-modules/) 34 | 35 | Contains a number of PowerShell modules you can build and add to your functions. 36 | | Module | Description | 37 | |:---|:---| 38 | |[AWSToolsforPowerShell](powershell-modules/AWSToolsforPowerShell/)|AWS Tools for PowerShell | 39 | |[VMwarePowerCLI](powershell-modules/VMwarePowerCLI/)|VMware PowerCLI| 40 | 41 | ### [Examples folder](examples/) 42 | 43 | Contains a number of demo applications to show the PowerShell runtime functionality. 44 | 45 | Initial demo application [demo-runtime-layer-function](examples/demo-runtime-layer-function/) uses AWS SAM to deploy the following: 46 | 47 | 1. PowerShell custom runtime based on ````provided.al2023```` as a Lambda layer. 48 | 2. Additional Lambda layer including the [AWSTools for PowerShell](https://aws.amazon.com/powershell/) with the following module. 49 | * ````AWS.Tools.Common```` 50 | 3. Both layers store their Amazon Resource Names (ARNs) as parameters in [AWS Systems Manager Parameter Store](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html) which can be referenced in other templates 51 | 52 | 4. Lambda function with three different handler options. 53 | 54 | ### All examples 55 | 56 | | Example | Description | 57 | |:---|:---| 58 | |[demo-runtime-layer-function](examples/demo-runtime-layer-function/)|All-in-one Powershell runtime layer, AWS Tools for PowerShell layer, Lambda function with all three handler options. | 59 | |[demo-s3-lambda-eventbridge](examples/demo-s3-lambda-eventbridge/)|Demo to show an event-drive application in PowerShell. Copy .CSV file to S3 which triggers PowerShell Lambda function which parses the file. Sends each file line as an event to EventBridge which writes it to CLoudWatch Logs. | 60 | |[demo-container-image-all-aws-sdk](examples/demo-container-image-all-aws-sdk/)|Demo application to deploy a PowerShell Lambda function using a [container image](https://docs.aws.amazon.com/lambda/latest/dg/images-create.html). The container image can be up to 10Gb in size which allows you to build functions larger than the 256MB limit for .zip archive functions. This allows you to include the entire [AWSTools for PowerShell](https://aws.amazon.com/powershell/) SDK, for example. | 61 | |[demo-container-images-shared](examples/demo-container-image-all-aws-sdk/)|Demo application to deploy container image Lambda function using separate layers for the PowerShell runtime and entire [AWSTools for PowerShell](https://aws.amazon.com/powershell/) SDK. This allows you to use these shared layers to build multiple Lambda functions. The container image can be up to 10Gb in size which allows you to build functions larger than the 256MB limit for .zip archive functions. | 62 | 63 | 64 | ## Powershell runtime information 65 | 66 | See the [PowerShell-runtime](powershell-runtime/) page for more information on how the runtime works, including: 67 | 68 | * Variables 69 | * Lambda handler options 70 | * Lambda context object in PowerShell 71 | * PowerShell module support 72 | * Function logging and metrics 73 | * Function errors 74 | 75 | ## Acknowledgements 76 | 77 | This custom runtime builds on the work of [Norm Johanson](https://twitter.com/socketnorm), [Kevin Marquette](https://twitter.com/KevinMarquette), [Andrew Pearce](https://twitter.com/austoonz), Afroz Mohammed, and Jonathan Nunn. 78 | 79 | ## Security 80 | 81 | See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more information. 82 | 83 | ## License 84 | 85 | This project is licensed under the Apache-2.0 License. 86 | -------------------------------------------------------------------------------- /examples/demo-container-image-all-aws-sdk/Dockerfile: -------------------------------------------------------------------------------- 1 | ## INSTALL POWERSHELL RUNTIME 2 | FROM public.ecr.aws/lambda/provided:al2023 as runtime-files 3 | # PWSH_VERSION is version of PowerShell to download 4 | ARG PWSH_VERSION=7.4.0 5 | # PWSH_ARCHITECTURE can be 'x64' or 'arm64' 6 | ARG PWSH_ARCHITECTURE=x64 7 | ARG ARTIFACTS_DIR=/opt 8 | # Download and extract PowerShell binaries. Remove downloaded file 9 | RUN dnf install tar gzip -y 10 | RUN curl -L -o $ARTIFACTS_DIR/powershell-$PWSH_VERSION-$PWSH_ARCHITECTURE.tar.gz https://github.com/PowerShell/PowerShell/releases/download/v$PWSH_VERSION/powershell-$PWSH_VERSION-linux-$PWSH_ARCHITECTURE.tar.gz 11 | RUN mkdir -p $ARTIFACTS_DIR/powershell 12 | RUN tar zxf $ARTIFACTS_DIR/powershell-$PWSH_VERSION-$PWSH_ARCHITECTURE.tar.gz -C $ARTIFACTS_DIR/powershell/ 13 | RUN rm $ARTIFACTS_DIR/powershell-$PWSH_VERSION-$PWSH_ARCHITECTURE.tar.gz 14 | # Make PowerShell binary executable 15 | RUN chmod +x $ARTIFACTS_DIR/powershell/pwsh 16 | # Copy additional runtime files from GitHub repo, including bootstrap. 17 | WORKDIR /tmp 18 | RUN dnf install git-core -y 19 | RUN git clone https://github.com/awslabs/aws-lambda-powershell-runtime 20 | ARG RUNTIME_DIR=/tmp/aws-lambda-powershell-runtime/powershell-runtime/source 21 | RUN cp $RUNTIME_DIR/bootstrap /var/runtime 22 | RUN cp $RUNTIME_DIR/PowerShellLambdaContext.cs $ARTIFACTS_DIR 23 | RUN mkdir $ARTIFACTS_DIR/modules 24 | RUN cp -r $RUNTIME_DIR/modules/ $ARTIFACTS_DIR/ 25 | RUN rm -Rf /tmp/aws-lambda-powershell-runtime 26 | # Merge all Private module content into a single .psm1 file to speed up module loading 27 | WORKDIR $ARTIFACTS_DIR/modules/Private 28 | RUN tail -n +3 -q $ARTIFACTS_DIR/modules/Private/*.ps1 >> $ARTIFACTS_DIR/modules/pwsh-runtime.psm1 29 | RUN rm -Rf $ARTIFACTS_DIR/modules/Private 30 | 31 | # Make bootstrap script executable 32 | RUN chmod +x /var/runtime/bootstrap 33 | 34 | ## INSTALL AWS SDK 35 | FROM public.ecr.aws/lambda/provided:al2023 as module-files 36 | ARG ARTIFACTS_DIR=/opt 37 | RUN dnf install unzip -y 38 | RUN curl -L -o $ARTIFACTS_DIR/AWS.Tools.zip https://sdk-for-net.amazonwebservices.com/ps/v4/latest/AWS.Tools.zip 39 | RUN mkdir -p $ARTIFACTS_DIR/modules 40 | 41 | # Extract Entire AWS.Tools modules 42 | RUN unzip $ARTIFACTS_DIR/AWS.Tools.zip -d $ARTIFACTS_DIR/modules 43 | # Extract select AWS.Tools modules (AWS.Tools.Common required) 44 | #RUN unzip $ARTIFACTS_DIR/AWS.Tools.zip 'AWS.Tools.Common/**/*' -d $ARTIFACTS_DIR/modules/ 45 | #RUN unzip $ARTIFACTS_DIR/AWS.Tools.zip 'AWS.Tools.S3/**/*' -d $ARTIFACTS_DIR/modules/ 46 | #RUN unzip $ARTIFACTS_DIR/AWS.Tools.zip 'AWS.Tools.EventBridge/**/*' -d $ARTIFACTS_DIR/modules/ 47 | RUN rm $ARTIFACTS_DIR/AWS.Tools.zip 48 | 49 | ## Build final image 50 | FROM public.ecr.aws/lambda/provided:al2023 51 | ## Copy PowerShell runtime files 52 | COPY --from=runtime-files . / 53 | ## Copy Module files 54 | COPY --from=module-files . / 55 | ## Function files 56 | COPY /function/ /var/task 57 | ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 58 | WORKDIR /var/task 59 | ENTRYPOINT [ "/var/runtime/bootstrap" ] 60 | CMD [ "examplehandler.ps1::handler" ] -------------------------------------------------------------------------------- /examples/demo-container-image-all-aws-sdk/function/examplehandler.ps1: -------------------------------------------------------------------------------- 1 | #$VerbosePreference = "continue" 2 | #$VerbosePreference = "SilentlyContinue" 3 | Write-Verbose "Run script init tasks before handler" 4 | Write-Verbose "Importing Modules" 5 | Import-Module "AWS.Tools.Common" 6 | function handler 7 | { 8 | [cmdletbinding()] 9 | param( 10 | [parameter()] 11 | $LambdaInput, 12 | 13 | [parameter()] 14 | $LambdaContext 15 | ) 16 | Write-Verbose "Run handler function from script1" 17 | Write-Verbose "Function Remaining Time: $($LambdaContext.GetRemainingTimeInMillis())" 18 | Get-AWSRegion 19 | } 20 | -------------------------------------------------------------------------------- /examples/demo-container-image-all-aws-sdk/readme.md: -------------------------------------------------------------------------------- 1 | # Demo-container-image-all-aws-sdk 2 | 3 | Demo application to deploy a PowerShell Lambda function using a [container image](https://docs.aws.amazon.com/lambda/latest/dg/images-create.html). The container image can be up to 10Gb in size which allows you to build functions larger than the 256MB limit for .zip archive functions. This allows you to include the entire [AWSTools for PowerShell](https://aws.amazon.com/powershell/) SDK, for example. 4 | 5 | The container image contains the following components: 6 | 7 | 1. PowerShell custom runtime based on ````provided.al2023````. This downloads the specified version of [PowerShell](https://github.com/PowerShell/PowerShell/releases/) and adds the custom runtime files from the [PowerShell-runtime](../../powershell-runtime/) folder. 8 | 2. The [AWSTools for PowerShell](https://aws.amazon.com/powershell/) with the entire AWS SDK. You can amend the loaded modules within the Dockerfile to only include specific modules. ````AWS.Tools.Common```` is required 9 | 3. Lambda function code in the [function](./function) folder. 10 | 11 | You can build and deploy the demo using either of the two options: 12 | 13 | * A: [Docker Desktop](https://docs.docker.com/get-docker/) and the AWS CLI 14 | * B: [AWS Serverless Application Model (AWS SAM)](https://aws.amazon.com/serverless/sam/) 15 | 16 | Use one of the *"Build and deploy"* options, A,B depending on your tools. 17 | 18 | ## A) Build and deploy using Docker Desktop and the AWS CLI. 19 | 20 | ### Pre-requisites 21 | 22 | * [Docker Desktop](https://docs.docker.com/get-docker/) 23 | * [AWS Command Line Interface (AWS CLI)](https://aws.amazon.com/cli/) 24 | 25 | ### Build and push the container image 26 | 27 | 1. Clone the repository and change into the example directory 28 | 29 | ```shell 30 | git clone https://github.com/awslabs/aws-lambda-powershell-runtime 31 | cd aws-lambda-powershell-runtime/examples/demo-container-image-all-aws-sdk 32 | ``` 33 | 34 | 2. Create an [Amazon Elastic Container Registry (ECR)](https://aws.amazon.com/ecr/) repository to store the container image. 35 | 36 | 3. Login to ECR. Replace the `` and `` values. 37 | ```shell 38 | aws ecr get-login-password --region | docker login --username AWS --password-stdin .dkr.ecr..amazonaws.com 39 | ``` 40 | 41 | 4. Create the repository. Rename `--repository-name` from `demo-container-image-all-aws-sdk` to your prefered name if required. 42 | ```shell 43 | aws ecr create-repository --repository-name demo-container-image-all-aws-sdk 44 | ``` 45 | 46 | 5. Build the Docker image. Rename the image name in the following steps from `demo-container-image-all-aws-sdk:latest` if required. Replace the `` and `` values. 47 | ```shell 48 | docker build -t .dkr.ecr..amazonaws.com/demo-container-image-all-aws-sdk:latest . 49 | ``` 50 | 51 | 6. Push the Docker image. Replace the `` and `` values. 52 | ```shell 53 | docker push .dkr.ecr..amazonaws.com/demo-container-image-all-aws-sdk:latest 54 | ``` 55 | 56 | ### Create the Lambda function 57 | 1. Create a Lambda function execution IAM Role using the [documentation](https://docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html). 58 | 59 | 2. Create a Lambda function using the AWS CLI. Replace the `` and `` values. Enter the correct IAM Role name for `--role`. You can amend the `--memory-size` and `--timeout` if required. 60 | ```shell 61 | aws lambda create-function --region --function-name demo-container-image-all-aws-sdk --package-type Image --memory-size 1024 --timeout 30 --code ImageUri=.dkr.ecr..amazonaws.com/demo-container-image-all-aws-sdk:latest --role "arn:aws:iam:::role/lambda-exec-role" 62 | ``` 63 | 64 | To make further configuration changes, you can use `aws lambda update-function-configuration`. For example, to increase the timeout. 65 | 66 | ```shell 67 | aws lambda update-function-configuration --region --function-name demo-container-image-all-aws-sdk --timeout 45 68 | ``` 69 | ### Invoke the function using the AWS CLI 70 | 71 | Once the Lambda function is deployed, you can invoke it using the AWS CLI. 72 | 73 | 1. From a command prompt, invoke the function. Amend the `--function-name` and `--region` values for your function. 74 | 75 | This should return `"StatusCode": 200` for a successful invoke. 76 | 77 | ````shell 78 | aws lambda invoke --function-name demo-container-image-all-aws-sdk --region invoke-result 79 | ```` 80 | 81 | 2. View the function results which are outputted to `invoke-result`. 82 | 83 | ````shell 84 | cat invoke-result 85 | ```` 86 | 87 | ![cat-invoke-result.png](/img/cat-invoke-result.png) 88 | 89 | ## B) Build and deploy using [AWS Serverless Application Model (AWS SAM)](https://aws.amazon.com/serverless/sam/). 90 | 91 | ### Pre-requisites 92 | 93 | * [AWS Serverless Application Model (AWS SAM)](https://aws.amazon.com/serverless/sam/) 94 | * [AWS Command Line Interface (AWS CLI)](https://aws.amazon.com/cli/) 95 | 96 | ### Build the container image function 97 | 1. Clone the repository and change into the example directory 98 | 99 | ```shell 100 | git clone https://github.com/awslabs/aws-lambda-powershell-runtime 101 | cd aws-lambda-powershell-runtime/examples/demo-container-image-all-aws-sdk 102 | ``` 103 | 104 | 2. use `sam build` to build the container image. 105 | 106 | ```shell 107 | sam build 108 | ``` 109 | ### Test the function locally 110 | 111 | Once the build process is complete, you can use AWS SAM to test the function locally. 112 | 113 | ```shell 114 | sam local invoke 115 | ``` 116 | 117 | This uses a Lambda-like environment to run the function locally and returns the function response, which is the result of `Get-AWSRegion`. 118 | 119 | ![sam local invoke](/img/sam-local-invoke.png) 120 | 121 | ### Deploying to the AWS Cloud 122 | 123 | Use AWS SAM to deploy the resources to your AWS account. 124 | 125 | 1. Run a guided deployment to set the default parameters for the first deploy. 126 | 127 | ```shell 128 | sam deploy -g 129 | ``` 130 | For subsequent deployments you can use `sam deploy`. 131 | 132 | 2. Enter a **Stack Name** such as `demo-container-image-all-aws-sdk` and accept the remaining initial defaults. 133 | 134 | AWS SAM deploys the infrastructure and outputs the function name `Value`. 135 | 136 | ### Invoke the function using AWS SAM 137 | 138 | Once the Lambda function is deployed, you can invoke it in the cloud using AWS SAM `remote invoke`. 139 | 140 | 1. From a command prompt, invoke the function. Amend the `--stack-name` from `demo-container-image-all-aws-sdk` if required. 141 | 142 | ```shell 143 | sam remote invoke --stack-name demo-container-image-all-aws-sdk 144 | ``` 145 | 146 | This should return a successful invoke with the result of `Get-AWSRegion`. 147 | 148 | ### Invoke the function using the AWS CLI 149 | 150 | Once the Lambda function is deployed, you can also invoke it using the AWS CLI. 151 | 152 | 1. From a command prompt, invoke the function. Amend the `--function-name` and `--region` values for your function. 153 | 154 | This should return `"StatusCode": 200` for a successful invoke. 155 | 156 | ````shell 157 | aws lambda invoke --function-name demo-container-image-all-aw-DemoPowerShellFunction-Nwecb1EWXKq6 --region invoke-result 158 | ```` 159 | 160 | 2. View the function result of `AWS-GetRegion` which is outputted to `invoke-result`. 161 | 162 | ````shell 163 | cat invoke-result 164 | ```` 165 | 166 | ![cat-invoke-result.png](/img/cat-invoke-result.png) 167 | 168 | ### AWS SAM cleanup 169 | 170 | To delete the AWS resources created, run the following and confirm that you want to delete the resources that were created by this template. 171 | 172 | ````shell 173 | sam delete 174 | ```` 175 | 176 | -------------------------------------------------------------------------------- /examples/demo-container-image-all-aws-sdk/template.yml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: '2010-09-09' 2 | Transform: AWS::Serverless-2016-10-31 3 | Description: Demo to explore how the PowerShell custom runtime and a Lambda function work. 4 | ########################################################################## 5 | # Parameters & Globals # 6 | ########################################################################## 7 | Globals: 8 | Function: 9 | Tracing: Active 10 | Tags: 11 | Application: demo-container-image-all-aws-sdk 12 | Resources: 13 | ########################################################################## 14 | # Lambda functions # 15 | ########################################################################## 16 | DemoPowerShellFunction: 17 | Type: AWS::Serverless::Function 18 | Properties: 19 | Architectures: 20 | - x86_64 21 | Description: PowerShell-Lambda-Runtime Demo Function 22 | PackageType: Image 23 | MemorySize: 1024 24 | Timeout: 100 25 | Environment: 26 | Variables: 27 | DOTNET_SYSTEM_GLOBALIZATION_INVARIANT: '1' 28 | Metadata: 29 | Dockerfile: Dockerfile 30 | DockerContext: . 31 | DockerTag: demo-container-image-all-aws-sdk 32 | ########################################################################## 33 | # OUTPUTS # 34 | ########################################################################## 35 | Outputs: 36 | DemoPowerShellFunction: 37 | Value: !Ref DemoPowerShellFunction 38 | Description: PowerShell Lambda Function -------------------------------------------------------------------------------- /examples/demo-container-images-shared/Dockerfile: -------------------------------------------------------------------------------- 1 | #FROM public.ecr.aws/lambda/provided:al2023 2 | ## INSTALL POWERSHELL RUNTIME 3 | FROM 978558897928.dkr.ecr.us-east-1.amazonaws.com/powershell-runtime:latest as runtime-files 4 | ## INSTALL AWS SDK 5 | FROM 978558897928.dkr.ecr.us-east-1.amazonaws.com/powershell-modules-aws-tools:latest as module-files 6 | 7 | ## Build final image 8 | FROM public.ecr.aws/lambda/provided:al2023 9 | ## Copy PowerShell runtime files 10 | COPY --from=runtime-files . / 11 | ## Copy Module files 12 | COPY --from=module-files . / 13 | ## Function files 14 | COPY /function/ /var/task 15 | ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 16 | WORKDIR /var/task 17 | ENTRYPOINT [ "/var/runtime/bootstrap" ] 18 | CMD [ "examplehandler.ps1::handler" ] -------------------------------------------------------------------------------- /examples/demo-container-images-shared/function/examplehandler.ps1: -------------------------------------------------------------------------------- 1 | #$VerbosePreference = "continue" 2 | #$VerbosePreference = "SilentlyContinue" 3 | Write-Verbose "Run script init tasks before handler" 4 | Write-Verbose "Importing Modules" 5 | Import-Module "AWS.Tools.Common" 6 | function handler 7 | { 8 | [cmdletbinding()] 9 | param( 10 | [parameter()] 11 | $LambdaInput, 12 | 13 | [parameter()] 14 | $LambdaContext 15 | ) 16 | Write-Verbose "Run handler function from script1" 17 | Write-Verbose "Function Remaining Time: $($LambdaContext.GetRemainingTimeInMillis())" 18 | Get-AWSRegion 19 | } 20 | -------------------------------------------------------------------------------- /examples/demo-container-images-shared/powershell-modules-aws-tools/Dockerfile: -------------------------------------------------------------------------------- 1 | ## INSTALL AWS SDK 2 | FROM public.ecr.aws/lambda/provided:al2023 as module-files 3 | ARG ARTIFACTS_DIR=/opt 4 | RUN dnf install unzip -y 5 | RUN curl -L -o $ARTIFACTS_DIR/AWS.Tools.zip https://sdk-for-net.amazonwebservices.com/ps/v4/latest/AWS.Tools.zip 6 | RUN mkdir -p $ARTIFACTS_DIR/modules 7 | 8 | # Extract Entire AWS.Tools modules 9 | RUN unzip $ARTIFACTS_DIR/AWS.Tools.zip -d $ARTIFACTS_DIR/modules 10 | # Extract select AWS.Tools modules (AWS.Tools.Common required) 11 | #RUN unzip $ARTIFACTS_DIR/AWS.Tools.zip 'AWS.Tools.Common/**/*' -d $ARTIFACTS_DIR/modules/ 12 | #RUN unzip $ARTIFACTS_DIR/AWS.Tools.zip 'AWS.Tools.S3/**/*' -d $ARTIFACTS_DIR/modules/ 13 | #RUN unzip $ARTIFACTS_DIR/AWS.Tools.zip 'AWS.Tools.EventBridge/**/*' -d $ARTIFACTS_DIR/modules/ 14 | RUN rm $ARTIFACTS_DIR/AWS.Tools.zip 15 | -------------------------------------------------------------------------------- /examples/demo-container-images-shared/powershell-runtime/Dockerfile: -------------------------------------------------------------------------------- 1 | ## INSTALL POWERSHELL RUNTIME 2 | FROM public.ecr.aws/lambda/provided:al2023 as runtime-files 3 | # PWSH_VERSION is version of PowerShell to download 4 | ARG PWSH_VERSION=7.4.0 5 | # PWSH_ARCHITECTURE can be 'x64' or 'arm64' 6 | ARG PWSH_ARCHITECTURE=x64 7 | ARG ARTIFACTS_DIR=/opt 8 | # Download and extract PowerShell binaries. Remove downloaded file 9 | RUN dnf install tar gzip -y 10 | RUN curl -L -o $ARTIFACTS_DIR/powershell-$PWSH_VERSION-$PWSH_ARCHITECTURE.tar.gz https://github.com/PowerShell/PowerShell/releases/download/v$PWSH_VERSION/powershell-$PWSH_VERSION-linux-$PWSH_ARCHITECTURE.tar.gz 11 | RUN mkdir -p $ARTIFACTS_DIR/powershell 12 | RUN tar zxf $ARTIFACTS_DIR/powershell-$PWSH_VERSION-$PWSH_ARCHITECTURE.tar.gz -C $ARTIFACTS_DIR/powershell/ 13 | RUN rm $ARTIFACTS_DIR/powershell-$PWSH_VERSION-$PWSH_ARCHITECTURE.tar.gz 14 | # Make PowerShell binary executable 15 | RUN chmod +x $ARTIFACTS_DIR/powershell/pwsh 16 | # Copy additional runtime files from GitHub repo, including bootstrap. 17 | WORKDIR /tmp 18 | RUN dnf install git-core -y 19 | RUN git clone https://github.com/awslabs/aws-lambda-powershell-runtime 20 | ARG RUNTIME_DIR=/tmp/aws-lambda-powershell-runtime/powershell-runtime/source 21 | RUN cp $RUNTIME_DIR/bootstrap /var/runtime 22 | RUN cp $RUNTIME_DIR/PowerShellLambdaContext.cs $ARTIFACTS_DIR 23 | RUN mkdir $ARTIFACTS_DIR/modules 24 | RUN cp -r $RUNTIME_DIR/modules/ $ARTIFACTS_DIR/ 25 | RUN rm -Rf /tmp/aws-lambda-powershell-runtime 26 | # Merge all Private module content into a single .psm1 file to speed up module loading 27 | WORKDIR $ARTIFACTS_DIR/modules/Private 28 | RUN tail -n +3 -q $ARTIFACTS_DIR/modules/Private/*.ps1 >> $ARTIFACTS_DIR/modules/pwsh-runtime.psm1 29 | RUN rm -Rf $ARTIFACTS_DIR/modules/Private 30 | 31 | # Make bootstrap script executable 32 | RUN chmod +x /var/runtime/bootstrap 33 | 34 | ## Build final image 35 | FROM public.ecr.aws/lambda/provided:al2023 36 | ## Copy PowerShell runtime files 37 | COPY --from=runtime-files . / -------------------------------------------------------------------------------- /examples/demo-container-images-shared/readme.md: -------------------------------------------------------------------------------- 1 | # Demo-container-images-shared 2 | 3 | Demo application to deploy a PowerShell Lambda function using existing [container image](https://docs.aws.amazon.com/lambda/latest/dg/images-create.html) layers. The container image can be up to 10Gb in size which allows you to build functions larger than the 256MB limit for .zip archive functions. This allows you to include the entire [AWSTools for PowerShell](https://aws.amazon.com/powershell/) SDK, for example. 4 | 5 | The build process initially creates two base image layers which makes it easier to share these base layers with multiple functions: 6 | 7 | 1. PowerShell custom runtime based on ````provided.al2023````. This downloads the specified version of [PowerShell](https://github.com/PowerShell/PowerShell/releases/) and adds the custom runtime files from the [PowerShell-runtime](../../powershell-runtime/) folder. 8 | 2. The [AWSTools for PowerShell](https://aws.amazon.com/powershell/) with the entire AWS SDK. You can amend the loaded modules within the Dockerfile to only include specific modules. ````AWS.Tools.Common```` is required 9 | 10 | You can then create Lambda functions by importing the two image layers and then adding the function code in the [function](./function) folder. 11 | 12 | You build the initial base layers using [Docker Desktop](https://docs.docker.com/get-docker/) and the AWS CLI. 13 | 14 | ### Pre-requisites 15 | 16 | * [Docker Desktop](https://docs.docker.com/get-docker/) 17 | * [AWS Command Line Interface (AWS CLI)](https://aws.amazon.com/cli/) 18 | 19 | 1. Clone the repository and change into the example directory 20 | 21 | ```shell 22 | git clone https://github.com/awslabs/aws-lambda-powershell-runtime 23 | cd aws-lambda-powershell-runtime/examples/demo-container-images-shared 24 | ``` 25 | 26 | 2. Login to [Amazon Elastic Container Registry (ECR)](https://aws.amazon.com/ecr/) which is used to store the container images. Replace the `` and `` values. 27 | ```shell 28 | aws ecr get-login-password --region | docker login --username AWS --password-stdin .dkr.ecr..amazonaws.com 29 | ``` 30 | 31 | ## Build the PowerShell runtime base layer. 32 | 33 | 1. Change into the `powershell-runtime` directory 34 | 35 | ```shell 36 | cd powershell-runtime 37 | ``` 38 | 2. Create an ECR repository. Rename `--repository-name` from `powershell-runtime` to your prefered name if required. 39 | ```shell 40 | aws ecr create-repository --repository-name powershell-runtime 41 | ``` 42 | 43 | 3. Build the Docker image. Rename the image name in the following steps from `powershell-runtime:latest` if required. Replace the `` and `` values. 44 | ```shell 45 | docker build -t .dkr.ecr..amazonaws.com/powershell-runtime:latest . 46 | ``` 47 | 48 | 4. Push the Docker image. Replace the `` and `` values. 49 | ```shell 50 | docker push .dkr.ecr..amazonaws.com/powershell-runtime:latest 51 | ``` 52 | 53 | ## Build the PowerShell modules AWS Tools base layer. 54 | 55 | 1. Change into the `powershell-modules-aws-tools` directory 56 | 57 | ```shell 58 | cd ../powershell-modules-aws-tools 59 | ``` 60 | 2. Create an ECR repository. Rename `--repository-name` from `powershell-modules-aws-tools` to your prefered name if required. 61 | ```shell 62 | aws ecr create-repository --repository-name powershell-modules-aws-tools 63 | ``` 64 | 65 | 3. Build the Docker image. Rename the image name in the following steps from `powershell-modules-aws-tools:latest` if required. Replace the `` and `` values. 66 | ```shell 67 | docker build -t .dkr.ecr..amazonaws.com/powershell-modules-aws-tools:latest . 68 | ``` 69 | 70 | 4. Push the Docker image. Replace the `` and `` values. 71 | ```shell 72 | docker push .dkr.ecr..amazonaws.com/powershell-runtime:latest 73 | ``` 74 | 75 | ## Build the Lambda function 76 | 77 | The [Dockerfile](Dockerfile) for the container image then adds the previously created layers and adds the function code. 78 | 79 | You can then use the same process to build multiple Lambda functions using the same base layers which simplifies the build process and allows you to manage the base layers separately. 80 | ```Dockerfile 81 | #FROM public.ecr.aws/lambda/provided:al2023 82 | ## INSTALL POWERSHELL RUNTIME 83 | FROM .dkr.ecr..amazonaws.com/runtime-powershell:latest as runtime-files 84 | ## INSTALL AWS SDK 85 | FROM .dkr.ecr..amazonaws.com/powershell-modules-aws-tools:latest as module-files 86 | 87 | ## Build final image 88 | FROM public.ecr.aws/lambda/provided:al2023 89 | ## Copy PowerShell runtime files 90 | COPY --from=runtime-files . / 91 | ## Copy Module files 92 | COPY --from=module-files . / 93 | ## Function files 94 | COPY /function/ /var/task 95 | ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 96 | WORKDIR /var/task 97 | ENTRYPOINT [ "/var/runtime/bootstrap" ] 98 | CMD [ "examplehandler.ps1::handler" ] 99 | ``` 100 | 101 | 1. Change into the parent directory 102 | 103 | ```shell 104 | cd .. 105 | ``` 106 | 2. Create an ECR repository. Rename `--repository-name` from `demo-container-images-shared` to your prefered name if required. 107 | ```shell 108 | aws ecr create-repository --repository-name demo-container-images-shared 109 | ``` 110 | 111 | 3. Build the Docker image. Rename the image name in the following steps from `demo-container-images-shared:latest` if required. Replace the `` and `` values. 112 | ```shell 113 | docker build -t .dkr.ecr..amazonaws.com/demo-container-images-shared:latest . 114 | ``` 115 | 116 | 4. Push the Docker image. Replace the `` and `` values. 117 | ```shell 118 | docker push .dkr.ecr..amazonaws.com/demo-container-images-shared:latest 119 | ``` 120 | 121 | ### Create the Lambda function 122 | 1. Create a Lambda function execution IAM Role using the [documentation](https://docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html). 123 | 124 | 2. Create a Lambda function using the AWS CLI. Replace the `` and `` values. Enter the correct IAM Role name for `--role`. You can amend the `--memory-size` and `--timeout` if required. 125 | ```shell 126 | aws lambda create-function --region --function-name demo-container-images-shared --package-type Image --memory-size 1024 --timeout 30 --code ImageUri=.dkr.ecr..amazonaws.com/demo-container-images-shared:latest --role "arn:aws:iam:::role/lambda-exec-role" 127 | ``` 128 | 129 | To make further configuration changes, you can use `aws lambda update-function-configuration`. For example, to increase the timeout. 130 | 131 | ```shell 132 | aws lambda update-function-configuration --region --function-name demo-container-images-shared --timeout 45 133 | ``` 134 | ### Invoke the function using the AWS CLI 135 | 136 | Once the Lambda function is deployed, you can invoke it using the AWS CLI. 137 | 138 | 1. From a command prompt, invoke the function. Amend the `--function-name` and `--region` values for your function. 139 | 140 | This should return `"StatusCode": 200` for a successful invoke. 141 | 142 | ````shell 143 | aws lambda invoke --function-name demo-container-images-shared --region invoke-result 144 | ```` 145 | 146 | 2. View the function results which are outputted to `invoke-result`. 147 | 148 | ````shell 149 | cat invoke-result 150 | ```` 151 | 152 | ![cat-invoke-result.png](/img/cat-invoke-result.png) 153 | 154 | ## Build and deploy using [AWS Serverless Application Model (AWS SAM)](https://aws.amazon.com/serverless/sam/). 155 | 156 | You can also build and deploy the Lambda function using AWS SAM, once the base layers are built and pushed to the ECR repositories using Docker. 157 | 158 | ### Pre-requisites 159 | 160 | * [AWS Serverless Application Model (AWS SAM)](https://aws.amazon.com/serverless/sam/) 161 | * [AWS Command Line Interface (AWS CLI)](https://aws.amazon.com/cli/) 162 | 163 | ### Build the container image function 164 | 165 | 1. use `sam build` to build the container image. 166 | 167 | ```shell 168 | sam build 169 | ``` 170 | ### Test the function locally 171 | 172 | Once the build process is complete, you can use AWS SAM to test the function locally. 173 | 174 | ```shell 175 | sam local invoke 176 | ``` 177 | 178 | This uses a Lambda-like environment to run the function locally and returns the function response, which is the result of `Get-AWSRegion`. 179 | 180 | ![sam local invoke](/img/sam-local-invoke.png) 181 | 182 | ### Deploying to the AWS Cloud 183 | 184 | Use AWS SAM to deploy the resources to your AWS account. 185 | 186 | 1. Run a guided deployment to set the default parameters for the first deploy. 187 | 188 | ```shell 189 | sam deploy -g 190 | ``` 191 | For subsequent deployments you can use `sam deploy`. 192 | 193 | 2. Enter a **Stack Name** such as `demo-container-images-shared` and accept the remaining initial defaults. 194 | 195 | AWS SAM deploys the infrastructure and outputs the function name `Value`. 196 | 197 | ### Invoke the function using AWS SAM 198 | 199 | Once the Lambda function is deployed, you can invoke it in the cloud using AWS SAM `remote invoke`. 200 | 201 | 1. From a command prompt, invoke the function. Amend the `--stack-name` from `demo-container-images-shared` if required. 202 | 203 | ```shell 204 | sam remote invoke --stack-name demo-container-images-shared 205 | ``` 206 | 207 | This should return a successful invoke with the result of `Get-AWSRegion`. 208 | 209 | ### AWS SAM cleanup 210 | 211 | To delete the AWS resources created, run the following and confirm that you want to delete the resources that were created by this template. 212 | 213 | ````shell 214 | sam delete 215 | ```` 216 | 217 | -------------------------------------------------------------------------------- /examples/demo-container-images-shared/template.yml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: '2010-09-09' 2 | Transform: AWS::Serverless-2016-10-31 3 | Description: Demo to explore how the PowerShell custom runtime and a Lambda function work. 4 | ########################################################################## 5 | # Parameters & Globals # 6 | ########################################################################## 7 | Globals: 8 | Function: 9 | Tracing: Active 10 | Tags: 11 | Application: demo-container-images-shared 12 | Resources: 13 | ########################################################################## 14 | # Lambda functions # 15 | ########################################################################## 16 | DemoPowerShellFunction: 17 | Type: AWS::Serverless::Function 18 | Properties: 19 | Architectures: 20 | - x86_64 21 | Description: PowerShell-Lambda-Runtime Demo Function 22 | PackageType: Image 23 | MemorySize: 1024 24 | Timeout: 100 25 | Environment: 26 | Variables: 27 | DOTNET_SYSTEM_GLOBALIZATION_INVARIANT: '1' 28 | Metadata: 29 | Dockerfile: Dockerfile 30 | DockerContext: . 31 | DockerTag: demo-container-images-shared 32 | ########################################################################## 33 | # OUTPUTS # 34 | ########################################################################## 35 | Outputs: 36 | DemoPowerShellFunction: 37 | Value: !Ref DemoPowerShellFunction 38 | Description: PowerShell Lambda Function -------------------------------------------------------------------------------- /examples/demo-runtime-layer-function/build-layers.ps1: -------------------------------------------------------------------------------- 1 | $ProgressPreference = 'SilentlyContinue' 2 | 3 | $examplesPath = Split-Path -Path $PSScriptRoot -Parent 4 | $gitRoot = Split-Path -Path $examplesPath -Parent 5 | $layersRoot = Join-Path -Path $PSScriptRoot -ChildPath 'layers' 6 | 7 | #################### 8 | # PwshRuntimeLayer # 9 | #################### 10 | $runtimeLayerPath = Join-Path -Path $layersRoot -ChildPath 'runtimeLayer' 11 | $runtimeBuildScript = [System.IO.Path]::Combine($gitRoot, 'powershell-runtime', 'build-PwshRuntimeLayer.ps1') 12 | & $runtimeBuildScript -PwshArchitecture 'x64' -LayerPath $runtimeLayerPath 13 | 14 | ################# 15 | # AWSToolsLayer # 16 | ################# 17 | $awsToolsLayerPath = Join-Path -Path $layersRoot -ChildPath 'modulesLayer' 18 | $awsToolsBuildScript = [System.IO.Path]::Combine($gitRoot, 'powershell-modules', 'AWSToolsforPowerShell', 'Demo-AWS.Tools', 'build-AWSToolsLayer.ps1') 19 | & $awsToolsBuildScript -ModuleList 'AWS.Tools.Common' -LayerPath $awsToolsLayerPath 20 | 21 | ######################## 22 | # SAM Template Updates # 23 | ######################## 24 | $samTemplatePath = Join-Path -Path $PSScriptRoot -ChildPath 'template.yml' 25 | (Get-Content -Path $samTemplatePath -Raw).replace( 26 | 'ContentUri: ../../powershell-runtime/source', 'ContentUri: ./layers/runtimeLayer').replace( 27 | 'ContentUri: ../../powershell-modules/AWSToolsforPowerShell/Demo-AWS.Tools/buildlayer', 'ContentUri: ./layers/modulesLayer') | Set-Content -Path $samTemplatePath -Encoding ascii 28 | -------------------------------------------------------------------------------- /examples/demo-runtime-layer-function/function/Makefile: -------------------------------------------------------------------------------- 1 | build-DemoPowerShellFunction: 2 | cp -R . $(ARTIFACTS_DIR) 3 | rm $(ARTIFACTS_DIR)/Makefile -------------------------------------------------------------------------------- /examples/demo-runtime-layer-function/function/examplehandler.ps1: -------------------------------------------------------------------------------- 1 | #$VerbosePreference = "continue" 2 | #$VerbosePreference = "SilentlyContinue" 3 | Write-Verbose "Run script init tasks before handler" 4 | Write-Verbose "Importing Modules" 5 | Import-Module "AWS.Tools.Common" 6 | function handler 7 | { 8 | [cmdletbinding()] 9 | param( 10 | [parameter()] 11 | $LambdaInput, 12 | 13 | [parameter()] 14 | $LambdaContext 15 | ) 16 | Write-Verbose "Run handler function from script1" 17 | Write-Verbose "Function Remaining Time: $($LambdaContext.GetRemainingTimeInMillis())" 18 | Get-AWSRegion 19 | } 20 | -------------------------------------------------------------------------------- /examples/demo-runtime-layer-function/function/examplemodule/examplemodule.psd1: -------------------------------------------------------------------------------- 1 | # 2 | # Module manifest for module 'examplemodule' 3 | # 4 | 5 | @{ 6 | 7 | # Script module or binary module file associated with this manifest. 8 | RootModule = 'examplemodule.psm1' 9 | 10 | # Version number of this module. 11 | ModuleVersion = '0.5' 12 | 13 | # Supported PSEditions 14 | # CompatiblePSEditions = @() 15 | 16 | # ID used to uniquely identify this module 17 | GUID = '0ac30eba-99f3-4cd3-939b-fb5e1f8cdb64' 18 | 19 | # Author of this module 20 | Author = 'Amazon.com, Inc' 21 | 22 | # Company or vendor of this module 23 | CompanyName = 'Amazon Web Services' 24 | 25 | # Copyright statement for this module 26 | Copyright = '2022 Amazon Inc.' 27 | 28 | # Description of the functionality provided by this module 29 | Description = 'Provides example module to test PowerShell runtime on AWS Lambda' 30 | 31 | # Minimum version of the PowerShell engine required by this module 32 | # PowerShellVersion = '' 33 | 34 | # Name of the PowerShell host required by this module 35 | # PowerShellHostName = '' 36 | 37 | # Minimum version of the PowerShell host required by this module 38 | # PowerShellHostVersion = '' 39 | 40 | # Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. 41 | # DotNetFrameworkVersion = '' 42 | 43 | # Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. 44 | # ClrVersion = '' 45 | 46 | # Processor architecture (None, X86, Amd64) required by this module 47 | # ProcessorArchitecture = '' 48 | 49 | # Modules that must be imported into the global environment prior to importing this module 50 | # RequiredModules = @() 51 | 52 | # Assemblies that must be loaded prior to importing this module 53 | # RequiredAssemblies = @() 54 | 55 | # Script files (.ps1) that are run in the caller's environment prior to importing this module. 56 | # ScriptsToProcess = @() 57 | 58 | # Type files (.ps1xml) to be loaded when importing this module 59 | # TypesToProcess = @() 60 | 61 | # Format files (.ps1xml) to be loaded when importing this module 62 | # FormatsToProcess = @() 63 | 64 | # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess 65 | # NestedModules = @() 66 | 67 | # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. 68 | FunctionsToExport = @('examplehandler') 69 | 70 | # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. 71 | CmdletsToExport = @() 72 | 73 | # Variables to export from this module 74 | VariablesToExport = '*' 75 | 76 | # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. 77 | AliasesToExport = @() 78 | 79 | # DSC resources to export from this module 80 | # DscResourcesToExport = @() 81 | 82 | # List of all modules packaged with this module 83 | # ModuleList = @() 84 | 85 | # List of all files packaged with this module 86 | # FileList = @() 87 | 88 | # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. 89 | PrivateData = @{ 90 | 91 | PSData = @{ 92 | 93 | # Tags applied to this module. These help with module discovery in online galleries. 94 | # Tags = @() 95 | 96 | # A URL to the license for this module. 97 | # LicenseUri = '' 98 | 99 | # A URL to the main website for this project. 100 | # ProjectUri = '' 101 | 102 | # A URL to an icon representing this module. 103 | # IconUri = '' 104 | 105 | # ReleaseNotes of this module 106 | # ReleaseNotes = '' 107 | 108 | # Prerelease string of this module 109 | # Prerelease = '' 110 | 111 | # Flag to indicate whether the module requires explicit user acceptance for install/update/save 112 | # RequireLicenseAcceptance = $false 113 | 114 | # External dependent modules of this module 115 | # ExternalModuleDependencies = @() 116 | 117 | } # End of PSData hashtable 118 | 119 | } # End of PrivateData hashtable 120 | 121 | # HelpInfo URI of this module 122 | # HelpInfoURI = '' 123 | 124 | # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. 125 | # DefaultCommandPrefix = '' 126 | 127 | } -------------------------------------------------------------------------------- /examples/demo-runtime-layer-function/function/examplemodule/examplemodule.psm1: -------------------------------------------------------------------------------- 1 | Write-Verbose "Run module init tasks before handler" 2 | Write-Verbose "Importing Modules" 3 | Import-Module "AWS.Tools.Common" 4 | 5 | function examplehandler 6 | { 7 | [cmdletbinding()] 8 | param( 9 | [parameter()] 10 | $InputObject, 11 | 12 | [parameter()] 13 | $Context 14 | ) 15 | Write-Verbose "Run handler function from module" 16 | Get-AWSRegion 17 | } -------------------------------------------------------------------------------- /examples/demo-runtime-layer-function/function/examplescript.ps1: -------------------------------------------------------------------------------- 1 | Write-Verbose "Run script" 2 | Write-Verbose "Importing Modules" 3 | Import-Module "AWS.Tools.Common" 4 | Write-Verbose $LambdaInput 5 | Write-Verbose $LambdaContext 6 | Get-AWSRegion -------------------------------------------------------------------------------- /examples/demo-runtime-layer-function/readme.md: -------------------------------------------------------------------------------- 1 | # Demo-runtime-layer-function 2 | 3 | Initial demo application [demo-runtime-layer-function](examples/demo-runtime-layer-function/) uses AWS SAM to deploy the following: 4 | 5 | 1. PowerShell custom runtime based on ````provided.al2023```` as a Lambda layer. 6 | 2. Additional Lambda layer including the [AWSTools for PowerShell](https://aws.amazon.com/powershell/) with the following module. 7 | * ````AWS.Tools.Common```` 8 | 3. Both layers store their Amazon Resource Names (ARNs) as parameters in [AWS Systems Manager Parameter Store](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html) which can be referenced in other templates 9 | 4. Lambda function with three different handler options. 10 | 11 | To build the custom runtime and the AWS Tools for PowerShell layer for this example, AWS SAM uses a Makefile. This downloads the specified version of [PowerShell](https://github.com/PowerShell/PowerShell/releases/) and select modules from the [AWSTools](https://sdk-for-net.amazonwebservices.com/ps/v4/latest/AWS.Tools.zip) 12 | 13 | Windows does not natively support Makefiles. When using Windows, you can use either [Windows Subsystem for Linux (WSL)](https://docs.microsoft.com/en-us/windows/wsl/about), [Docker Desktop](https://docs.docker.com/get-docker/) or native PowerShell. 14 | 15 | ## Pre-requisites 16 | 17 | * [AWS Serverless Application Model (AWS SAM)](https://aws.amazon.com/serverless/sam/) 18 | * If building on Windows: 19 | * [Windows Subsystem for Linux (WSL)](https://docs.microsoft.com/en-us/windows/wsl/about) *or* 20 | * [Docker Desktop](https://docs.docker.com/get-docker/) *or* 21 | * [PowerShell for Windows](https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows) 22 | 23 | Clone the repository and change into the example directory 24 | 25 | ```shell 26 | git clone https://github.com/awslabs/aws-lambda-powershell-runtime 27 | cd aws-lambda-powershell-runtime/examples/demo-runtime-layer-function 28 | ``` 29 | 30 | Use one of the *"Build"* options, A,B,C, depending on your operating system and tools. 31 | 32 | ## A) Build using Linux or WSL 33 | 34 | Build the custom runtime, Lambda layer, and function packages using native Linux or WSL. 35 | 36 | *Note:* The `make` package is required for `sam build` to work. When building in Linux environments, including WSL, you may need to install `make` before this command will work. 37 | 38 | ```shell 39 | sam build --parallel 40 | ``` 41 | 42 | ![sam build --parallel](../../img/sam-build-parallel.png) 43 | 44 | ## B) Build using Docker 45 | 46 | You can build the custom runtime, Lambda layer, and function packages using Docker. This uses a Linux-based Lambda-like Docker container to build the packages. Use this option for Windows without WSL or as an isolated Mac/Linux build environment. 47 | 48 | ```shell 49 | sam build --parallel --use-container 50 | ``` 51 | 52 | ![sam build --parallel --use-container](/img/sam-build-parallel-use-container.png) 53 | 54 | ## C) Build using PowerShell for Windows 55 | 56 | You can use native PowerShell for Windows to download and extract the custom runtime and Lambda layer files. This performs the same file copy functionality as the Makefile. It adds the files to the source folders rather than a build location for subsequent deployment with AWS SAM. Use this option for Windows without WSL or Docker. 57 | 58 | ```shell 59 | .\build-layers.ps1 60 | ``` 61 | 62 | ![.\build-layers.ps1](/img/build-layers.png) 63 | 64 | ## Test the function locally 65 | 66 | Once the build process is complete, you can use AWS SAM to test the function locally. 67 | 68 | ```shell 69 | sam local invoke 70 | ``` 71 | 72 | This uses a Lambda-like environment to run the function locally and returns the function response, which is the result of `Get-AWSRegion`. 73 | 74 | ![sam local invoke](/img/sam-local-invoke.png) 75 | 76 | ## Deploying to the AWS Cloud 77 | 78 | Use AWS SAM to deploy the resources to your AWS account. Run a guided deployment to set the default parameters for the first deploy. 79 | 80 | ```shell 81 | sam deploy -g 82 | ``` 83 | 84 | For subsequent deployments you can use `sam deploy`. 85 | 86 | Enter a **Stack Name** and accept the remaining initial defaults. 87 | 88 | ![sam deploy -g](/img/sam-deploy-g.png) 89 | 90 | AWS SAM deploys the infrastructure and outputs the details of the resources. 91 | 92 | ![AWS SAM resources](/img/aws-sam-resources.png) 93 | 94 | ### View, edit, and invoke the function in the AWS Management Console 95 | 96 | You can view, edit code, and invoke the Lambda function in the Lambda Console. 97 | 98 | Navigate to the *Functions* page and choose the function specified in the `sam deploy` *Outputs*. 99 | 100 | Using the built-in [code editor](https://docs.aws.amazon.com/lambda/latest/dg/foundation-console.html#code-editor), you can view the function code. 101 | 102 | This function imports the ````AWS.Tools.Common```` module during the init process. The function handler runs and returns the output of ````Get-AWSRegion````. 103 | 104 | ![lambda-console-code](/img/lambda-console-code.png) 105 | 106 | To invoke the function, select the **Test** button and create a test event. For more information on invoking a function with a test event, see the [documentation](https://docs.aws.amazon.com/lambda/latest/dg/getting-started-create-function.html#get-started-invoke-manually). 107 | 108 | You can see the results in the *Execution result* pane. 109 | 110 | You can also view a snippet of the generated *Function Logs* below the *Response*. View the full logs in [Amazon CloudWatch Logs](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs). You can navigate directly via the *Monitor* tab. 111 | 112 | ![lambda-console-test](/img/lambda-console-test.png) 113 | 114 | ## Invoke the function using the AWS CLI 115 | 116 | From a command prompt, invoke the function. Amend the `--function-name` and `--region` values for your function. This should return `"StatusCode": 200` for a successful invoke. 117 | 118 | ````shell 119 | aws lambda invoke --function-name "aws-lambda-powershell-runtime-Function-6W3bn1znmW8G" --region us-east-1 invoke-result 120 | ```` 121 | 122 | View the function results which are outputted to `invoke-result`. 123 | 124 | ````shell 125 | cat invoke-result 126 | ```` 127 | 128 | ![cat-invoke-result.png](/img/cat-invoke-result.png) 129 | 130 | ## Invoke the function using the AWS Tools for PowerShell 131 | 132 | You can invoke the Lambda function using the AWS Tools for PowerShell and capture the response in a variable. The response is available in the `Payload` property of the `$result` object which can be read using the .NET `StreamReader` class. 133 | 134 | ````shell 135 | $Response = Invoke-LMFunction -FunctionName aws-lambda-powershell-runtime-PowerShellFunction-HHdKLkXxnkUn -LogType Tail 136 | [System.IO.StreamReader]::new($Response.Payload).ReadToEnd() 137 | ```` 138 | 139 | This outputs the result of `AWS-GetRegion` 140 | 141 | ## Cleanup 142 | 143 | To delete the AWS resources created, run the following and confirm that you want to delete the resources that were created by this template. 144 | 145 | ````shell 146 | sam delete 147 | ```` 148 | -------------------------------------------------------------------------------- /examples/demo-runtime-layer-function/template.yml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: '2010-09-09' 2 | Transform: AWS::Serverless-2016-10-31 3 | Description: Demo to explore how the PowerShell custom runtime and a Lambda function work. 4 | ########################################################################## 5 | # Parameters & Globals # 6 | ########################################################################## 7 | Globals: 8 | Function: 9 | Tracing: Active 10 | Tags: 11 | Application: demo-runtime-layer-function 12 | Resources: 13 | ########################################################################## 14 | # Lambda functions # 15 | ########################################################################## 16 | DemoPowerShellFunction: 17 | Type: AWS::Serverless::Function 18 | Properties: 19 | Architectures: 20 | - x86_64 21 | Description: PowerShell-Lambda-Runtime Demo Function 22 | CodeUri: function/ 23 | Runtime: provided.al2023 24 | Handler: examplehandler.ps1::handler 25 | MemorySize: 1024 26 | Timeout: 100 27 | Layers: 28 | - !Ref PwshRuntimeLayer 29 | - !Ref DemoAWSToolsLayer 30 | Environment: 31 | Variables: 32 | DOTNET_SYSTEM_GLOBALIZATION_INVARIANT: '1' 33 | Metadata: 34 | BuildMethod: makefile 35 | ########################################################################## 36 | # Lambda layers # 37 | ########################################################################## 38 | PwshRuntimeLayer: 39 | Type: AWS::Serverless::LayerVersion 40 | Properties: 41 | Description: Lambda Layer containing PowerShell 42 | ContentUri: ../../powershell-runtime/source 43 | CompatibleRuntimes: 44 | - provided.al2 45 | - provided.al2023 46 | RetentionPolicy: Delete 47 | Metadata: 48 | BuildMethod: makefile 49 | DemoPwshRuntimeParameter: 50 | Type: AWS::SSM::Parameter 51 | Properties: 52 | Name: demo-lambda-powershell-runtime-latest-version-arn 53 | Description: PwshRuntime Layer Name 54 | Type: String 55 | Value: !Ref PwshRuntimeLayer 56 | 57 | DemoAWSToolsLayer: 58 | Type: AWS::Serverless::LayerVersion 59 | Properties: 60 | Description: Layer containing Demo-AWS.Tools 61 | ContentUri: ../../powershell-modules/AWSToolsforPowerShell/Demo-AWS.Tools/buildlayer 62 | CompatibleRuntimes: 63 | - provided.al2 64 | - provided.al2023 65 | RetentionPolicy: Delete 66 | Metadata: 67 | BuildMethod: makefile 68 | DemoAWSToolsParameter: 69 | Type: AWS::SSM::Parameter 70 | Properties: 71 | Name: lambda-powershell-DemoAWSTools-latest-version-arn 72 | Description: DemoAWSTools Layer Name 73 | Type: String 74 | Value: !Ref DemoAWSToolsLayer 75 | 76 | ########################################################################## 77 | # OUTPUTS # 78 | ########################################################################## 79 | Outputs: 80 | PwshRuntimeLayer: 81 | Value: !Ref PwshRuntimeLayer 82 | Description: PwshRuntimeLayer Layer ARN 83 | DemoAWSToolsLayer: 84 | Value: !Ref DemoAWSToolsLayer 85 | Description: DemoAWSToolsLayer Layer ARN 86 | DemoPowerShellFunction: 87 | Value: !Ref DemoPowerShellFunction 88 | Description: PowerShell Lambda Function -------------------------------------------------------------------------------- /examples/demo-s3-lambda-eventbridge/build-layers.ps1: -------------------------------------------------------------------------------- 1 | #################### 2 | # PwshRuntimeLayer # 3 | #################### 4 | ../../powershell-runtime/build-PwshRuntimeLayer.ps1 5 | ################# 6 | # AWSToolsLayer # 7 | ################# 8 | ../../powershell-modules/AWSToolsforPowerShell/AWS.Tools.S3EventBridge/build-AWSToolsLayer.ps1 -------------------------------------------------------------------------------- /examples/demo-s3-lambda-eventbridge/function/Makefile: -------------------------------------------------------------------------------- 1 | build-S3toEBFunction: 2 | cp -R . $(ARTIFACTS_DIR) 3 | rm $(ARTIFACTS_DIR)/Makefile -------------------------------------------------------------------------------- /examples/demo-s3-lambda-eventbridge/function/modules/demo-s3-lambda-eventbridge/demo-s3-lambda-eventbridge.psd1: -------------------------------------------------------------------------------- 1 | # 2 | # Module manifest for module 'examplemodule' 3 | # 4 | 5 | @{ 6 | 7 | # Script module or binary module file associated with this manifest. 8 | RootModule = 'demo-s3-lambda-eventbridge.psm1' 9 | 10 | # Version number of this module. 11 | ModuleVersion = '0.5' 12 | 13 | # Supported PSEditions 14 | # CompatiblePSEditions = @() 15 | 16 | # ID used to uniquely identify this module 17 | GUID = '06d44c75-5d03-4bbe-bab6-77e3faab9d71' 18 | 19 | # Author of this module 20 | Author = 'Amazon.com, Inc' 21 | 22 | # Company or vendor of this module 23 | CompanyName = 'Amazon Web Services' 24 | 25 | # Copyright statement for this module 26 | Copyright = '2022 Amazon Inc.' 27 | 28 | # Description of the functionality provided by this module 29 | Description = 'Provides example module to test PowerShell runtime on AWS Lambda' 30 | 31 | # Minimum version of the PowerShell engine required by this module 32 | # PowerShellVersion = '' 33 | 34 | # Name of the PowerShell host required by this module 35 | # PowerShellHostName = '' 36 | 37 | # Minimum version of the PowerShell host required by this module 38 | # PowerShellHostVersion = '' 39 | 40 | # Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. 41 | # DotNetFrameworkVersion = '' 42 | 43 | # Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. 44 | # ClrVersion = '' 45 | 46 | # Processor architecture (None, X86, Amd64) required by this module 47 | # ProcessorArchitecture = '' 48 | 49 | # Modules that must be imported into the global environment prior to importing this module 50 | # RequiredModules = @() 51 | 52 | # Assemblies that must be loaded prior to importing this module 53 | # RequiredAssemblies = @() 54 | 55 | # Script files (.ps1) that are run in the caller's environment prior to importing this module. 56 | # ScriptsToProcess = @() 57 | 58 | # Type files (.ps1xml) to be loaded when importing this module 59 | # TypesToProcess = @() 60 | 61 | # Format files (.ps1xml) to be loaded when importing this module 62 | # FormatsToProcess = @() 63 | 64 | # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess 65 | # NestedModules = @() 66 | 67 | # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. 68 | FunctionsToExport = @( 69 | 'handler' 70 | ) 71 | 72 | # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. 73 | CmdletsToExport = @() 74 | 75 | # Variables to export from this module 76 | VariablesToExport = '*' 77 | 78 | # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. 79 | AliasesToExport = @() 80 | 81 | # DSC resources to export from this module 82 | # DscResourcesToExport = @() 83 | 84 | # List of all modules packaged with this module 85 | # ModuleList = @() 86 | 87 | # List of all files packaged with this module 88 | # FileList = @() 89 | 90 | # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. 91 | PrivateData = @{ 92 | 93 | PSData = @{ 94 | 95 | # Tags applied to this module. These help with module discovery in online galleries. 96 | # Tags = @() 97 | 98 | # A URL to the license for this module. 99 | # LicenseUri = '' 100 | 101 | # A URL to the main website for this project. 102 | # ProjectUri = '' 103 | 104 | # A URL to an icon representing this module. 105 | # IconUri = '' 106 | 107 | # ReleaseNotes of this module 108 | # ReleaseNotes = '' 109 | 110 | # Prerelease string of this module 111 | # Prerelease = '' 112 | 113 | # Flag to indicate whether the module requires explicit user acceptance for install/update/save 114 | # RequireLicenseAcceptance = $false 115 | 116 | # External dependent modules of this module 117 | # ExternalModuleDependencies = @() 118 | 119 | } # End of PSData hashtable 120 | 121 | } # End of PrivateData hashtable 122 | 123 | # HelpInfo URI of this module 124 | # HelpInfoURI = '' 125 | 126 | # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. 127 | # DefaultCommandPrefix = '' 128 | 129 | } 130 | 131 | -------------------------------------------------------------------------------- /examples/demo-s3-lambda-eventbridge/function/modules/demo-s3-lambda-eventbridge/demo-s3-lambda-eventbridge.psm1: -------------------------------------------------------------------------------- 1 | Write-Verbose "Run module init tasks before handler" 2 | Write-Verbose "Importing Modules" 3 | Import-Module "AWS.Tools.Common" 4 | Import-Module "AWS.Tools.S3" 5 | Import-Module "AWS.Tools.EventBridge" 6 | 7 | function handler 8 | { 9 | [cmdletbinding()] 10 | param( 11 | [parameter()] 12 | $LambdaInput, 13 | 14 | [parameter()] 15 | $LambdaContext 16 | ) 17 | Write-Host "Getting S3 Object:Bucket Name: $($LambdaInput.Records[0].s3.bucket.name) Bucket key: $($LambdaInput.Records[0].s3.object.key)" 18 | ($CSVFile = Read-S3Object -BucketName $($LambdaInput.Records[0].s3.bucket.name) -Key $($LambdaInput.Records[0].s3.object.key) -File "/tmp/$($LambdaInput.Records[0].s3.object.key)" | Import-CSV) | Out-Null 19 | Write-Host "Parsing CSV file and sending to EventBridge Bus $env:DESTINATION_BUS" 20 | $CSVFile | ForEach-Object { 21 | $detail = ($_ | ConvertTo-Json).toString() 22 | $entry = [pscustomobject] @{ 23 | EventBusName = $env:DESTINATION_BUS 24 | Source = "demo-s3-lambda-eventbridge" 25 | resources = $($LambdaContext.InvokedFunctionArn) 26 | DetailType = "size-order" 27 | Detail = $detail 28 | } 29 | Write-EVBEvent -Entry @($entry) | Out-Null 30 | } 31 | } -------------------------------------------------------------------------------- /examples/demo-s3-lambda-eventbridge/readme.md: -------------------------------------------------------------------------------- 1 | # Demo-s3-lambda-eventbridge 2 | 3 | Demo to show an event-drive application in PowerShell. 4 | 5 | This post expands on the functionality introduced with the PowerShell custom runtime for [AWS Lambda](https://aws.amazon.com/lambda/). See the blog post Extending PowerShell on AWS Lambda with other services for more information on adding PowerShell modules. 6 | 7 | You can take also advantage of the event-driven nature of Lambda, which allows you to run Lambda functions in response to events. Events can include a file being uploaded to [Amazon S3](https://aws.amazon.com/s3/), a message placed on an [Amazon SQS](https://aws.amazon.com/sqs/) queue, a scheduled task using [Amazon EventBridge](https://aws.amazon.com/eventbridge/), or an HTTP request from [Amazon API Gateway](https://aws.amazon.com/api-gateway/). You can trigger a Lambda function from over 200 AWS services and software as a service (SaaS) applications and only pay for what you use. 8 | 9 | ## Demo application 10 | 11 | A clothing printing company needs to manage its t-shirt size and color inventory. The printers store t-shirt orders for each day in a .CSV file. The inventory service is one service that needs to receive the .CSV file. It parses the file and, for each order, records the details to manage stock deliveries. 12 | 13 | The stores upload the files to S3. This automatically invokes a PowerShell Lambda function, which is configured to respond to the S3 `ObjectCreated` event. The Lambda function receives the S3 object location as part of the `$LambdaInput` event object. It uses the AWS Tools for PowerShell to download the file from S3. It parses the contents and, for each line in the .CSV file, sends the individual order details as an event to an EventBridge event bus. 14 | 15 | In this example, there is a single rule to log the event to Amazon CloudWatch Logs to show the received event. You could extend this functionality to write different EventBridge rules. You could route each order, depending on the order details, to different targets. For example, you can send different color combinations to Amazon SQS queues which the dyeing service can read from to order dyes. You could send particular size combinations to another Lambda function which manages cloth orders. 16 | 17 | The demo application uses the [AWS Serverless Application Model (AWS SAM)](https://aws.amazon.com/serverless/sam/) to deploy the following resources: 18 | 19 | 1. PowerShell custom runtime. 20 | 1. Additional Lambda layer containing the `AWS.Tools.Common`, `AWS.Tools.S3`, and `AWS.Tools.EventBridge` modules from [AWSTools for PowerShell](https://aws.amazon.com/powershell/). The layer ARN is stored in Parameter Store. 21 | 1. S3 bucket to store .CSV files. 22 | 1. Lambda function triggered by S3 upload. 23 | 1. Custom EventBridge event bus and rule to send events to CloudWatch Logs. 24 | 25 | To build the custom runtime and the AWSTools for PowerShell layer, AWS SAM uses a Makefile. This downloads the specified version of PowerShell from and the AWSTools from 26 | 27 | Makefiles are not natively supported in Windows. When using Windows, you can use either [Windows Subsystem for Linux (WSL)](https://docs.microsoft.com/en-us/windows/wsl/about), [Docker Desktop](https://docs.docker.com/get-docker/) or native PowerShell. 28 | 29 | ### Pre-requisites 30 | 31 | * [AWS Serverless Application Model (AWS SAM)](https://aws.amazon.com/serverless/sam/) 32 | * If building on Windows: 33 | * [Windows Subsystem for Linux (WSL)](https://docs.microsoft.com/en-us/windows/wsl/about) *or* 34 | * [Docker Desktop](https://docs.docker.com/get-docker/) *or* 35 | * [PowerShell for Windows](https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows) 36 | 37 | Clone the repository and change into the example directory 38 | 39 | ```shell 40 | git clone https://github.com/awslabs/aws-lambda-powershell-runtime 41 | cd aws-lambda-powershell-runtime/examples/demo-s3-lambda-eventbridge 42 | ``` 43 | 44 | Use one of the *"Build"* options, A,B,C, depending on your operating system and tools. 45 | 46 | ### A. Build using Linux or WSL 47 | 48 | Build the custom runtime, Lambda layer, and function packages using native Linux or WSL. 49 | 50 | *Note:* The `make` package is required for `sam build` to work. When building in Linux environments, including WSL, you may need to install `make` before this command will work. 51 | 52 | ```shell 53 | sam build --parallel 54 | ``` 55 | 56 | ![sam build --parallel](../../img/sam-build-parallel.png) 57 | 58 | ### B. Build using Docker 59 | 60 | You can build the custom runtime, Lambda layer, and function packages using Docker. This uses a linux-based Lambda-like Docker container to build the packages. Use this option for Windows without WSL or as an isolated Mac/Linux build environment. 61 | 62 | ```shell 63 | sam build --parallel --use-container 64 | ``` 65 | 66 | ![sam build --parallel --use-container](/img/sam-build-parallel-use-container.png) 67 | 68 | ### C. Build using PowerShell for Windows 69 | 70 | You can use native PowerShell for Windows to download and extract the custom runtime and Lambda layer files. This performs the same file copy functionality as the Makefile. It adds the files to the source folders rather than a build location for subsequent deployment with AWS SAM. Use this option for Windows without WSL or Docker. 71 | 72 | ```shell 73 | .\build-layers.ps1 74 | ``` 75 | 76 | ![.\build-layers.ps1](/img/build-layers.png) 77 | 78 | ### Deploying to the AWS Cloud 79 | 80 | Use AWS SAM to deploy the resources to your AWS account. Run a guided deployment to set the default parameters for the first deploy. 81 | 82 | ```shell 83 | sam deploy -g 84 | ``` 85 | 86 | For subsequent deployments, you can use `sam deploy`. 87 | 88 | Enter a **Stack Name**. 89 | 90 | Enter a unique S3 **SourceBucketName**. 91 | You can use your AWS Account number to generate a unique name, for example `demo-s3-lambda-eventbridge-bucket-ACCOUNT_NUMBER`. 92 | 93 | Accept the remaining initial defaults. 94 | 95 | ![sam deploy -g](/img/s3-demo-sam-deploy-g.png) 96 | 97 | AWS SAM deploys the infrastructure and outputs the details of the resources. 98 | 99 | ![AWS SAM resources](/img/s3-demo-aws-sam-resources.png) 100 | 101 | ## Testing the event-driven application 102 | 103 | Use the AWS CLI or AWS Tools for PowerShell to copy the sample .CSV file to S3. Replace `BUCKET_NAME` with your S3 `SourceBucket` Name. 104 | 105 | ### AWS CLI 106 | 107 | ````shell 108 | aws s3 cp .\test.csv s3://BUCKET_NAME 109 | ```` 110 | 111 | ### AWSTools for PowerShell 112 | 113 | ````shell 114 | Write-S3Object -BucketName BUCKET_NAME -File .\test.csv 115 | ```` 116 | 117 | The S3 file copy generates an S3 notification event. This invokes the Lambda function, passing the S3 file location details as part of the function `$LambdaInput` event object. 118 | 119 | The function downloads the S3 .CSV file, parses the contents and sends the individual lines to EventBridge, which logs the events to CloudWatch Logs. 120 | 121 | Navigate to the CloudWatch Logs group `/aws/events/demo-s3-lambda-eventbridge`. 122 | 123 | You can see the individual events in logged from the S3 object. 124 | -------------------------------------------------------------------------------- /examples/demo-s3-lambda-eventbridge/template.yml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: '2010-09-09' 2 | Transform: AWS::Serverless-2016-10-31 3 | Description: demo-s3-lambda-eventbridge 4 | ########################################################################## 5 | # Parameters & Globals # 6 | ########################################################################## 7 | Parameters: 8 | SourceBucketName: 9 | Type: String 10 | Description: "REQUIRED: Unique S3 bucket name to use for the app." 11 | AllowedPattern: "[a-zA-Z][a-zA-Z0-9_-]*" 12 | LogRetentionInDays: 13 | Type: Number 14 | Default: 7 15 | Description: CloudWatch Logs retention period 16 | 17 | Globals: 18 | Function: 19 | Tracing: Active 20 | Tags: 21 | Application: demo-s3-lambda-eventbridge 22 | 23 | Resources: 24 | ########################################################################## 25 | # S3 Bucket # 26 | ########################################################################## 27 | SourceBucket: 28 | Type: AWS::S3::Bucket 29 | Properties: 30 | BucketName: !Ref SourceBucketName 31 | 32 | ########################################################################## 33 | # Lambda functions # 34 | ########################################################################## 35 | S3toEBFunction: 36 | Type: AWS::Serverless::Function 37 | Metadata: 38 | BuildMethod: makefile 39 | Properties: 40 | Description: PowerShell-Lambda-Runtime Demo Function 41 | CodeUri: function/ 42 | Runtime: provided.al2023 43 | Handler: Module::demo-s3-lambda-eventbridge::handler 44 | MemorySize: 1024 45 | Timeout: 100 46 | Layers: 47 | - !Ref PwshRuntimeLayer 48 | - !Ref AWSToolsS3EventBridgeLayer 49 | Policies: 50 | - S3ReadPolicy: 51 | BucketName: !Ref SourceBucketName 52 | - EventBridgePutEventsPolicy: 53 | EventBusName: !Ref PowerShellEventBus 54 | Environment: 55 | Variables: 56 | DESTINATION_BUS: !Ref PowerShellEventBus 57 | DOTNET_SYSTEM_GLOBALIZATION_INVARIANT: '1' 58 | Events: 59 | S3NewObjectEvent: 60 | Type: S3 61 | Properties: 62 | Bucket: !Ref SourceBucket 63 | Events: s3:ObjectCreated:* 64 | Filter: 65 | S3Key: 66 | Rules: 67 | - Name: suffix 68 | Value: ".csv" 69 | ########################################################################## 70 | # Lambda layers # 71 | ########################################################################## 72 | PwshRuntimeLayer: 73 | Type: AWS::Serverless::LayerVersion 74 | Properties: 75 | Description: Lambda Layer containing PowerShell 76 | ContentUri: ../../powershell-runtime/source 77 | CompatibleRuntimes: 78 | - provided.al2 79 | - provided.al2023 80 | LicenseInfo: 'Available under the MIT-0 license.' 81 | RetentionPolicy: Delete 82 | Metadata: 83 | BuildMethod: makefile 84 | 85 | AWSToolsS3EventBridgeLayer: 86 | Type: AWS::Serverless::LayerVersion 87 | Properties: 88 | Description: Layer containing AWSTools.S3EventBridge 89 | ContentUri: ../../powershell-modules/AWSToolsforPowerShell/AWS.Tools.S3EventBridge/buildlayer 90 | CompatibleRuntimes: 91 | - provided.al2 92 | - provided.al2023 93 | LicenseInfo: 'Available under the MIT-0 license.' 94 | RetentionPolicy: Delete 95 | Metadata: 96 | BuildMethod: makefile 97 | 98 | ########################################################################## 99 | # EventBridge Resources # 100 | ########################################################################## 101 | PowerShellEventBus: 102 | Type: AWS::Events::EventBus 103 | Properties: 104 | Name: demo-s3-lambda-eventbridge 105 | 106 | LogsRule: 107 | Type: AWS::Events::Rule 108 | Properties: 109 | EventBusName: !Ref PowerShellEventBus 110 | EventPattern: 111 | source: 112 | - 'demo-s3-lambda-eventbridge' 113 | account: 114 | - !Ref AWS::AccountId 115 | Targets: 116 | - Arn: !GetAtt LogGroupForEvents.Arn 117 | Id: LogTarget 118 | 119 | LogGroupForEvents: 120 | Type: AWS::Logs::LogGroup 121 | Properties: 122 | LogGroupName: /aws/events/demo-s3-lambda-eventbridge 123 | RetentionInDays: !Ref LogRetentionInDays 124 | 125 | LogGroupForEventsPolicy: 126 | Type: AWS::Logs::ResourcePolicy 127 | Properties: 128 | PolicyName: EventBridgeToCWLogsPolicy 129 | PolicyDocument: !Sub > 130 | { 131 | "Version": "2012-10-17", 132 | "Statement": [ 133 | { 134 | "Sid": "EventBridgetoCWLogsCreateLogStreamPolicy", 135 | "Effect": "Allow", 136 | "Principal": { 137 | "Service": [ 138 | "events.amazonaws.com" 139 | ] 140 | }, 141 | "Action": [ 142 | "logs:CreateLogStream" 143 | ], 144 | "Resource": [ 145 | "${LogGroupForEvents.Arn}" 146 | ] 147 | }, 148 | { 149 | "Sid": "EventBridgetoCWLogsPutLogEventsPolicy", 150 | "Effect": "Allow", 151 | "Principal": { 152 | "Service": [ 153 | "events.amazonaws.com" 154 | ] 155 | }, 156 | "Action": [ 157 | "logs:PutLogEvents" 158 | ], 159 | "Resource": [ 160 | "${LogGroupForEvents.Arn}" 161 | ], 162 | "Condition": { 163 | "ArnEquals": {"AWS:SourceArn": "${LogsRule.Arn}"} 164 | } 165 | } 166 | ] 167 | } 168 | 169 | ########################################################################## 170 | # OUTPUTS # 171 | ########################################################################## 172 | Outputs: 173 | PwshRuntimeLayer: 174 | Value: !Ref PwshRuntimeLayer 175 | Description: PwshRuntimeLayer Layer ARN 176 | AWSToolsS3EventBridgeLayer: 177 | Value: !Ref AWSToolsS3EventBridgeLayer 178 | Description: AWSToolsS3EventBridgeLayer Layer ARN 179 | S3toEBFunction: 180 | Value: !Ref S3toEBFunction 181 | Description: S3toEB Lambda Function 182 | SourceBucket: 183 | Value: !Ref SourceBucket 184 | Description: S3 Source Bucket for object storage 185 | PowerShellEventBus: 186 | Value: !Ref PowerShellEventBus 187 | Description: EventBridge custom event bus 188 | LogGroupForEvents: 189 | Value: !Ref LogGroupForEvents 190 | Description: CloudWatch log group for EventBridge rule 191 | 192 | -------------------------------------------------------------------------------- /examples/demo-s3-lambda-eventbridge/test.csv: -------------------------------------------------------------------------------- 1 | Store,Order,FirstName,LastName,Size,Color 2 | LDN,001,Joe,Blogs,M,Blue 3 | LDN,002,Mykola,Melnyk,S,Red 4 | LDN,003,Vuyokazi,Thembu,XS,Green 5 | LDN,004,Lisa,Svensson,XL,Scarlet 6 | LDN,005,Mario,Rossi,L,Orange 7 | LDN,006,Seán,Ó Rudaí,M,Green 8 | LDN,007,Erika,Mustermann,M,Yellow 9 | LDN,008,Jean,Dupont,S,Blue -------------------------------------------------------------------------------- /img/aws-cli-publish-layer-version.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awslabs/aws-lambda-powershell-runtime/402b46c1e2f1b349ff8313e1cd30da4c9edd78cc/img/aws-cli-publish-layer-version.png -------------------------------------------------------------------------------- /img/aws-sam-layer-resources.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awslabs/aws-lambda-powershell-runtime/402b46c1e2f1b349ff8313e1cd30da4c9edd78cc/img/aws-sam-layer-resources.png -------------------------------------------------------------------------------- /img/aws-sam-resources.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awslabs/aws-lambda-powershell-runtime/402b46c1e2f1b349ff8313e1cd30da4c9edd78cc/img/aws-sam-resources.png -------------------------------------------------------------------------------- /img/build-layers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awslabs/aws-lambda-powershell-runtime/402b46c1e2f1b349ff8313e1cd30da4c9edd78cc/img/build-layers.png -------------------------------------------------------------------------------- /img/build-modules-layer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awslabs/aws-lambda-powershell-runtime/402b46c1e2f1b349ff8313e1cd30da4c9edd78cc/img/build-modules-layer.png -------------------------------------------------------------------------------- /img/cat-invoke-result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awslabs/aws-lambda-powershell-runtime/402b46c1e2f1b349ff8313e1cd30da4c9edd78cc/img/cat-invoke-result.png -------------------------------------------------------------------------------- /img/lambda-console-code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awslabs/aws-lambda-powershell-runtime/402b46c1e2f1b349ff8313e1cd30da4c9edd78cc/img/lambda-console-code.png -------------------------------------------------------------------------------- /img/lambda-console-test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awslabs/aws-lambda-powershell-runtime/402b46c1e2f1b349ff8313e1cd30da4c9edd78cc/img/lambda-console-test.png -------------------------------------------------------------------------------- /img/s3-demo-aws-sam-resources.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awslabs/aws-lambda-powershell-runtime/402b46c1e2f1b349ff8313e1cd30da4c9edd78cc/img/s3-demo-aws-sam-resources.png -------------------------------------------------------------------------------- /img/s3-demo-sam-deploy-g.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awslabs/aws-lambda-powershell-runtime/402b46c1e2f1b349ff8313e1cd30da4c9edd78cc/img/s3-demo-sam-deploy-g.png -------------------------------------------------------------------------------- /img/sam-build-layer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awslabs/aws-lambda-powershell-runtime/402b46c1e2f1b349ff8313e1cd30da4c9edd78cc/img/sam-build-layer.png -------------------------------------------------------------------------------- /img/sam-build-parallel-use-container.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awslabs/aws-lambda-powershell-runtime/402b46c1e2f1b349ff8313e1cd30da4c9edd78cc/img/sam-build-parallel-use-container.png -------------------------------------------------------------------------------- /img/sam-build-parallel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awslabs/aws-lambda-powershell-runtime/402b46c1e2f1b349ff8313e1cd30da4c9edd78cc/img/sam-build-parallel.png -------------------------------------------------------------------------------- /img/sam-deploy-g.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awslabs/aws-lambda-powershell-runtime/402b46c1e2f1b349ff8313e1cd30da4c9edd78cc/img/sam-deploy-g.png -------------------------------------------------------------------------------- /img/sam-deploy-layer-g.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awslabs/aws-lambda-powershell-runtime/402b46c1e2f1b349ff8313e1cd30da4c9edd78cc/img/sam-deploy-layer-g.png -------------------------------------------------------------------------------- /img/sam-local-invoke.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awslabs/aws-lambda-powershell-runtime/402b46c1e2f1b349ff8313e1cd30da4c9edd78cc/img/sam-local-invoke.png -------------------------------------------------------------------------------- /powershell-modules/AWSToolsforPowerShell/AWS.Tools.All/build-AWSToolsLayer.ps1: -------------------------------------------------------------------------------- 1 | ################# 2 | # AWSToolsLayer # 3 | ################# 4 | Write-Host "Downloading AWSToolsLayer" -foregroundcolor "green" 5 | Write-Host $PSScriptRoot 6 | $stagePath = Join-Path -Path $PSScriptRoot -ChildPath '\buildlayer\stage' 7 | New-Item -Path $stagePath -ItemType Directory -Force | Out-Null 8 | $modulesPath = Join-Path -Path $PSScriptRoot -ChildPath '\buildlayer\modules' 9 | New-Item -Path $modulesPath -ItemType Directory -Force | Out-Null 10 | 11 | Write-Host "Downloading full AWSTools module to stage area:" $stagePath -foregroundcolor "green" 12 | Invoke-WebRequest -Uri https://sdk-for-net.amazonwebservices.com/ps/v4/latest/AWS.Tools.zip -OutFile $stagePath\AWS.Tools.zip 13 | 14 | ### Extract entire AWS.Tools modules to moduled area 15 | Write-Host 'Extracting full AWSTools module to: '$modulesPath 16 | Expand-Archive $stagePath\AWS.Tools.zip $modulesPath 17 | 18 | Write-Host "Deleting AWSTools stage area" -foregroundcolor "green" 19 | Remove-Item $stagePath -Recurse -------------------------------------------------------------------------------- /powershell-modules/AWSToolsforPowerShell/AWS.Tools.All/buildlayer/Makefile: -------------------------------------------------------------------------------- 1 | build-AWSToolsAllLayer: 2 | # Download AWSToolsLayer module binaries 3 | curl -L -o $(ARTIFACTS_DIR)/AWS.Tools.zip https://sdk-for-net.amazonwebservices.com/ps/v4/latest/AWS.Tools.zip 4 | mkdir -p $(ARTIFACTS_DIR)/modules 5 | 6 | # Extract Entire AWS.Tools modules 7 | unzip $(ARTIFACTS_DIR)/AWS.Tools.zip -d $(ARTIFACTS_DIR)/modules 8 | 9 | # Extract select AWS.Tools modules (AWS.Tools.Common required) 10 | # unzip $(ARTIFACTS_DIR)/AWS.Tools.zip 'AWS.Tools.Common/**/*' -d $(ARTIFACTS_DIR)/modules/ 11 | # unzip $(ARTIFACTS_DIR)/AWS.Tools.zip 'AWS.Tools.S3/**/*' -d $(ARTIFACTS_DIR)/modules/ 12 | # unzip $(ARTIFACTS_DIR)/AWS.Tools.zip 'AWS.Tools.EventBridge/**/*' -d $(ARTIFACTS_DIR)/modules/ 13 | 14 | rm $(ARTIFACTS_DIR)/AWS.Tools.zip -------------------------------------------------------------------------------- /powershell-modules/AWSToolsforPowerShell/AWS.Tools.All/template.yml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: '2010-09-09' 2 | Transform: AWS::Serverless-2016-10-31 3 | Description: powershell-layer-AWSTools.All 4 | ########################################################################## 5 | # Parameters & Globals # 6 | ########################################################################## 7 | Globals: 8 | Function: 9 | Tracing: Active 10 | Tags: 11 | Application: powershell-layer-AWSTools.All 12 | Resources: 13 | ########################################################################## 14 | # Lambda layers # 15 | ########################################################################## 16 | AWSToolsAllLayer: 17 | Type: AWS::Serverless::LayerVersion 18 | Properties: 19 | Description: Layer containing AWSTools.All 20 | ContentUri: buildlayer 21 | CompatibleRuntimes: 22 | - provided.al2 23 | - provided.al2023 24 | RetentionPolicy: Delete 25 | Metadata: 26 | BuildMethod: makefile 27 | AWSToolsAllParameter: 28 | Type: AWS::SSM::Parameter 29 | Properties: 30 | Name: lambda-powershell-AWSToolsAll-latest-version-arn 31 | Description: AWSToolsAll Layer Name 32 | Type: String 33 | Value: !Ref AWSToolsAllLayer 34 | 35 | ########################################################################## 36 | # OUTPUTS # 37 | ########################################################################## 38 | Outputs: 39 | AWSToolsAllLayer: 40 | Value: !Ref AWSToolsAllLayer 41 | Description: AWSToolsAllLayer Layer ARN -------------------------------------------------------------------------------- /powershell-modules/AWSToolsforPowerShell/AWS.Tools.Common/build-AWSToolsLayer.ps1: -------------------------------------------------------------------------------- 1 | ################# 2 | # AWSToolsLayer # 3 | ################# 4 | Write-Host "Downloading AWSToolsLayer" -foregroundcolor "green" 5 | Write-Host $PSScriptRoot 6 | $stagePath = Join-Path -Path $PSScriptRoot -ChildPath '\buildlayer\stage' 7 | New-Item -Path $stagePath -ItemType Directory -Force | Out-Null 8 | $modulesPath = Join-Path -Path $PSScriptRoot -ChildPath '\buildlayer\modules' 9 | New-Item -Path $modulesPath -ItemType Directory -Force | Out-Null 10 | 11 | Write-Host "Downloading full AWSTools module to stage area:" $stagePath -foregroundcolor "green" 12 | Invoke-WebRequest -Uri https://sdk-for-net.amazonwebservices.com/ps/v4/latest/AWS.Tools.zip -OutFile $stagePath\AWS.Tools.zip 13 | 14 | ### Extract entire AWS.Tools modules to stage area but only move over select AWS.Tools modules (AWS.Tools.Common required) 15 | Write-Host "Extracting full AWSTools module to stage area:" $stagePath -foregroundcolor "green" 16 | Expand-Archive $stagePath\AWS.Tools.zip $stagePath -Force 17 | 18 | Write-Host "Moving selected AWSTools modules to modules directory:"$modulesPath -foregroundcolor "green" 19 | Move-Item "$stagePath\AWS.Tools.Common" "$modulesPath" -Force 20 | # Move-Item "$stagePathe\AWS.Tools.S3" "$modulesPath" -Force 21 | # Move-Item "$stagePath\AWS.Tools.EventBridge" "$modulesPath" -Force 22 | 23 | Write-Host "Deleting AWSTools stage area" -foregroundcolor "green" 24 | Remove-Item $stagePath -Recurse -------------------------------------------------------------------------------- /powershell-modules/AWSToolsforPowerShell/AWS.Tools.Common/buildlayer/Makefile: -------------------------------------------------------------------------------- 1 | build-AWSToolsCommonLayer: 2 | # Download AWSToolsLayer module binaries 3 | curl -L -o $(ARTIFACTS_DIR)/AWS.Tools.zip https://sdk-for-net.amazonwebservices.com/ps/v4/latest/AWS.Tools.zip 4 | mkdir -p $(ARTIFACTS_DIR)/modules 5 | 6 | # Extract Entire AWS.Tools modules 7 | # unzip $(ARTIFACTS_DIR)/AWS.Tools.zip -d $(ARTIFACTS_DIR)/modules 8 | 9 | # Extract select AWS.Tools modules (AWS.Tools.Common required) 10 | unzip $(ARTIFACTS_DIR)/AWS.Tools.zip 'AWS.Tools.Common/**/*' -d $(ARTIFACTS_DIR)/modules/ 11 | # unzip $(ARTIFACTS_DIR)/AWS.Tools.zip 'AWS.Tools.S3/**/*' -d $(ARTIFACTS_DIR)/modules/ 12 | # unzip $(ARTIFACTS_DIR)/AWS.Tools.zip 'AWS.Tools.EventBridge/**/*' -d $(ARTIFACTS_DIR)/modules/ 13 | 14 | rm $(ARTIFACTS_DIR)/AWS.Tools.zip -------------------------------------------------------------------------------- /powershell-modules/AWSToolsforPowerShell/AWS.Tools.Common/template.yml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: '2010-09-09' 2 | Transform: AWS::Serverless-2016-10-31 3 | Description: powershell-layer-AWSTools.Common 4 | ########################################################################## 5 | # Parameters & Globals # 6 | ########################################################################## 7 | Globals: 8 | Function: 9 | Tracing: Active 10 | Tags: 11 | Application: powershell-layer-AWSTools.Common 12 | Resources: 13 | ########################################################################## 14 | # Lambda layers # 15 | ########################################################################## 16 | AWSToolsCommonLayer: 17 | Type: AWS::Serverless::LayerVersion 18 | Properties: 19 | Description: Layer containing AWSTools.Common 20 | ContentUri: buildlayer 21 | CompatibleRuntimes: 22 | - provided.al2 23 | - provided.al2023 24 | RetentionPolicy: Delete 25 | Metadata: 26 | BuildMethod: makefile 27 | AWSToolsCommonParameter: 28 | Type: AWS::SSM::Parameter 29 | Properties: 30 | Name: lambda-powershell-AWSToolsCommon-latest-version-arn 31 | Description: AWSToolsCommon Layer Name 32 | Type: String 33 | Value: !Ref AWSToolsCommonLayer 34 | 35 | ########################################################################## 36 | # OUTPUTS # 37 | ########################################################################## 38 | Outputs: 39 | AWSToolsCommonLayer: 40 | Value: !Ref AWSToolsCommonLayer 41 | Description: AWSToolsCommonLayer Layer ARN -------------------------------------------------------------------------------- /powershell-modules/AWSToolsforPowerShell/AWS.Tools.S3EventBridge/build-AWSToolsLayer.ps1: -------------------------------------------------------------------------------- 1 | ################# 2 | # AWSToolsLayer # 3 | ################# 4 | Write-Host "Downloading AWSToolsLayer" -foregroundcolor "green" 5 | Write-Host $PSScriptRoot 6 | $stagePath = Join-Path -Path $PSScriptRoot -ChildPath '\buildlayer\stage' 7 | New-Item -Path $stagePath -ItemType Directory -Force | Out-Null 8 | $modulesPath = Join-Path -Path $PSScriptRoot -ChildPath '\buildlayer\modules' 9 | New-Item -Path $modulesPath -ItemType Directory -Force | Out-Null 10 | 11 | Write-Host "Downloading full AWSTools module to stage area:" $stagePath -foregroundcolor "green" 12 | Invoke-WebRequest -Uri https://sdk-for-net.amazonwebservices.com/ps/v4/latest/AWS.Tools.zip -OutFile $stagePath\AWS.Tools.zip 13 | 14 | ### Extract entire AWS.Tools modules to stage area but only move over select AWS.Tools modules (AWS.Tools.Common required) 15 | Write-Host "Extracting full AWSTools module to stage area:" $stagePath -foregroundcolor "green" 16 | Expand-Archive $stagePath\AWS.Tools.zip $stagePath -Force 17 | 18 | Write-Host "Moving selected AWSTools modules to modules directory:"$modulesPath -foregroundcolor "green" 19 | Move-Item "$stagePath\AWS.Tools.Common" "$modulesPath" -Force 20 | Move-Item "$stagePath\AWS.Tools.S3" "$modulesPath" -Force 21 | Move-Item "$stagePath\AWS.Tools.EventBridge" "$modulesPath" -Force 22 | 23 | Write-Host "Deleting AWSTools stage area" -foregroundcolor "green" 24 | Remove-Item $stagePath -Recurse -------------------------------------------------------------------------------- /powershell-modules/AWSToolsforPowerShell/AWS.Tools.S3EventBridge/buildlayer/Makefile: -------------------------------------------------------------------------------- 1 | build-AWSToolsS3EventBridgeLayer: 2 | # Download AWSToolsLayer module binaries 3 | curl -L -o $(ARTIFACTS_DIR)/AWS.Tools.zip https://sdk-for-net.amazonwebservices.com/ps/v4/latest/AWS.Tools.zip 4 | mkdir -p $(ARTIFACTS_DIR)/modules 5 | 6 | # Extract Entire AWS.Tools modules 7 | # unzip $(ARTIFACTS_DIR)/AWS.Tools.zip -d $(ARTIFACTS_DIR)/modules 8 | 9 | # Extract select AWS.Tools modules (AWS.Tools.Common required) 10 | unzip $(ARTIFACTS_DIR)/AWS.Tools.zip 'AWS.Tools.Common/**/*' -d $(ARTIFACTS_DIR)/modules/ 11 | unzip $(ARTIFACTS_DIR)/AWS.Tools.zip 'AWS.Tools.S3/**/*' -d $(ARTIFACTS_DIR)/modules/ 12 | unzip $(ARTIFACTS_DIR)/AWS.Tools.zip 'AWS.Tools.EventBridge/**/*' -d $(ARTIFACTS_DIR)/modules/ 13 | 14 | rm $(ARTIFACTS_DIR)/AWS.Tools.zip -------------------------------------------------------------------------------- /powershell-modules/AWSToolsforPowerShell/AWS.Tools.S3EventBridge/template.yml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: '2010-09-09' 2 | Transform: AWS::Serverless-2016-10-31 3 | Description: powershell-layer-AWSTools.S3EventBridge 4 | ########################################################################## 5 | # Parameters & Globals # 6 | ########################################################################## 7 | Globals: 8 | Function: 9 | Tracing: Active 10 | Tags: 11 | Application: powershell-layer-AWSTools.S3EventBridge 12 | Resources: 13 | ########################################################################## 14 | # Lambda layers # 15 | ########################################################################## 16 | AWSToolsS3EventBridgeLayer: 17 | Type: AWS::Serverless::LayerVersion 18 | Properties: 19 | Description: Layer containing AWSTools.S3EventBridge 20 | ContentUri: buildlayer 21 | CompatibleRuntimes: 22 | - provided.al2 23 | - provided.al2023 24 | RetentionPolicy: Delete 25 | Metadata: 26 | BuildMethod: makefile 27 | AWSToolsS3EventBridgeParameter: 28 | Type: AWS::SSM::Parameter 29 | Properties: 30 | Name: lambda-powershell-AWSToolsS3EventBridge-latest-version-arn 31 | Description: AWSToolsS3EventBridge Layer Name 32 | Type: String 33 | Value: !Ref AWSToolsS3EventBridgeLayer 34 | 35 | ########################################################################## 36 | # OUTPUTS # 37 | ########################################################################## 38 | Outputs: 39 | AWSToolsS3EventBridgeLayer: 40 | Value: !Ref AWSToolsS3EventBridgeLayer 41 | Description: AWSToolsS3EventBridgeLayer Layer ARN -------------------------------------------------------------------------------- /powershell-modules/AWSToolsforPowerShell/Demo-AWS.Tools/build-AWSToolsLayer.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | A script to create a folder to be used as a Lambda layer containing the specified AWS.Tools modules. 4 | #> 5 | param ( 6 | # A list of AWS.Tools modules to embed in the Lambda layer. 7 | [string[]]$ModuleList = @('AWS.Tools.Common'), 8 | 9 | # The folder path where the layer content should be created. 10 | [ValidateNotNullOrEmpty()] 11 | [string]$LayerPath = ([System.IO.Path]::Combine($PSScriptRoot, 'layers', 'modulesLayer')), 12 | 13 | # The URL to the AWS.Tools zip file. 14 | [string]$AWSToolsSource = 'https://sdk-for-net.amazonwebservices.com/ps/v4/latest/AWS.Tools.zip', 15 | 16 | # The staging path where the AWS Tools for PowerShell will be extracted 17 | [string]$ModuleStagingPath = ([System.IO.Path]::Combine($PSScriptRoot, 'layers', 'staging')), 18 | 19 | # Can be used to prevent the downloading and expansions of the AWS.Tools source. 20 | [switch]$SkipZipFileExpansion 21 | ) 22 | 23 | function Log { 24 | param ( 25 | [Parameter(Position=0)] 26 | $Message, 27 | $ForegroundColor = 'Green' 28 | ) 29 | Write-Host "AWSToolsLayer: $Message" -ForegroundColor $ForegroundColor 30 | } 31 | 32 | $ProgressPreference = 'SilentlyContinue' 33 | Log 'Starting to build the AWS.Tools layer.' -ForegroundColor 'Yellow' 34 | 35 | Log "Using the layer path: '$LayerPath'." 36 | Log "Using the staging path: '$ModuleStagingPath'." 37 | 38 | if (Test-Path -Path $LayerPath -PathType Container) { 39 | $null = Remove-Item -Path $LayerPath -Recurse 40 | } 41 | 42 | $layerModulePath = Join-Path -Path $LayerPath -ChildPath 'modules' 43 | $LayerPath, $ModuleStagingPath | ForEach-Object { 44 | $null = New-Item -Path $_ -ItemType Directory -Force 45 | } 46 | 47 | if (-not $SkipZipFileExpansion) { 48 | Log "Downloading the AWS.Tools modules from '$AWSToolsSource'." 49 | $zipFile = Join-Path -Path $ModuleStagingPath -ChildPath 'AWS.Tools.zip' 50 | if (Test-Path -Path $AWSToolsSource -PathType Leaf) { 51 | $zipFile = $AWSToolsSource 52 | } else { 53 | Invoke-WebRequest -Uri $AWSToolsSource -OutFile $zipFile 54 | } 55 | 56 | Log 'Expanding the AWS.Tools zip file to the staging path.' 57 | Expand-Archive -Path $zipFile -DestinationPath $ModuleStagingPath -ErrorAction SilentlyContinue 58 | } 59 | 60 | $ModuleList | ForEach-Object { 61 | Log "Copying the '$_' module to the layer path." 62 | $awsModulePath = (Join-Path -Path $ModuleStagingPath -ChildPath $_) 63 | if (-not(Test-Path -Path $awsModulePath -PathType Container)) { 64 | throw "Cannot find the module '$_' in the staging path '$ModuleStagingPath'." 65 | } 66 | $destinationPath = Join-Path -Path $layerModulePath -ChildPath $_ 67 | $null = New-Item -Path $destinationPath -ItemType Directory 68 | Copy-Item -Path (Join-Path -Path $awsModulePath -ChildPath '*') -Destination $destinationPath -Recurse -Force 69 | } 70 | 71 | Log 'Updating the SAM template ContentUri.' 72 | $samTemplatePath = Join-Path -Path $PSScriptRoot -ChildPath 'template.yml' 73 | (Get-Content -Path $samTemplatePath -Raw).replace( 74 | 'ContentUri: ./buildlayer', 'ContentUri: ./layers/modulesLayer') | Set-Content -Path $samTemplatePath -Encoding ascii 75 | 76 | Remove-Item -Path $ModuleStagingPath -Recurse -Force 77 | 78 | Log 'Finished building the AWS.Tools layer.' -ForegroundColor 'Yellow' 79 | -------------------------------------------------------------------------------- /powershell-modules/AWSToolsforPowerShell/Demo-AWS.Tools/buildlayer/Makefile: -------------------------------------------------------------------------------- 1 | build-DemoAWSToolsLayer: 2 | # Download AWSToolsLayer module binaries 3 | curl -L -o $(ARTIFACTS_DIR)/AWS.Tools.zip https://sdk-for-net.amazonwebservices.com/ps/v4/latest/AWS.Tools.zip 4 | mkdir -p $(ARTIFACTS_DIR)/modules 5 | 6 | # Extract Entire AWS.Tools modules 7 | # unzip $(ARTIFACTS_DIR)/AWS.Tools.zip -d $(ARTIFACTS_DIR)/modules 8 | 9 | # Extract select AWS.Tools modules (AWS.Tools.Common required) 10 | unzip $(ARTIFACTS_DIR)/AWS.Tools.zip 'AWS.Tools.Common/**/*' -d $(ARTIFACTS_DIR)/modules/ 11 | # unzip $(ARTIFACTS_DIR)/AWS.Tools.zip 'AWS.Tools.S3/**/*' -d $(ARTIFACTS_DIR)/modules/ 12 | # unzip $(ARTIFACTS_DIR)/AWS.Tools.zip 'AWS.Tools.EventBridge/**/*' -d $(ARTIFACTS_DIR)/modules/ 13 | 14 | rm $(ARTIFACTS_DIR)/AWS.Tools.zip -------------------------------------------------------------------------------- /powershell-modules/AWSToolsforPowerShell/Demo-AWS.Tools/template.yml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: '2010-09-09' 2 | Transform: AWS::Serverless-2016-10-31 3 | Description: powershell-layer-Demo-AWS.Tools 4 | ########################################################################## 5 | # Parameters & Globals # 6 | ########################################################################## 7 | Globals: 8 | Function: 9 | Tracing: Active 10 | Tags: 11 | Application: powershell-layer-Demo-AWS.Tools 12 | Resources: 13 | ########################################################################## 14 | # Lambda layers # 15 | ########################################################################## 16 | DemoAWSToolsLayer: 17 | Type: AWS::Serverless::LayerVersion 18 | Properties: 19 | Description: Layer containing Demo-AWS.Tools 20 | ContentUri: ./buildlayer 21 | CompatibleRuntimes: 22 | - provided.al2 23 | - provided.al2023 24 | RetentionPolicy: Delete 25 | Metadata: 26 | BuildMethod: makefile 27 | DemoAWSToolsParameter: 28 | Type: AWS::SSM::Parameter 29 | Properties: 30 | Name: lambda-powershell-DemoAWSTools-latest-version-arn 31 | Description: DemoAWSTools Layer Name 32 | Type: String 33 | Value: !Ref DemoAWSToolsLayer 34 | 35 | ########################################################################## 36 | # OUTPUTS # 37 | ########################################################################## 38 | Outputs: 39 | DemoAWSToolsLayer: 40 | Value: !Ref DemoAWSToolsLayer 41 | Description: DemoAWSToolsLayer Layer ARN -------------------------------------------------------------------------------- /powershell-modules/AWSToolsforPowerShell/Demo-AWS.Tools/tests/build-AWSToolsLayer.Tests.ps1: -------------------------------------------------------------------------------- 1 | Describe 'build-AWSToolsLayer' { 2 | BeforeAll { 3 | $ProgressPreference = 'SilentlyContinue' 4 | 5 | $TempFolder = "TestDrive:\Testing" 6 | $StagingPath = "$TempFolder\StagingPath" 7 | $LayerPath = "$TempFolder\LayerPath" 8 | $ModulePath = Join-Path -Path $LayerPath -ChildPath 'modules' 9 | 10 | $null = New-Item -Path $TempFolder -ItemType Directory -Force 11 | $SourceZipFile = Join-Path -Path $TempFolder -ChildPath 'AWS.Tools.zip' 12 | 13 | # Downloading the AWS.Tools zip file to prevent repeated downloads during testing. 14 | $invokeWebRequest = @{ 15 | Uri = 'https://sdk-for-net.amazonwebservices.com/ps/v4/latest/AWS.Tools.zip' 16 | OutFile = $SourceZipFile 17 | } 18 | Invoke-WebRequest @invokeWebRequest 19 | 20 | $folder = Split-Path -Path $PSScriptRoot -Parent 21 | $sut = Join-Path -Path $folder -ChildPath 'build-AWSToolsLayer.ps1' 22 | 23 | # Prevent IDE warnings about variables not being used 24 | $null = $ModulePath, $StagingPath, $sut 25 | } 26 | 27 | AfterAll { 28 | if (Test-Path -Path $TempFolder) { 29 | $null = Remove-Item -Path $TempFolder -Recurse -Force 30 | } 31 | } 32 | 33 | BeforeEach { 34 | $StagingPath, $LayerPath, $ModulePath | ForEach-Object { 35 | if (Test-Path -Path $_) { 36 | $null = Remove-Item -Path $_ -Recurse 37 | } 38 | } 39 | 40 | # Prevent log statements 41 | function Write-Host {} 42 | } 43 | 44 | Context 'Successful Builds' { 45 | It 'Builds the layer with the AWS.Tools.Common module when provided defaults' { 46 | Test-Path -Path $ModulePath -PathType Container | Should -BeFalse 47 | 48 | & $sut -LayerPath $LayerPath -AWSToolsSource $SourceZipFile 49 | 50 | Test-Path -Path $ModulePath -PathType Container | Should -BeTrue 51 | 'AWS.Tools.Common' | ForEach-Object { 52 | $awsModulePath = Join-Path -Path $ModulePath -ChildPath $_ 53 | Test-Path -Path $awsModulePath -PathType Container | Should -BeTrue 54 | Get-ChildItem -Path $ModulePath -Recurse -Name "$_.psd1" -File | Should -HaveCount 1 55 | } 56 | } 57 | 58 | It 'Builds the layer with the correct AWS Tools for PowerShell modules when provided' -TestCases @( 59 | @{ModuleList = @('AWS.Tools.Common', 'AWS.Tools.S3')} 60 | ) { 61 | param ([string[]]$ModuleList) 62 | Test-Path -Path $ModulePath -PathType Container | Should -BeFalse 63 | 64 | & $sut -ModuleList $ModuleList -LayerPath $LayerPath -AWSToolsSource $SourceZipFile 65 | 66 | $ModuleList | ForEach-Object { 67 | Test-Path -Path (Join-Path -Path $ModulePath -ChildPath $_) -PathType Container | Should -BeTrue 68 | Get-ChildItem -Path $ModulePath -Recurse -Name "$_.psd1" -File | Should -HaveCount 1 69 | } 70 | } 71 | } 72 | 73 | Context 'Failures' { 74 | It 'Fails when an invalid AWS Tools for PowerShell module is provided' { 75 | { & $sut -ModuleList 'DoesNotExist' -LayerPath $LayerPath -AWSToolsSource $SourceZipFile } | Should -Throw 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /powershell-modules/AWSToolsforPowerShell/readme.md: -------------------------------------------------------------------------------- 1 | # AWS Tools for PowerShell 2 | 3 | You can build Lambda layers containing all or select modules from the AWS Tools for PowerShell. 4 | 5 | You add one or more layers to your functions, along with the [PowerShell custom runtime](../../powershell-runtime/). 6 | 7 | The process is a two stage process, first build the layer(s) and then deploy the layers to your AWS account. 8 | 9 | Windows does not natively support Makefiles. When using Windows, you can use either [Windows Subsystem for Linux (WSL)](https://docs.microsoft.com/en-us/windows/wsl/about), [Docker Desktop](https://docs.docker.com/get-docker/) or native PowerShell. 10 | 11 | ## Pre-requisites 12 | 13 | * [AWS Serverless Application Model (AWS SAM)](https://aws.amazon.com/serverless/sam/) or [AWS Command Line Interface (AWS CLI)](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) 14 | 15 | * If building on Windows: 16 | * [Windows Subsystem for Linux (WSL)](https://docs.microsoft.com/en-us/windows/wsl/about) *or* 17 | * [Docker Desktop](https://docs.docker.com/get-docker/) *or* 18 | * [PowerShell for Windows](https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows) 19 | 20 | ## Build stage 21 | 22 | Clone the repository and change into the modules directory. 23 | 24 | ```shell 25 | git clone https://github.com/awslabs/aws-lambda-powershell-runtime 26 | cd aws-lambda-powershell-runtime 27 | cd powershell-modules/AWSToolsforPowerShell 28 | ``` 29 | 30 | Change into the specific module collection directory that matches the modules you wish to install. 31 | 32 | To install all modules, use [AWS.Tools.All](https://github.com/awslabs/aws-lambda-powershell-runtime/tree/main/powershell-modules/AWSToolsforPowerShell/AWS.Tools.All) 33 | 34 | To install only the AWS.Tools.Common modules, use [AWS.Tools.Common](https://github.com/awslabs/aws-lambda-powershell-runtime/tree/main/powershell-modules/AWSToolsforPowerShell/AWS.Tools.Commonl) 35 | 36 | To install select AWS.Tools modules, you can amend the modules imported. 37 | 38 | The following example shows importing the modules for [S3 and EventBridge](https://github.com/awslabs/aws-lambda-powershell-runtime/tree/main/powershell-modules/AWSToolsforPowerShell/AWS.Tools.S3EventBridge) 39 | 40 | ```shell 41 | cd AWS.Tools.S3EventBridge 42 | ``` 43 | 44 | You can amend the [makefile](https://github.com/awslabs/aws-lambda-powershell-runtime/blob/main/powershell-modules/AWSToolsforPowerShell/AWS.Tools.S3EventBridge/Makefile) or [build-AWSToolsLayer.ps1](https://github.com/awslabs/aws-lambda-powershell-runtime/blob/main/powershell-modules/AWSToolsforPowerShell/AWS.Tools.S3EventBridge/build-AWSToolsLayer.ps1) files to selectively include or exclude any of the AWS Tools for PowerShell modules. 45 | 46 | Use one of the *"Build"* options, A,B,C, depending on your operating system and tools. 47 | 48 | ### A) Build using Linux or WSL with AWS SAM 49 | 50 | Build the Lambda layer using native Linux or WSL. 51 | 52 | *Note:* The `make` package is required for `sam build` to work. When building in Linux environments, including WSL, you may need to install `make` before this command will work. 53 | 54 | ```shell 55 | sam build 56 | ``` 57 | 58 | ![sam build](../../img/sam-build-layer.png) 59 | 60 | ### B) Build using Docker with AWS SAM 61 | 62 | You can build the Lambda layer using Docker. This uses a Linux-based Lambda-like Docker container to build the packages. Use this option for Windows without WSL or as an isolated Mac/Linux build environment. 63 | 64 | ```shell 65 | sam build --use-container 66 | ``` 67 | 68 | ### C) Build using PowerShell for Windows 69 | 70 | You can use native PowerShell for Windows to download and extract the Lambda layer files. This performs the same file copy functionality as the Makefile. It adds the files to the `buildlayer` folder rather than a temporary build location for subsequent deployment with AWS SAM or the AWS CLI. Use this option for Windows without WSL or Docker. 71 | 72 | ```shell 73 | .\build-AWSToolsLayer.ps1 74 | ``` 75 | 76 | ![.\build-modules-layer.png](/img/build-modules-layer.png) 77 | 78 | ## Deploy stage 79 | 80 | Use one of the *"Deploy"* options, A,B, to deploy the layer depending on your tools. 81 | 82 | ### A) Deploy using AWS SAM 83 | 84 | Use AWS SAM to deploy the resources to your AWS account. You can use AWS SAM even if you didn't use the tool in the build phase. Deploy either of the build A), B), or C) options. Run a guided deployment to set the default parameters for the first deploy. 85 | 86 | ```shell 87 | sam deploy -g 88 | ``` 89 | 90 | For subsequent deployments you can use `sam deploy`. 91 | 92 | Enter a **Stack Name** such as `AWSToolsCommon` and accept the remaining initial defaults. 93 | 94 | ![sam deploy layer -g](/img/sam-deploy-layer-g.png) 95 | 96 | AWS SAM deploys the infrastructure and outputs the details of the layer. Note the ARN value to add to your functions. 97 | 98 | ![AWS SAM resources](/img/aws-sam-layer-resources.png) 99 | 100 | #### Cleanup 101 | 102 | To delete the layer created, run the following and confirm that you want to delete the resources that were created by this template. 103 | 104 | ````shell 105 | sam delete 106 | ```` 107 | 108 | ### B) Deploy using AWS CLI 109 | 110 | If you built the layer using PowerShell for Windows, you can deploy to AWS without requiring AWS SAM. 111 | 112 | Zip up the layer files. 113 | 114 | ```shell 115 | cd buildlayer 116 | zip -FSr ../AWS.Tools.S3EventBridge.zip . 117 | cd .. 118 | ``` 119 | 120 | Use the AWS CLI to create the layer. Replace the `--layer-name`, and `--description` values. 121 | 122 | ```shell 123 | aws lambda publish-layer-version --layer-name "AWSToolsS3EventBridge" --zip-file "fileb://AWS.Tools.S3EventBridge.zip" --description "Layer containing AWSTools.S3EventBridge" --compatible-runtimes provided.al2 124 | ``` 125 | 126 | Note the `LayerVersionArn` value to add to your functions. 127 | 128 | ![aws-cli-publish-layer-version](/img/aws-cli-publish-layer-version.png) 129 | 130 | #### Cleanup 131 | 132 | Use the AWS CLI to delete the layer version created. If you need to delete all versions, repeat the command for all published versions. Replace the `--layer-name`, and `--version-number` values. 133 | 134 | ````shell 135 | aws lambda delete-layer-version --layer-name "AWSToolsS3EventBridge" --version-number 1 136 | ```` 137 | -------------------------------------------------------------------------------- /powershell-modules/VMwarePowerCLI/Makefile: -------------------------------------------------------------------------------- 1 | build-PowerCLILayer: 2 | # Copy and extract PowerShell binaries 3 | curl -L -o $(ARTIFACTS_DIR)/PowerCLI.zip https://vdc-download.vmware.com/vmwb-repository/dcr-public/fdf729aa-01f9-4129-87c7-1e7ce17c5e7b/1c6d21ef-d60e-472a-b2c2-ce8b83abe095/VMware-PowerCLI-12.5.0-19195797.zip 4 | mkdir -p $(ARTIFACTS_DIR)/modules 5 | 6 | rm $(ARTIFACTS_DIR)/PowerCLI.zip -------------------------------------------------------------------------------- /powershell-modules/VMwarePowerCLI/build-PowerCLILayer.ps1: -------------------------------------------------------------------------------- 1 | ################# 2 | # PowerCLILayer # 3 | ################# 4 | Write-Host "Downloading PowerCLILayer" -foregroundcolor "green" 5 | Save-Module -Name VMware.PowerCLI -Path $PSScriptRoot\PowerCLI 6 | -------------------------------------------------------------------------------- /powershell-modules/VMwarePowerCLI/template.yml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: '2010-09-09' 2 | Transform: AWS::Serverless-2016-10-31 3 | Description: powershell-layer-PowerCLI 4 | ########################################################################## 5 | # Parameters & Globals # 6 | ########################################################################## 7 | Globals: 8 | Function: 9 | Tracing: Active 10 | Tags: 11 | Application: powershell-layer-PowerCLI 12 | Resources: 13 | ########################################################################## 14 | # Lambda layers # 15 | ########################################################################## 16 | PowerCLILayer: 17 | Type: AWS::Serverless::LayerVersion 18 | Properties: 19 | LayerName: PowerCLI 20 | Description: Layer containing VMware PowerCLI 21 | ContentUri: PowerCLI 22 | CompatibleRuntimes: 23 | - provided.al2 24 | - provided.al2023 25 | RetentionPolicy: Delete 26 | Metadata: 27 | BuildMethod: makefile 28 | PowerCLIParameter: 29 | Type: AWS::SSM::Parameter 30 | Properties: 31 | Name: lambda-powershell-PowerCLI-latest-version-arn 32 | Description: VMware PowerCLI Layer Name 33 | Type: String 34 | Value: !Ref PowerCLILayer 35 | 36 | ########################################################################## 37 | # OUTPUTS # 38 | ########################################################################## 39 | Outputs: 40 | PowerCLILayer: 41 | Value: !Ref PowerCLILayer 42 | Description: PowerCLILayer Layer ARN -------------------------------------------------------------------------------- /powershell-modules/readme.md: -------------------------------------------------------------------------------- 1 | # Powershell-modules 2 | 3 | Installation instructions to build Lambda layers containing various PowerShell modules for use with the PowerShell custom runtime. 4 | 5 | Deploy the example [demo-runtime-layer-function](../examples/demo-runtime-layer-function/) to explore how the runtime, modules, and PowerShell function work. 6 | 7 | See further instructions within the subfolders 8 | 9 | | Module | Description | 10 | |:---|:---| 11 | |[AWSToolsforPowerShell](powershell-modules/AWSToolsforPowerShell/)|AWS Tools for PowerShell | 12 | |[VMwarePowerCLI](powershell-modules/VMwarePowerCLI/)|VMware PowerCLI| 13 | -------------------------------------------------------------------------------- /powershell-runtime/build-PwshRuntimeLayer.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | A script to create a folder to be used as the PowerShell Runtime Layer. 4 | #> 5 | param ( 6 | # The version of PowerShell to use for the runtime 7 | [string]$PwshVersion = '7.4.5', 8 | 9 | # The desired CPU architecture for the runtime 10 | [ValidateSet('arm64', 'x64')] 11 | [string]$PwshArchitecture = 'x64', 12 | 13 | [ValidateNotNullOrEmpty()] 14 | [string]$LayerPath = ([System.IO.Path]::Combine($PSScriptRoot, 'layers', 'runtimeLayer')) 15 | ) 16 | 17 | function Log { 18 | param ( 19 | [Parameter(Position=0)] 20 | $Message, 21 | $ForegroundColor = 'Green' 22 | ) 23 | Write-Host "PwshRuntimeLayer: $Message" -ForegroundColor $ForegroundColor 24 | } 25 | 26 | $ProgressPreference = 'SilentlyContinue' 27 | Log 'Starting to build the PowerShell Runtime layer.' -ForegroundColor 'Yellow' 28 | 29 | $sourcePath = Join-Path -Path $PSScriptRoot -ChildPath 'source' 30 | 31 | Log "Using the layer path: '$LayerPath'." 32 | 33 | # Copy the source files into the layer path, then change the source path to the layerpath 34 | if (Test-Path -Path $LayerPath) { 35 | Log 'Cleaning the layer path.' 36 | $null = Remove-Item -Path $LayerPath -Recurse 37 | } 38 | 39 | $null = New-Item -Path $LayerPath -ItemType Directory -Force 40 | Log 'Copying the PwshRuntime source to the layer path.' 41 | Copy-Item -Path (Join-Path -Path $sourcePath -ChildPath '*') -Destination $LayerPath -Recurse 42 | 43 | Log "Using the layer path: '$LayerPath'." 44 | $modulePath = Join-Path -Path $LayerPath -ChildPath 'modules' 45 | $moduleFilePath = Join-Path -Path $modulePath -ChildPath 'pwsh-runtime.psm1' 46 | $privateFunctionPath = Join-Path -Path $modulePath -ChildPath 'Private' 47 | 48 | $powershellPath = Join-Path -Path $LayerPath -ChildPath 'powershell' 49 | $tarFile = Join-Path -Path $LayerPath -ChildPath "powershell-$PwshVersion-$PwshArchitecture.tar.gz" 50 | 51 | $githubSource = "https://github.com/PowerShell/PowerShell/releases/download/v$PwshVersion/powershell-$PwshVersion-linux-$PwshArchitecture.tar.gz" 52 | Log "Downloading the PowerShell runtime from '$githubSource'." 53 | Invoke-WebRequest -Uri $githubSource -OutFile $tarFile 54 | 55 | Log "Extracting the PowerShell runtime to '$powershellPath'." 56 | if (-not(Test-Path -Path $powershellPath)) {$null = New-Item -ItemType Directory -Force -Path $powershellPath} 57 | tar zxf $tarFile -C $powershellPath 58 | Remove-Item -Path $tarFile -Force 59 | 60 | Log 'Copying additional runtime files, including bootstrap.' 61 | if (-not(Select-String -Path $moduleFilePath -Pattern 'private:Get-Handler')) { 62 | Get-ChildItem -Path $privateFunctionPath -Filter '*.ps1' | ForEach-Object { 63 | Get-Content $_.FullName | Select-Object -Skip 2 | Out-File -FilePath $moduleFilePath -Append -Encoding ascii 64 | } 65 | Remove-Item -Path $privateFunctionPath -Force -Recurse 66 | } else { 67 | Log 'Private modules likely merged already, skipping.' 68 | } 69 | 70 | Log 'Removing the Makefile from the layer path.' 71 | Remove-Item -Path (Join-Path -Path $LayerPath -ChildPath 'Makefile') -ErrorAction SilentlyContinue 72 | 73 | Log 'Updating the SAM template ContentUri.' 74 | $samTemplatePath = Join-Path -Path $PSScriptRoot -ChildPath 'template.yml' 75 | (Get-Content -Path $samTemplatePath -Raw).replace( 76 | 'ContentUri: ./source', 'ContentUri: ./layers/runtimeLayer') | Set-Content -Path $samTemplatePath -Encoding ascii 77 | 78 | Log 'Finished building the PowerShell Runtime layer.' -ForegroundColor 'Yellow' 79 | -------------------------------------------------------------------------------- /powershell-runtime/readme.md: -------------------------------------------------------------------------------- 1 | # PowerShell-runtime 2 | 3 | Contains the PowerShell custom runtime based on ````provided.al2023```` with a number of deployment methods. 4 | 5 | Deploy the example [demo-runtime-layer-function](../examples/demo-runtime-layer-function/) to explore how the runtime and PowerShell function work. 6 | 7 | ## Deploying the PowerShell custom runtime 8 | 9 | You can build the custom runtime using a number of tools, including the the [AWS Command Line Interface (AWS CLI)](https://aws.amazon.com/cli/), or with infrastructure as code tools such as [AWS CloudFormation](https://aws.amazon.com/cloudformation/), [AWS Serverless Application Model (AWS SAM)](https://aws.amazon.com/serverless/sam/), [Serverless Framework](https://serverless.com/framework/), and [AWS Cloud Development Kit (AWS CDK)](https://aws.amazon.com/cdk/). 10 | 11 | ## AWS SAM 12 | 13 | AWS SAM deploys the custom runtime as a Lambda layer. You can amend the template to also stores the resulting layer name in AWS Systems Manager Parameter Store for easier reference in other templates 14 | 15 | To build the custom runtime layer, AWS SAM uses a Makefile. This downloads the specified version of [PowerShell](https://github.com/PowerShell/PowerShell/releases/). 16 | 17 | Windows does not natively support Makefiles. When using Windows, you can use either [Windows Subsystem for Linux (WSL)](https://docs.microsoft.com/en-us/windows/wsl/about), [Docker Desktop](https://docs.docker.com/get-docker/) or native PowerShell. 18 | 19 | Clone the repository and change into the runtime directory 20 | 21 | ```shell 22 | git clone https://github.com/awslabs/aws-lambda-powershell-runtime 23 | cd aws-lambda-powershell-runtime 24 | cd powershell-runtime 25 | ``` 26 | 27 | Use one of the *"Build"* options, A,B,C, depending on your operating system and tools. 28 | 29 | ### A) Build using Linux or WSL 30 | 31 | Build the custom runtime using native Linux or WSL. 32 | 33 | *Note:* The `make` package is required for `sam build` to work. When building in Linux environments, including WSL, you may need to install `make` before this command will work. 34 | 35 | ```shell 36 | sam build --parallel 37 | ``` 38 | 39 | ### B) Build using Docker 40 | 41 | You can build the custom runtime using Docker. This uses a Linux-based Lambda-like Docker container to build the packages. Use this option for Windows without WSL or as an isolated Mac/Linux build environment. 42 | 43 | ```shell 44 | sam build --parallel --use-container 45 | ``` 46 | 47 | ### C) Build using PowerShell for Windows 48 | 49 | You can use native PowerShell for Windows to download and extract the custom runtime files. This performs the same file copy functionality as the Makefile. It adds the files to the source folders rather than a build location for subsequent deployment with AWS SAM. Use this option for Windows without WSL or Docker. 50 | 51 | ```shell 52 | .\build-PwshRuntimeLayer 53 | ``` 54 | 55 | ### Deploying to the AWS Cloud 56 | 57 | Use AWS SAM to deploy the runtime and optional SSM parameter to your AWS account. Run a guided deployment to set the default parameters for the first deploy. 58 | 59 | ```shell 60 | sam deploy -g 61 | ``` 62 | 63 | For subsequent deployments you can use `sam deploy`. 64 | 65 | Enter a **Stack Name** such as `powershell-runtime` and accept the remaining initial defaults. 66 | 67 | ### [AWS Command Line Interface (AWS CLI)](https://aws.amazon.com/cli/) 68 | 69 | coming soon... 70 | 71 | ## Powershell runtime information 72 | 73 | ### Variables 74 | 75 | The runtime defines the following variables which are made available to the Lambda function. 76 | 77 | | Variable | Description | 78 | |:---|:---| 79 | |`$LambdaInput`|A PSObject that contains the Lambda function input event data. | 80 | |`$LambdaContext`|An `Amazon.Lambda.PowerShell.Internal` object that contains information about the currently running Lambda environment.| 81 | 82 | ### Lambda context object in PowerShell 83 | 84 | When Lambda runs your function, it passes context information by making a `$LambdaContext` variable available to the script, module, or handler. This variable provides methods and properties with information about the invocation, function, and execution environment. 85 | 86 | #### Context methods 87 | 88 | * `getRemainingTimeInMillis` – Returns the number of milliseconds left before the invocation times out. 89 | 90 | #### Context properties 91 | 92 | * `FunctionName` – The name of the Lambda function. 93 | * `FunctionVersion` – The [version](https://docs.aws.amazon.com/lambda/latest/dg/configuration-versions.html) of the function. 94 | * `InvokedFunctionArn` – The Amazon Resource Name (ARN) that's used to invoke the function. * Indicates if the invoker specified a version number or alias. 95 | * `MemoryLimitInMB` – The amount of memory that's allocated for the function. 96 | * `AwsRequestId` – The identifier of the invocation request. 97 | * `LogGroupName` – The log group for the function. 98 | * `LogStreamName` – The log stream for the function instance. 99 | * `RemainingTime` – The number of milliseconds left before the execution times out. 100 | * `Identity` – (synchronous requests) Information about the Amazon Cognito identity that authorized the request. 101 | * `ClientContext` – (synchronous requests) Client context that's provided to Lambda by the client application. 102 | * `Logger` – The [logger](https://docs.aws.amazon.com/lambda/latest/dg/powershell-logging.html) object for the function. 103 | 104 | ### Lambda handler options 105 | 106 | There are three different Lambda handler formats supported with this runtime. 107 | | handler | Description | 108 | |:---|:---| 109 | |``| Run entire PowerShell script | 110 | | `::` | PowerShell scripts that include a function handler | 111 | | `Module::::` | PowerShell modules that include a function handler | 112 | 113 | #### `` 114 | 115 | You provide a PowerShell script that is the handler. Lambda runs the entire script on each invoke. `$LambdaInput` and `$LambdaContext` are made available during the script invocation. 116 | 117 | This experience mimics the existing .NET Core-based PowerShell implementation. 118 | 119 | #### `::` 120 | 121 | You provide a PowerShell script that includes a PowerShell function name.The PowerShell function name is the handler. 122 | 123 | The PowerShell runtime [dot-sources](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_scripts#script-scope-and-dot-sourcing) the specified ``. This allows you to run PowerShell code during the function initialization cold start process. Lambda then invokes the PowerShell handler function `` with two positional input parameters, `$LambdaInput` and `$LambdaContext`. On subsequent invokes using the same runtime environment, Lambda invokes only the handler function ``. 124 | 125 | This experience mimics the existing PowerShell .NET Core implementation when a PowerShell function handler is specified. 126 | 127 | #### `Module::::` 128 | 129 | You provide a PowerShell module. You include a PowerShell function as the handler within the module. Add the PowerShell module using a [Lambda Layer](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html) or by including the module in the Lambda function code package. 130 | 131 | The PowerShell runtime imports the specified ``. This allows you to run PowerShell code during the module initialization cold start process. Lambda then invokes the PowerShell handler function `function_name>` with two positional input parameters, `$LambdaInput` and `$LambdaContext`. On subsequent invokes using the same runtime environment, Lambda invokes only the handler function ``. 132 | 133 | This experience mimics the existing PowerShell .NET Core implementation when a PowerShell module and function handler is specified. 134 | 135 | ### PowerShell module support 136 | 137 | You can include additional PowerShell modules either via a Lambda Layer, or within your function code package, or container image. Using Lambda layers provides a convenient way to package and share modules that you can use with your Lambda functions. Layers reduce the size of uploaded deployment archives and make it faster to deploy your code. 138 | 139 | The `PSModulePath` environment variable contains a list of folder locations that are searched to find user-supplied modules. This is configured during the runtime initialization. Folders are specified in the following order: 140 | 141 | **1. Modules as part of function package in a `/modules` subfolder.** 142 | 143 | You can include PowerShell modules inside the published Lambda function package. This folder is first in the list for module imports. `<$env:LAMBDA_TASK_ROOT>` is the function root package folder which is extracted to `/var/task` within the Lambda runtime environment. Use the following folder structure in your package: 144 | 145 | `<$env:LAMBDA_TASK_ROOT>/modules///` 146 | 147 | **2. Modules as part of Lambda layers in a `/modules` subfolder.** 148 | 149 | You can publish Lambda Layers that include PowerShell modules. This allows you to share modules across functions and accounts. Lambda layers are extracted to `/opt` within the Lambda runtime environment. This is the preferred solution to use modules with multiple functions. Use the following folder structure in your package: 150 | 151 | `/modules///` 152 | 153 | **3. Modules as part of the PowerShell custom runtime layer in a `/modules` subfolder.** 154 | 155 | Default modules within the PowerShell runtime layer. You can include additional user modules. Create the layer using the following folder structure: 156 | 157 | `/powershell/modules///` 158 | 159 | ### Function logging and metrics 160 | 161 | AWS Lambda automatically monitors Lambda functions on your behalf and sends function metrics to [Amazon CloudWatch](https://aws.amazon.com/cloudwatch/). Your Lambda function comes with a CloudWatch Logs log group and a log stream for each instance of your function. The Lambda runtime environment sends details about each invocation to the log stream, and relays logs and other output from your function’s code. For more information, see the [documentation](https://docs.aws.amazon.com/lambda/latest/dg/powershell-logging.html). 162 | 163 | Output from `Write-Host`, `Write-Verbose`, `Write-Warning`, and `Write-Error` is written to the function log stream. The output from `Write-Output` is added to the pipeline, which you can use with your function response. 164 | 165 | ### Error handling 166 | 167 | The runtime can terminate your function because it ran out of time, detected a syntax error, or failed to marshal the response object into JSON. 168 | 169 | Your function code can throw an exception or return an error object. Lambda writes the error to CloudWatch Logs and, for synchronous invocations, also returns the error in the function response output. 170 | 171 | See the [documentation](https://docs.aws.amazon.com/lambda/latest/dg/powershell-exceptions.html) on how to view Lambda function invocation errors for the PowerShell runtime using the Lambda console and the AWS CLI. 172 | 173 | ### Provided Runtime options 174 | 175 | The runtime supports both the `provided.al2` and `provided.al2023` Lambda runtimes. 176 | 177 | #### provided.al2023 178 | 179 | To work as expected in the `provided.al2023` runtime, the environment variable `DOTNET_SYSTEM_GLOBALIZATION_INVARIANT` must be set to `1`. This is to prevent the need for installing the `libicu` package. If this is an issue for your environment, either continue using `provided.al2`, or open an issue in this GitHub repository. 180 | 181 | If this environment variable is not configured, the following error will likely be shown the your function logs. The error includes a link to a [Microsoft documentation page](https://aka.ms/dotnet-missing-libicu) for more information. 182 | 183 | ```text 184 | Process terminated. Couldn't find a valid ICU package installed on the system. Please install libicu (or icu-libs) using your package manager and try again. Alternatively you can set the configuration flag System.Globalization.Invariant to true if you want to run with no globalization support. Please see https://aka.ms/dotnet-missing-libicu for more information. 185 | at System.Environment.FailFast(System.String) 186 | at System.Globalization.GlobalizationMode+Settings..cctor() 187 | at System.Globalization.CultureData.CreateCultureWithInvariantData() 188 | at System.Globalization.CultureData.get_Invariant() 189 | at System.Globalization.CultureInfo..cctor() 190 | at System.Globalization.CultureInfo.get_CurrentUICulture() 191 | at Microsoft.PowerShell.UnmanagedPSEntry.Start(System.String[], Int32) 192 | at Microsoft.PowerShell.ManagedPSEntry.Main(System.String[]) 193 | ``` 194 | -------------------------------------------------------------------------------- /powershell-runtime/source/Makefile: -------------------------------------------------------------------------------- 1 | # PWSH_VERSION is version of PowerShell to download 2 | PWSH_VERSION ?= 7.4.5 3 | # PWSH_ARCHITECTURE can be 'x64' or 'arm64' 4 | PWSH_ARCHITECTURE ?= x64 5 | build-PwshRuntimeLayer: 6 | # Download and extract PowerShell binaries. Remove downloaded file 7 | curl -L -o $(ARTIFACTS_DIR)/powershell-$(PWSH_VERSION)-$(PWSH_ARCHITECTURE).tar.gz https://github.com/PowerShell/PowerShell/releases/download/v$(PWSH_VERSION)/powershell-$(PWSH_VERSION)-linux-$(PWSH_ARCHITECTURE).tar.gz 8 | mkdir -p $(ARTIFACTS_DIR)/powershell 9 | tar zxf $(ARTIFACTS_DIR)/powershell-$(PWSH_VERSION)-$(PWSH_ARCHITECTURE).tar.gz -C $(ARTIFACTS_DIR)/powershell/ 10 | rm $(ARTIFACTS_DIR)/powershell-$(PWSH_VERSION)-$(PWSH_ARCHITECTURE).tar.gz 11 | # Make PowerShell binary executable 12 | chmod +x $(ARTIFACTS_DIR)/powershell/pwsh 13 | 14 | # Copy additional runtime files, including bootstrap. Remove Makefile from destination 15 | cp bootstrap $(ARTIFACTS_DIR) 16 | cp PowerShellLambdaContext.cs $(ARTIFACTS_DIR) 17 | mkdir $(ARTIFACTS_DIR)/modules 18 | cp -R ./modules/* $(ARTIFACTS_DIR)/modules/ 19 | 20 | # Merge all Private module content into a single .psm1 file to speed up module loading 21 | cd $(ARTIFACTS_DIR)/modules/Private 22 | tail -n +3 -q $(ARTIFACTS_DIR)/modules/Private/*.ps1 >> $(ARTIFACTS_DIR)/modules/pwsh-runtime.psm1 23 | rm -Rf $(ARTIFACTS_DIR)/modules/Private 24 | 25 | # Make bootstrap script executable 26 | chmod +x $(ARTIFACTS_DIR)/bootstrap -------------------------------------------------------------------------------- /powershell-runtime/source/PowerShellLambdaContext.cs: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * *****************************************************************************/ 16 | 17 | namespace Amazon.Lambda.PowerShell.Internal 18 | { 19 | using System; 20 | 21 | /// 22 | /// $LambdaContext object that allows you to access useful information available within the Lambda execution environment. 23 | /// 24 | public class LambdaContext 25 | { 26 | /// 27 | /// The AWS request ID associated with the request. 28 | /// This is the same ID returned to the client that called invoke(). 29 | /// This ID is reused for retries on the same request. 30 | /// 31 | public string AwsRequestId { get; } 32 | 33 | /// 34 | /// Information about the client application and device when invoked 35 | /// through the AWS Mobile SDK. It can be null. 36 | /// Client context provides client information such as client ID, 37 | /// application title, version name, version code, and the application 38 | /// package name. 39 | /// 40 | public string ClientContext { get; } 41 | 42 | /// 43 | /// Name of the Lambda function that is running. 44 | /// 45 | public string FunctionName { get; } 46 | 47 | /// 48 | /// The Lambda function version that is executing. 49 | /// If an alias is used to invoke the function, then will be 50 | /// the version the alias points to. 51 | /// 52 | public string FunctionVersion { get; } 53 | 54 | /// 55 | /// Information about the Amazon Cognito identity provider when 56 | /// invoked through the AWS Mobile SDK. 57 | /// Can be null. 58 | /// 59 | public string Identity { get; } 60 | /// ICognitoIdentity Identity { get; set; } 61 | 62 | /// 63 | /// The ARN used to invoke this function. 64 | /// It can be function ARN or alias ARN. 65 | /// An unqualified ARN executes the $LATEST version and aliases execute 66 | /// the function version they are pointing to. 67 | /// 68 | public string InvokedFunctionArn { get; } 69 | 70 | /// 71 | /// The CloudWatch log group name associated with the invoked function. 72 | /// It can be null if the IAM user provided does not have permission for 73 | /// CloudWatch actions. 74 | /// 75 | public string LogGroupName { get; } 76 | 77 | /// 78 | /// The CloudWatch log stream name for this function execution. 79 | /// It can be null if the IAM user provided does not have permission 80 | /// for CloudWatch actions. 81 | /// 82 | public string LogStreamName { get; } 83 | 84 | /// 85 | /// Memory limit, in MB, you configured for the Lambda function. 86 | /// 87 | public int MemoryLimitInMB { get; } 88 | 89 | /// 90 | /// Memory limit, in MB, you configured for the Lambda function. 91 | /// 92 | private DateTime _deadlineMS { get; } 93 | 94 | public LambdaContext( 95 | string FunctionName, 96 | string FunctionVersion, 97 | string InvokedFunctionArn, 98 | int MemoryLimitInMB, 99 | string AwsRequestId, 100 | string LogGroupName, 101 | string LogStreamName, 102 | string Identity, 103 | string ClientContext, 104 | double DeadlineMS 105 | ) 106 | { 107 | this.FunctionName = FunctionName; 108 | this.FunctionVersion = FunctionVersion; 109 | this.InvokedFunctionArn = FunctionName; 110 | this.MemoryLimitInMB = MemoryLimitInMB; 111 | this.AwsRequestId = AwsRequestId; 112 | this.LogGroupName = LogGroupName; 113 | this.LogStreamName = LogStreamName; 114 | this.Identity = Identity; 115 | this.ClientContext = ClientContext; 116 | 117 | DateTime epoch = new DateTime(1970, 1, 1); 118 | this._deadlineMS = epoch.AddMilliseconds(DeadlineMS); 119 | 120 | } 121 | 122 | /// 123 | /// Remaining execution time till the function will be terminated. 124 | /// At the time you create the Lambda function you set maximum time 125 | /// limit, at which time AWS Lambda will terminate the function 126 | /// execution. 127 | /// Information about the remaining time of function execution can be 128 | /// used to specify function behavior when nearing the timeout. 129 | /// 130 | public TimeSpan RemainingTime 131 | { 132 | get => this._deadlineMS - DateTime.UtcNow; 133 | } 134 | /// 135 | /// Remaining execution time in Milliseconds until the function will be terminated. 136 | /// At the time you create the Lambda function you set maximum time 137 | /// limit, at which time AWS Lambda will terminate the function 138 | /// execution. 139 | /// Information about the remaining time of function execution can be 140 | /// used to specify function behavior when nearing the timeout. 141 | /// 142 | public Double GetRemainingTimeInMillis() 143 | { 144 | return Math.Round((this._deadlineMS - DateTime.UtcNow).TotalMilliseconds); 145 | } 146 | } 147 | } -------------------------------------------------------------------------------- /powershell-runtime/source/bootstrap: -------------------------------------------------------------------------------- 1 | #!/opt/powershell/pwsh -noprofile 2 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | # SPDX-License-Identifier: Apache 2.0 4 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') {$VerbosePreference = 'continue'} 5 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') {Write-Host '[RUNTIME-bootstrap]Start: bootstrap'} 6 | ## Initiating custom runtime 7 | 8 | # Set PowerShell version environment 9 | $env:POWERSHELL_VERSION = ($PSVersionTable).PSVersion.ToString() 10 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') {Write-Host "[RUNTIME-bootstrap]Running PowerShell: $($env:POWERSHELL_VERSION)"} 11 | 12 | # Importing runtime module helpers 13 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') {Write-Host '[RUNTIME-bootstrap]Importing runtime module helpers'} 14 | Import-Module '/opt/modules/pwsh-runtime.psd1' 15 | 16 | # Importing .NET class from .cs file to support the script property "RemainingTime" and method "getRemainingTimeInMillis". 17 | # This is taken from the Lambda .Net runtime LambdaContext code: https://github.com/aws/aws-lambda-dotnet/blob/master/Libraries/src/Amazon.Lambda.Core/ILambdaContext.cs 18 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host '[RUNTIME-bootstrap]Importing .NET class from .cs file to support script properties and method' } 19 | Add-Type -TypeDefinition ([System.IO.File]::ReadAllText('/opt/PowerShellLambdaContext.cs')) 20 | 21 | # Modify $env:PSModulePath to support Lambda paths 22 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') {Write-Host '[RUNTIME-bootstrap]Modify PSModulePath to support Lambda paths'} 23 | Set-PSModulePath 24 | 25 | # Parse _HANDLER environment variable 26 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') {Write-Host '[RUNTIME-bootstrap]Parse _HANDLER environment variable'} 27 | $private:handlerArray = Get-Handler -Handler $env:_HANDLER 28 | 29 | ## Initiating function 30 | # Run function/module pre-handler initialization in global scope 31 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') {Write-Host '[RUNTIME-bootstrap]Run function/module pre-handler initialization in global scope'} 32 | switch ($private:handlerArray.handlerType) { 33 | 'Function' { 34 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') {Write-Host "[RUNTIME-bootstrap]Dot sourcing PowerShell script: $($private:handlerArray.scriptFilePath)"} 35 | . $private:handlerArray.ScriptFilePath 36 | } 37 | 'Module' { 38 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') {Write-Host "[RUNTIME-bootstrap]Importing module: $($private:handlerArray.moduleName)"} 39 | Import-Module -Name $private:handlerArray.moduleName -Force 40 | } 41 | } 42 | 43 | $private:httpClient = [System.Net.Http.HttpClient]::new() 44 | $private:httpClient.Timeout = [System.Threading.Timeout]::InfiniteTimeSpan 45 | 46 | ## Event loop 47 | # Processes invocation events from Lambda Runtime API in a loop until runtime environment is terminated. 48 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') {Write-Host '[RUNTIME-bootstrap]Start event loop'} 49 | do { 50 | # Get /NEXT invocation from AWS Lambda Runtime API. 51 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') {Write-Host '[RUNTIME-bootstrap]Get /NEXT invocation from AWS Lambda Runtime API'} 52 | $private:runtimeNextInvocationResponse = Get-LambdaNextInvocation $private:httpClient 53 | 54 | # Set default and AWS Lambda specific environment variables for each invocation 55 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') {Write-Host '[RUNTIME-bootstrap]Set default and AWS Lambda specific environment variables for each invocation'} 56 | Set-HandlerEnvironmentVariables $private:runtimeNextInvocationResponse.headers 57 | 58 | # Create the $LambdaContext object 59 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') {Write-Host '[RUNTIME-bootstrap]Create the $LambdaContext object'} 60 | $private:LambdaContext = Set-LambdaContext 61 | 62 | try { 63 | # Run function handler from script/module 64 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') {Write-Host '[RUNTIME-bootstrap]Run function handler from script/module'} 65 | $private:InvocationResponse = Invoke-FunctionHandler $private:runtimeNextInvocationResponse $private:handlerArray $private:LambdaContext 66 | 67 | # POST function handler response back to Runtime API 68 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') {Write-Host '[RUNTIME-bootstrap]POST function handler response back to Runtime API'} 69 | 70 | Send-FunctionHandlerResponse $private:httpClient $private:InvocationResponse 71 | } 72 | catch { 73 | # POST function invocation error back to Runtime API 74 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') {Write-Host '[RUNTIME-bootstrap]POST function invocation error back to Runtime API'} 75 | Send-FunctionHandlerError $private:httpClient $_ 76 | } 77 | 78 | # Cleanup 79 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') {Write-Host '[RUNTIME-bootstrap]Cleanup'} 80 | Remove-Variable -Name 'LambdaInput', 'LambdaContext', 'private:LambdaContext', 'private:runtimeNextInvocationResponse', 'private:InvocationResponse' -ErrorAction 'SilentlyContinue' 81 | $env:_X_AMZN_TRACE_ID = '' 82 | } 83 | while ($true) 84 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') {Write-Host '[RUNTIME-bootstrap]Complete event loop, spindown runtime environment'} 85 | -------------------------------------------------------------------------------- /powershell-runtime/source/modules/Private/Get-Handler.ps1: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | function private:Get-Handler { 5 | <# 6 | .SYNOPSIS 7 | Parse _HANDLER environment variable. 8 | 9 | .DESCRIPTION 10 | Parse _HANDLER environment variable. 11 | 12 | .Notes 13 | Valid "_HANDLER" options: 14 | - "" 15 | - "::" 16 | - "Module::::" 17 | #> 18 | [CmdletBinding()] 19 | param ( 20 | [String]$handler = $env:_HANDLER 21 | ) 22 | 23 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host '[RUNTIME-Get-Handler]Start: Get-Handler' } 24 | 25 | enum HandlerType { 26 | Script 27 | Function 28 | Module 29 | } 30 | 31 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host '[RUNTIME-Get-Handler]Split _HANDLER environment variable' } 32 | $private:handlerArray = $handler.Split('::') 33 | 34 | if ($private:handlerArray[0] -like '*.ps1' -and $private:handlerArray.Count -eq 1) { 35 | # Handler contains only a script file 36 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host '[RUNTIME-Get-Handler]Handler contains only a script file' } 37 | 38 | $private:handlerObject = @{ 39 | handlerType = [HandlerType]::Script 40 | scriptFileName = $private:handlerArray[0] 41 | scriptFilePath = [System.IO.Path]::Combine($env:LAMBDA_TASK_ROOT, $private:handlerArray[0]) 42 | } 43 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host "[RUNTIME-Get-Handler]Handler type set to: $($private:handlerObject.handlerType)" } 44 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host "[RUNTIME-Get-Handler]Handler set to PowerShell script name: $($private:handlerObject.scriptFileName)" } 45 | } 46 | 47 | elseif ($private:handlerArray[0] -like '*.ps1' -and $private:handlerArray.Count -eq 2) { 48 | # Handler contains a script file and handler function name 49 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host '[RUNTIME-Get-Handler]Handler contains a script file and handler function name' } 50 | 51 | $private:handlerObject = @{ 52 | handlerType = [HandlerType]::Function 53 | scriptFileName = $private:handlerArray[0] 54 | scriptFilePath = [System.IO.Path]::Combine($env:LAMBDA_TASK_ROOT, $private:handlerArray[0]) 55 | functionName = $private:handlerArray[1] 56 | } 57 | 58 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host "[RUNTIME-Get-Handler]Handler type set to: $($private:handlerObject.handlerType)" } 59 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host "[RUNTIME-Get-Handler]Script file set to PowerShell script name: $($private:handlerObject.scriptFileName)" } 60 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host "[RUNTIME-Get-Handler]Handler set to PowerShell function: $($private:handlerObject.functionName)" } 61 | 62 | } 63 | elseif ($private:handlerArray[0] -eq 'Module' -and $private:handlerArray.Count -eq 3) { 64 | # Handler contains a module name and handler function name 65 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host '[RUNTIME-Get-Handler]Handler contains a module name and handler function name' } 66 | 67 | $private:handlerObject = @{ 68 | handlerType = [HandlerType]::Module 69 | moduleName = $private:handlerArray[1] 70 | functionName = $private:handlerArray[2] 71 | } 72 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host "[RUNTIME-Get-Handler]Handler type set to: $($private:handlerObject.handlerType)" } 73 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host "[RUNTIME-Get-Handler]Module name set to PowerShell module: $($private:handlerObject.moduleName)" } 74 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host "[RUNTIME-Get-Handler]Handler set to PowerShell function: $($private:handlerObject.functionName)" } 75 | 76 | } 77 | # Unable to parse Handler object 78 | else { 79 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host '[RUNTIME-Get-Handler]Unable to parse Handler object' } 80 | throw ('Invalid Lambda Handler: {0}' -f $handler) 81 | } 82 | 83 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host '[RUNTIME-Get-Handler]Return handlerObject' } 84 | return [pscustomobject]$private:handlerObject 85 | } 86 | -------------------------------------------------------------------------------- /powershell-runtime/source/modules/Private/Get-LambdaNextInvocation.ps1: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | function private:Get-LambdaNextInvocation { 5 | <# 6 | .SYNOPSIS 7 | Get /NEXT invocation from AWS Lambda Runtime API. 8 | 9 | .DESCRIPTION 10 | Get /NEXT invocation from AWS Lambda Runtime API. 11 | 12 | .Notes 13 | If there is an error calling the Runtime API endpoint, this is ignored and retried as part of the event loop. 14 | #> 15 | param ( 16 | [Parameter(Position=0)] 17 | [System.Net.Http.HttpClient]$private:HttpClient 18 | ) 19 | 20 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host '[RUNTIME-Get-LambdaNextInvocation]Start: Get-LambdaNextInvocation' } 21 | 22 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host '[RUNTIME-Get-LambdaNextInvocation]Create GET request to Runtime API' } 23 | 24 | $private:request = [System.Net.Http.HttpRequestMessage]::new() 25 | $private:request.Headers.Add('User-Agent', "aws-lambda-powershell/$env:POWERSHELL_VERSION") 26 | $private:request.Method = 'GET' 27 | $private:request.RequestUri = "http://$env:AWS_LAMBDA_RUNTIME_API/2018-06-01/runtime/invocation/next" 28 | 29 | try { 30 | # Get the next invocation 31 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host '[RUNTIME-Get-LambdaNextInvocation]Get the next invocation' } 32 | $private:response = $private:HttpClient.SendAsync($private:request).GetAwaiter().GetResult() 33 | } 34 | catch { 35 | # If there is an error calling the Runtime API endpoint, ignore which tries again 36 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host "[RUNTIME-Get-LambdaNextInvocation]Exception caught: $($_.Exception.Message)" } 37 | continue 38 | } 39 | 40 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host '[RUNTIME-Get-LambdaNextInvocation]Read the response content' } 41 | $private:incomingEvent = $private:response.Content.ReadAsStringAsync().GetAwaiter().GetResult() 42 | 43 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host '[RUNTIME-Get-LambdaNextInvocation]Generate the correct response headers' } 44 | $private:incomingHeaders = @{} 45 | foreach ($private:header in $private:response.Headers) { 46 | $private:incomingHeaders[$private:header.Key] = $private:header.Value 47 | } 48 | 49 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host '[RUNTIME-Get-LambdaNextInvocation]Create a response object' } 50 | $private:NextInvocationResponseObject = [pscustomobject]@{ 51 | headers = $private:incomingHeaders 52 | incomingEvent = $private:incomingEvent 53 | } 54 | 55 | if ($private:response) { $private:response.Dispose() } 56 | if ($private:responseStream) { $private:responseStream.Dispose() } 57 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host '[RUNTIME-Get-LambdaNextInvocation]Return response object' } 58 | return [pscustomobject]$private:NextInvocationResponseObject 59 | } 60 | -------------------------------------------------------------------------------- /powershell-runtime/source/modules/Private/Invoke-FunctionHandler.ps1: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | function private:Invoke-FunctionHandler { 5 | <# 6 | .SYNOPSIS 7 | Invoke Lambda handler function. 8 | 9 | .DESCRIPTION 10 | Invoke Lambda handler function. 11 | 12 | .Notes 13 | Runs entire script if handler isthe script, or function from script/module. 14 | #> 15 | [CmdletBinding()] 16 | param ( 17 | [Parameter(Mandatory)] $private:runtimeNextInvocationResponse, 18 | [Parameter(Mandatory)] $private:HandlerArray, 19 | [Parameter(Mandatory)] $private:LambdaContext 20 | ) 21 | 22 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host '[RUNTIME-Invoke-FunctionHandler]Start: Invoke-FunctionHandler' } 23 | 24 | $private:LambdaInput = ConvertFrom-Json -InputObject $private:runtimeNextInvocationResponse.incomingEvent 25 | switch ($private:HandlerArray.handlerType) { 26 | 'Module' { 27 | $private:functionInvocationResponse = & $private:handlerArray.functionName $private:LambdaInput $private:LambdaContext 28 | } 29 | 'Function' { 30 | $private:functionInvocationResponse = & $private:handlerArray.functionName $private:LambdaInput $private:LambdaContext 31 | } 32 | 'Script' { 33 | $private:functionInvocationResponse = & $private:handlerArray.scriptFilePath $private:LambdaInput $private:LambdaContext 34 | } 35 | } 36 | 37 | # Convert function response to a string if needed 38 | if ($private:functionInvocationResponse -and ($private:functionInvocationResponse.GetType().Name -ne 'String')) { 39 | $private:responseString = ConvertTo-Json -InputObject $private:functionInvocationResponse -Compress 40 | } 41 | else { 42 | $private:responseString = $private:functionInvocationResponse 43 | 44 | } 45 | 46 | return $private:responseString 47 | } 48 | -------------------------------------------------------------------------------- /powershell-runtime/source/modules/Private/Send-FunctionHandlerError.ps1: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | function private:Send-FunctionHandlerError { 5 | <# 6 | .SYNOPSIS 7 | POST function invocation error back to Runtime API. 8 | 9 | .DESCRIPTION 10 | POST function invocation error back to Runtime API. 11 | 12 | .Notes 13 | 14 | #> 15 | [CmdletBinding()] 16 | param ( 17 | [Parameter(Position=0)] 18 | [System.Net.Http.HttpClient]$private:HttpClient, 19 | 20 | [Parameter(Mandatory, Position=1)] 21 | $private:Exception 22 | ) 23 | 24 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host '[RUNTIME-Send-FunctionHandlerError]Start: Send-FunctionHandlerError' } 25 | Write-Host $private:Exception 26 | 27 | $private:uri = "http://$env:AWS_LAMBDA_RUNTIME_API/2018-06-01/runtime/invocation/$env:AWS_LAMBDA_RUNTIME_AWS_REQUEST_ID/error" 28 | $private:body = ConvertTo-Json -Compress -InputObject @{ 29 | errorMessage = $private:Exception.Exception.Message 30 | errorType = $private:Exception.CategoryInfo.Reason 31 | } 32 | $private:headers = @(@{ 33 | Key = 'Lambda-Runtime-Function-Error-Type' 34 | Value = '{0}.{1}' -f $private:Exception.CategoryInfo.Category, $private:Exception.CategoryInfo.Reason 35 | }) 36 | _SendRuntimeApiRequest $private:HttpClient $private:uri $private:body $private:headers 37 | } 38 | -------------------------------------------------------------------------------- /powershell-runtime/source/modules/Private/Send-FunctionHandlerResponse.ps1: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | function private:Send-FunctionHandlerResponse { 5 | <# 6 | .SYNOPSIS 7 | POST function response back to Runtime API. 8 | 9 | .DESCRIPTION 10 | POST function response back to Runtime API. 11 | 12 | .Notes 13 | 14 | #> 15 | [CmdletBinding()] 16 | param ( 17 | [Parameter(Position=0)] 18 | [System.Net.Http.HttpClient]$private:HttpClient, 19 | 20 | [Parameter(Position=1)] 21 | $private:InvocationResponse 22 | ) 23 | 24 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host '[RUNTIME-Send-FunctionHandlerResponse]Start: Send-FunctionHandlerResponse' } 25 | $private:uri = "http://$env:AWS_LAMBDA_RUNTIME_API/2018-06-01/runtime/invocation/$env:AWS_LAMBDA_RUNTIME_AWS_REQUEST_ID/response" 26 | 27 | _SendRuntimeApiRequest $private:HttpClient $private:uri $private:InvocationResponse 28 | } 29 | -------------------------------------------------------------------------------- /powershell-runtime/source/modules/Private/Set-HandlerEnvironmentVariables.ps1: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | function private:Set-HandlerEnvironmentVariables { 5 | <# 6 | .SYNOPSIS 7 | Set default and AWS Lambda specific environment variables for each invocation. 8 | 9 | .DESCRIPTION 10 | Set default and AWS Lambda specific environment variables for each invocation. 11 | 12 | .Notes 13 | 14 | #> 15 | [CmdletBinding()] 16 | param ( 17 | [Parameter(Mandatory)] $Headers 18 | ) 19 | 20 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host '[RUNTIME-Set-HandlerEnvironmentVariables]Start: Set-HandlerEnvironmentVariables' } 21 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host "[RUNTIME-Set-HandlerEnvironmentVariables]Received Headers: $($Headers)" } 22 | 23 | # Set default TEMP environment variables for each invocation to ensure they're "clean" for each handler invocation 24 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host '[RUNTIME-Set-HandlerEnvironmentVariables]Set default TEMP environment variables' } 25 | $env:TEMP = '/tmp' 26 | $env:TMP = '/tmp' 27 | $env:TMPDIR = '/tmp' 28 | 29 | # Set AWS Lambda specific environment variables 30 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host '[RUNTIME-Set-HandlerEnvironmentVariables]Set AWS Lambda specific environment variables' } 31 | $env:AWS_LAMBDA_RUNTIME_AWS_REQUEST_ID = $Headers['Lambda-Runtime-Aws-Request-Id'] 32 | $env:AWS_LAMBDA_RUNTIME_CLIENT_CONTEXT = $Headers['Lambda-Runtime-Client-Context'] 33 | $env:AWS_LAMBDA_RUNTIME_COGNITO_IDENTITY = $Headers['Lambda-Runtime-Cognito-Identity'] 34 | $env:AWS_LAMBDA_RUNTIME_DEADLINE_MS = $Headers['Lambda-Runtime-Deadline-Ms'] 35 | $env:AWS_LAMBDA_RUNTIME_INVOKED_FUNCTION_ARN = $Headers['Lambda-Runtime-Invoked-Function-Arn'] 36 | $env:_X_AMZN_TRACE_ID = $Headers['Lambda-Runtime-Trace-Id'] 37 | } 38 | -------------------------------------------------------------------------------- /powershell-runtime/source/modules/Private/Set-LambdaContext.ps1: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | function Private:Set-LambdaContext { 5 | <# 6 | .SYNOPSIS 7 | Captures the content of the provided Lambda Context variable. 8 | 9 | .DESCRIPTION 10 | Captures the content of the provided Lambda Context variable. 11 | #> 12 | 13 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host '[RUNTIME-Set-LambdaContext]Start: Set-LambdaContext' } 14 | 15 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host '[RUNTIME-Set-LambdaContext]Creating LambdaContext' } 16 | $private:LambdaContext = [Amazon.Lambda.PowerShell.Internal.LambdaContext]::new( 17 | $env:AWS_LAMBDA_FUNCTION_NAME, 18 | $env:AWS_LAMBDA_FUNCTION_VERSION, 19 | $env:AWS_LAMBDA_RUNTIME_INVOKE_FUNCTION_ARN, 20 | [int]$env:AWS_LAMBDA_FUNCTION_MEMORY_SIZE, 21 | $env:AWS_LAMBDA_RUNTIME_AWS_REQUEST_ID, 22 | $env:AWS_LAMBDA_LOG_GROUP_NAME, 23 | $env:AWS_LAMBDA_LOG_STREAM_NAME, 24 | $env:AWS_LAMBDA_RUNTIME_COGNITO_IDENTITY, 25 | $env:AWS_LAMBDA_RUNTIME_CLIENT_CONTEXT, 26 | [double]$env:AWS_LAMBDA_RUNTIME_DEADLINE_MS 27 | ) 28 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host "[RUNTIME-Set-LambdaContext]Return LambdaContext: $(ConvertTo-Json -InputObject $private:LambdaContext -Compress)" } 29 | return $private:LambdaContext 30 | } 31 | -------------------------------------------------------------------------------- /powershell-runtime/source/modules/Private/Set-PSModulePath.ps1: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | function private:Set-PSModulePath { 5 | <# 6 | .SYNOPSIS 7 | Modify $env:PSModulePath to support Lambda module file paths. 8 | 9 | .DESCRIPTION 10 | Modify $env:PSModulePath to support Lambda module file paths. 11 | 12 | .Notes 13 | Module folders are added in a specific order: 14 | 1: Modules supplied with pwsh 15 | 2: User supplied modules as part of Lambda Layers 16 | 3: User supplied modules as part of function package 17 | #> 18 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host '[RUNTIME-Set-PSModulePath]Start: Set-PSModulePath' } 19 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host '[RUNTIME-Set-PSModulePath]Setting PSModulePath environment variable' } 20 | $env:PSModulePath = @( 21 | '/opt/powershell/modules', # Modules supplied with pwsh 22 | '/opt/modules', # User supplied modules as part of Lambda Layers 23 | [System.IO.Path]::Combine($env:LAMBDA_TASK_ROOT, 'modules') # User supplied modules as part of function package 24 | ) -join ':' 25 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host "[RUNTIME-Set-PSModulePath]PSModulePath environment variable set to: $($env:PSModulePath)" } 26 | } 27 | -------------------------------------------------------------------------------- /powershell-runtime/source/modules/Private/_SendRuntimeApiPost.ps1: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | function _SendRuntimeApiRequest { 5 | [CmdletBinding()] 6 | param ( 7 | [Parameter(Position=0)] 8 | [System.Net.Http.HttpClient]$private:HttpClient, 9 | 10 | [Parameter(Position=1)] 11 | [string]$private:Uri, 12 | 13 | [Parameter(Position=2)] 14 | [string]$private:Body, 15 | 16 | [Parameter(Position=3)] 17 | [array]$private:Header 18 | ) 19 | 20 | $private:request = [System.Net.Http.HttpRequestMessage]::new() 21 | $private:request.Headers.Add('User-Agent', "aws-lambda-powershell/$env:POWERSHELL_VERSION") 22 | if ($private:Header) { 23 | foreach ($h in $private:Header) { 24 | $private:request.Headers.Add($h.Key, $h.Value) 25 | } 26 | } 27 | $private:request.Method = 'POST' 28 | $private:request.RequestUri = $private:Uri 29 | $private:request.Content = [System.Net.Http.StringContent]::new($private:Body) 30 | 31 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host "[RUNTIME-SendRuntimeApiRequest]Sending request to Runtime API: $(ConvertTO-Json -Compress -InputObject $private:request -Depth 5)" } 32 | 33 | $private:runtimeResponse = $private:HttpClient.SendAsync($private:request).GetAwaiter().GetResult() 34 | $private:runtimeResponseContent = $private:runtimeResponse.Content.ReadAsStringAsync().GetAwaiter().GetResult() 35 | 36 | if ($env:POWERSHELL_RUNTIME_VERBOSE -eq 'TRUE') { Write-Host "[RUNTIME-SendRuntimeApiRequest]Runtime API Response: $private:runtimeResponseContent" } 37 | 38 | if ($private:runtimeResponse) { $private:runtimeResponse.Dispose() } 39 | } -------------------------------------------------------------------------------- /powershell-runtime/source/modules/pwsh-runtime.psd1: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | @{ 5 | 6 | # Script module or binary module file associated with this manifest. 7 | RootModule = 'pwsh-runtime.psm1' 8 | 9 | # Version number of this module. 10 | ModuleVersion = '0.6' 11 | 12 | # Supported PSEditions 13 | CompatiblePSEditions = 'Core' 14 | 15 | # ID used to uniquely identify this module 16 | GUID = 'd8728acd-6b96-4593-99ea-61ef1c7f3b18' 17 | 18 | # Author of this module 19 | Author = 'Amazon.com, Inc' 20 | 21 | # Company or vendor of this module 22 | CompanyName = 'Amazon Web Services' 23 | 24 | # Copyright statement for this module 25 | Copyright = '(c) 2022 Amazon Web Services. All rights reserved.' 26 | 27 | # Description of the functionality provided by this module 28 | Description = 'The PowerShell custom runtime for AWS Lambda makes it even easier easy to run Lambda functions written in PowerShell.' 29 | 30 | # Minimum version of the PowerShell engine required by this module 31 | PowerShellVersion = '6.0' 32 | 33 | # Name of the PowerShell host required by this module 34 | # PowerShellHostName = '' 35 | 36 | # Minimum version of the PowerShell host required by this module 37 | # PowerShellHostVersion = '' 38 | 39 | # Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. 40 | # DotNetFrameworkVersion = '' 41 | 42 | # Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. 43 | # ClrVersion = '' 44 | 45 | # Processor architecture (None, X86, Amd64) required by this module 46 | # ProcessorArchitecture = '' 47 | 48 | # Modules that must be imported into the global environment prior to importing this module 49 | # RequiredModules = @() 50 | 51 | # Assemblies that must be loaded prior to importing this module 52 | # RequiredAssemblies = @() 53 | 54 | # Script files (.ps1) that are run in the caller's environment prior to importing this module. 55 | # ScriptsToProcess = @() 56 | 57 | # Type files (.ps1xml) to be loaded when importing this module 58 | # TypesToProcess = @() 59 | 60 | # Format files (.ps1xml) to be loaded when importing this module 61 | # FormatsToProcess = @() 62 | 63 | # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess 64 | # NestedModules = @() 65 | 66 | # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. 67 | FunctionsToExport = @( 68 | 'Get-Handler' 69 | 'Get-LambdaNextInvocation' 70 | 'Invoke-FunctionHandler' 71 | 'Send-FunctionHandlerResponse' 72 | 'Send-FunctionHandlerError' 73 | 'Set-HandlerEnvironmentVariables' 74 | 'Set-LambdaContext' 75 | 'Set-PSModulePath' 76 | ) 77 | # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. 78 | CmdletsToExport = '' 79 | 80 | # Variables to export from this module 81 | VariablesToExport = '' 82 | 83 | # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. 84 | AliasesToExport = '' 85 | 86 | # DSC resources to export from this module 87 | # DscResourcesToExport = @() 88 | 89 | # List of all modules packaged with this module 90 | # ModuleList = @() 91 | 92 | # List of all files packaged with this module 93 | # FileList = @() 94 | 95 | # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. 96 | PrivateData = @{ 97 | 98 | PSData = @{ 99 | 100 | # Tags applied to this module. These help with module discovery in online galleries. 101 | Tags = 'AWS','Lambda' 102 | 103 | # A URL to the license for this module. 104 | LicenseUri = 'https://github.com/awslabs/aws-lambda-powershell-runtime/blob/main/LICENSE' 105 | 106 | # A URL to the main website for this project. 107 | ProjectUri = 'https://github.com/awslabs/aws-lambda-powershell-runtime' 108 | 109 | # A URL to an icon representing this module. 110 | # IconUri = '' 111 | 112 | # ReleaseNotes of this module 113 | # ReleaseNotes = '' 114 | 115 | # Prerelease string of this module 116 | # Prerelease = '' 117 | 118 | # Flag to indicate whether the module requires explicit user acceptance for install/update/save 119 | # RequireLicenseAcceptance = $false 120 | 121 | # External dependent modules of this module 122 | # ExternalModuleDependencies = @() 123 | 124 | } # End of PSData hashtable 125 | 126 | } # End of PrivateData hashtable 127 | 128 | # HelpInfo URI of this module 129 | # HelpInfoURI = '' 130 | 131 | # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. 132 | # DefaultCommandPrefix = '' 133 | 134 | } 135 | -------------------------------------------------------------------------------- /powershell-runtime/source/modules/pwsh-runtime.psm1: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | Set-PSDebug -Strict 5 | # All Private modules merged into this file during build process to speed up module loading. 6 | -------------------------------------------------------------------------------- /powershell-runtime/template.yml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: '2010-09-09' 2 | Transform: AWS::Serverless-2016-10-31 3 | Description: aws-lambda-powershell-runtime 4 | ########################################################################## 5 | # Globals & Parameters # 6 | ########################################################################## 7 | Resources: 8 | ########################################################################## 9 | # Lambda layers # 10 | ########################################################################## 11 | PwshRuntimeLayer: 12 | Type: AWS::Serverless::LayerVersion 13 | Properties: 14 | Description: Lambda Layer containing PowerShell 15 | ContentUri: ./source 16 | CompatibleRuntimes: 17 | - provided.al2 18 | - provided.al2023 19 | RetentionPolicy: Delete 20 | Metadata: 21 | BuildMethod: makefile 22 | # Optional AWS Systems Manager Parameter Store to store Layer ARN for referencing in further templates. 23 | # PwshRuntimeParameter: 24 | # Type: AWS::SSM::Parameter 25 | # Properties: 26 | # Name: lambda-powershell-runtime-latest-version-arn 27 | # Description: PwshRuntime Layer Name 28 | # Type: String 29 | # Value: !Ref PwshRuntimeLayer 30 | 31 | ########################################################################## 32 | # OUTPUTS # 33 | ########################################################################## 34 | Outputs: 35 | PwshRuntimeLayer: 36 | Value: !Ref PwshRuntimeLayer 37 | Description: PwshRuntimeLayer Layer ARN --------------------------------------------------------------------------------